diff --git a/misc/services/life_mngr/command.c b/misc/services/life_mngr/command.c new file mode 100644 index 000000000..282ee51b5 --- /dev/null +++ b/misc/services/life_mngr/command.c @@ -0,0 +1,100 @@ +/* + * Copyright (C)2021 Intel Corporation + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "command.h" +#include "log.h" + +#define GEN_CMD_OBJ(cmd_name, cmd_id) \ + {.name = cmd_name, .id = cmd_id, .cmd_handler_mtx = PTHREAD_MUTEX_INITIALIZER} +#define CMD_OBJS \ + GEN_CMD_OBJ(SYNC_CMD, SYNC_ID), \ + GEN_CMD_OBJ(ACK_SYNC, ACKED_SYNC_ID), \ + GEN_CMD_OBJ(REQ_SYS_SHUTDOWN, REQ_SYS_SHUTDOWN_ID), \ + GEN_CMD_OBJ(ACK_REQ_SYS_SHUTDOWN, ACKED_REQ_SYS_SHUTDOWN_ID), \ + GEN_CMD_OBJ(POWEROFF_CMD, POWEROFF_CMD_ID), \ + GEN_CMD_OBJ(ACK_POWEROFF, ACKED_POWEROFF_ID), \ + GEN_CMD_OBJ(ACK_TIMEOUT, ACK_TIMEOUT_ID), \ + GEN_CMD_OBJ(REQ_USER_VM_SHUTDOWN, REQ_USER_VM_SHUTDOWN_ID), \ + GEN_CMD_OBJ(USER_VM_SHUTDOWN, USER_VM_SHUTDOWN_ID),\ + GEN_CMD_OBJ(ACK_USER_VM_SHUTDOWN, ACK_USER_VM_SHUTDOWN_ID),\ + +struct command dm_command_list[CMD_END] = {CMD_OBJS}; + +int dispatch_command_handlers(void *arg, int fd) +{ + struct command *cmd = (struct command *)arg; + struct command_handlers *handler; + unsigned int count = 0U; + int ret = 0; + + if (cmd == NULL) { + LOG_PRINTF("Invalid command, fd=%d\n", fd); + return -EINVAL; + } + LOG_PRINTF("Handle command (%s) in command monitor\n", cmd->name); + LIST_FOREACH(handler, &cmd->cmd_handlers_head, list) { + if (handler->fn) { + ret = handler->fn(handler->arg, fd); + count++; + } + } + LOG_PRINTF("Command handler ret=%d\n", ret); + if (!count) + LOG_PRINTF("No handler for command:%s\r\n", cmd->name); + return 0; +} +struct command *find_command(const char *name) +{ + for (int i = 0; (i < CMD_END) && (name != NULL); i++) { + if (strcmp(dm_command_list[i].name, name) == 0) + return &dm_command_list[i]; + } + return NULL; +} + +int register_command_handler(cmd_handler *fn, void *arg, const char *cmd_name) +{ + struct command *cmd; + struct command_handlers *handler; + + if ((!fn) || (!arg) || (!cmd_name)) { + LOG_PRINTF("%s:Failed to register command_handler\n", __func__); + return -EINVAL; + } + cmd = find_command(cmd_name); + if (cmd == NULL) { + LOG_PRINTF("%s:invalid command name (%s)\r\n", __func__, cmd_name); + return -EINVAL; + } + + handler = calloc(1, sizeof(*handler)); + if (!handler) { + LOG_WRITE("Failed to allocate command handler\r\n"); + return -ENOMEM; + } + + handler->fn = fn; + handler->arg = arg; + + pthread_mutex_lock(&cmd->cmd_handler_mtx); + LIST_INSERT_HEAD(&cmd->cmd_handlers_head, handler, list); + pthread_mutex_unlock(&cmd->cmd_handler_mtx); + + return 0; +} diff --git a/misc/services/life_mngr/command.h b/misc/services/life_mngr/command.h new file mode 100644 index 000000000..d3b6a7a0e --- /dev/null +++ b/misc/services/life_mngr/command.h @@ -0,0 +1,87 @@ +/* + * Copyright (C)2021 Intel Corporation + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef _CMD_H_ +#define _CMD_H_ +#include +#include + + +#define SYNC_CMD "sync" +#define ACK_SYNC "ack_sync" +#define REQ_SYS_SHUTDOWN "req_sys_shutdown" +#define ACK_REQ_SYS_SHUTDOWN "ack_req_sys_shutdown" +#define POWEROFF_CMD "poweroff_cmd" +#define ACK_POWEROFF "ack_poweroff" +#define ACK_TIMEOUT "ack_timeout" +#define REQ_USER_VM_SHUTDOWN "req_user_vm_shutdown" +#define USER_VM_SHUTDOWN "user_vm_shutdown" + +#define ACK_REQ_USER_VM_SHUTDOWN "ack_req_user_vm_shutdown" +#define ACK_USER_VM_SHUTDOWN "ack_user_vm_shutdown" +#define FAIL_CONNECT "fail_connect" +#define USER_VM_DISCONNECT "user_vm_disconnect" +#define S5_REJECTED "system shutdown request is rejected" + +#define SYNC_LEN (sizeof(SYNC_CMD)) + +#define POWEROFF "poweroff" + +#define CMD_NAME_MAX 32U + +enum command_id { + SYNC_ID = 0x0, + ACKED_SYNC_ID, + REQ_SYS_SHUTDOWN_ID, + ACKED_REQ_SYS_SHUTDOWN_ID, + POWEROFF_CMD_ID, + ACKED_POWEROFF_ID, + ACK_TIMEOUT_ID, + REQ_USER_VM_SHUTDOWN_ID, + USER_VM_SHUTDOWN_ID, + ACK_USER_VM_SHUTDOWN_ID, + CMD_END, +}; + +typedef int (cmd_handler)(void *arg, int fd); +struct command_handlers { + void *arg; + cmd_handler *fn; + + LIST_ENTRY(command_handlers) list; +}; + +struct command { + const char name[CMD_NAME_MAX]; /**< command name */ + enum command_id id; /**< command id */ + + /* command handler list */ + LIST_HEAD(cmd_handlers_list, command_handlers) cmd_handlers_head; + pthread_mutex_t cmd_handler_mtx; /**< mutex to protect command handler list */ +}; +/** + * @brief register command handler, other module can use this interface to + * register multiple handler for one command. + * + * @param fn the command handler which will be registered + * @param arg the parameter which will be passed into hanlder + * @param cmd_name the command name + */ +int register_command_handler(cmd_handler *fn, void *arg, const char *cmd_name); +/** + * @brief find a command instance by name + * + * @param name the command name + * @return command instance + */ +struct command *find_command(const char *name); +/** + * @brief dispatch the command and invoke registered handler. + * + * @param arg command instance + * @param fd the file descriptor of the device + * @return the flag indicates the state of command handler execution + */ +int dispatch_command_handlers(void *arg, int fd); +#endif