/** * @file geek_shell.h * @author Letter (NevermindZZT@gmail.com) * @brief letter shell * @version 3.0.0 * @date 2019-12-30 * * @copyright (c) 2020 Letter * */ #ifndef __GEEK_SHELL_H__ #define __GEEK_SHELL_H__ #include "geek_shell_cfg.h" #define SHELL_VERSION "3.1.1" /**< 版本号 */ /** * @brief shell 断言 * * @param expr 表达式 * @param action 断言失败操作 */ #define SHELL_ASSERT(expr, action) \ if (!(expr)) { \ action; \ } #define SHELL_RETURN_ASSERT(expr, action, v) \ if (!(expr)) { \ action v; \ } #if SHELL_USING_LOCK == 1 #define SHELL_LOCK(shell) shell->lock(shell) #define SHELL_UNLOCK(shell) shell->unlock(shell) #else #define SHELL_LOCK(shell) #define SHELL_UNLOCK(shell) #endif /** SHELL_USING_LOCK == 1 */ /** * @brief shell 命令权限 * * @param permission 权限级别 */ #define SHELL_CMD_PERMISSION(permission) \ (permission & 0x000000FF) /** * @brief shell 命令类型 * * @param type 类型 */ #define SHELL_CMD_TYPE(type) \ ((type & 0x0000000F) << 8) /** * @brief 使能命令在未校验密码的情况下使用 */ #define SHELL_CMD_ENABLE_UNCHECKED \ (1 << 12) /** * @brief 禁用返回值打印 */ #define SHELL_CMD_DISABLE_RETURN \ (1 << 13) /** * @brief 只读属性(仅对变量生效) */ #define SHELL_CMD_READ_ONLY \ (1 << 14) /** * @brief 命令参数数量 */ #define SHELL_CMD_PARAM_NUM(num) \ ((num & 0x0000000F)) << 16 #ifndef SHELL_SECTION #if defined(__CC_ARM) || defined(__CLANG_ARM) #define SHELL_SECTION(x) __attribute__((section(x))) #elif defined (__IAR_SYSTEMS_ICC__) #define SHELL_SECTION(x) @ x #elif defined(__GNUC__) #define SHELL_SECTION(x) __attribute__((section(x))) #else #define SHELL_SECTION(x) #endif #endif #ifndef SHELL_USED #if defined(__CC_ARM) || defined(__CLANG_ARM) #define SHELL_USED __attribute__((used)) #elif defined (__IAR_SYSTEMS_ICC__) #define SHELL_USED __root #elif defined(__GNUC__) #define SHELL_USED __attribute__((used)) #else #define SHELL_USED #endif #endif /** * @brief shell float型参数转换 */ #define SHELL_PARAM_FLOAT(x) (*(float *)(&x)) /** * @brief shell 代理函数名 */ #define SHELL_AGENCY_FUNC_NAME(_func) agency##_func /** * @brief shell代理函数定义 * * @param _func 被代理的函数 * @param ... 代理参数 */ #define SHELL_AGENCY_FUNC(_func, ...) \ void SHELL_AGENCY_FUNC_NAME(_func)(int p1, int p2, int p3, int p4, int p5, int p6, int p7) \ { _func(__VA_ARGS__); } #if SHELL_USING_CMD_EXPORT == 1 /** * @brief shell 命令定义 * * @param _attr 命令属性 * @param _name 命令名 * @param _func 命令函数 * @param _desc 命令描述 */ #define SHELL_EXPORT_CMD(_attr, _name, _func, _desc) \ const char shellCmd##_name[] = #_name; \ const char shellDesc##_name[] = #_desc; \ SHELL_USED const ShellCommand \ shellCommand##_name SHELL_SECTION("shellCommand") = \ { \ .attr.value = _attr, \ .data.cmd.name = shellCmd##_name, \ .data.cmd.function = (int (*)())_func, \ .data.cmd.desc = shellDesc##_name \ } /** * @brief shell 代理命令定义 * * @param _attr 命令属性 * @param _name 命令名 * @param _func 命令函数 * @param _desc 命令描述 * @param ... 代理参数 */ #define SHELL_EXPORT_CMD_AGENCY(_attr, _name, _func, _desc, ...) \ SHELL_AGENCY_FUNC(_func, ##__VA_ARGS__) \ SHELL_EXPORT_CMD(_attr, _name, SHELL_AGENCY_FUNC_NAME(_func), _desc) /** * @brief shell 变量定义 * * @param _attr 变量属性 * @param _name 变量名 * @param _value 变量值 * @param _desc 变量描述 */ #define SHELL_EXPORT_VAR(_attr, _name, _value, _desc) \ const char shellCmd##_name[] = #_name; \ const char shellDesc##_name[] = #_desc; \ SHELL_USED const ShellCommand \ shellVar##_name SHELL_SECTION("shellCommand") = \ { \ .attr.value = _attr, \ .data.var.name = shellCmd##_name, \ .data.var.value = (void *)_value, \ .data.var.desc = shellDesc##_name \ } /** * @brief shell 用户定义 * * @param _attr 用户属性 * @param _name 用户名 * @param _password 用户密码 * @param _desc 用户描述 */ #define SHELL_EXPORT_USER(_attr, _name, _password, _desc) \ const char shellCmd##_name[] = #_name; \ const char shellPassword##_name[] = #_password; \ const char shellDesc##_name[] = #_desc; \ SHELL_USED const ShellCommand \ shellUser##_name SHELL_SECTION("shellCommand") = \ { \ .attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_USER), \ .data.user.name = shellCmd##_name, \ .data.user.password = shellPassword##_name, \ .data.user.desc = shellDesc##_name \ } /** * @brief shell 按键定义 * * @param _attr 按键属性 * @param _value 按键键值 * @param _func 按键函数 * @param _desc 按键描述 */ #define SHELL_EXPORT_KEY(_attr, _value, _func, _desc) \ const char shellDesc##_value[] = #_desc; \ SHELL_USED const ShellCommand \ shellKey##_value SHELL_SECTION("shellCommand") = \ { \ .attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_KEY), \ .data.key.value = _value, \ .data.key.function = (void (*)(Shell *))_func, \ .data.key.desc = shellDesc##_value \ } /** * @brief shell 代理按键定义 * * @param _attr 按键属性 * @param _value 按键键值 * @param _func 按键函数 * @param _desc 按键描述 * @param ... 代理参数 */ #define SHELL_EXPORT_KEY_AGENCY(_attr, _value, _func, _desc, ...) \ SHELL_AGENCY_FUNC(_func, ##__VA_ARGS__) \ SHELL_EXPORT_KEY(_attr, _value, SHELL_AGENCY_FUNC_NAME(_func), _desc) #else /** * @brief shell 命令item定义 * * @param _attr 命令属性 * @param _name 命令名 * @param _func 命令函数 * @param _desc 命令描述 */ #define SHELL_CMD_ITEM(_attr, _name, _func, _desc) \ { \ .attr.value = _attr, \ .data.cmd.name = #_name, \ .data.cmd.function = (int (*)())_func, \ .data.cmd.desc = #_desc \ } /** * @brief shell 变量item定义 * * @param _attr 变量属性 * @param _name 变量名 * @param _value 变量值 * @param _desc 变量描述 */ #define SHELL_VAR_ITEM(_attr, _name, _value, _desc) \ { \ .attr.value = _attr, \ .data.var.name = #_name, \ .data.var.value = (void *)_value, \ .data.var.desc = #_desc \ } /** * @brief shell 用户item定义 * * @param _attr 用户属性 * @param _name 用户名 * @param _password 用户密码 * @param _desc 用户描述 */ #define SHELL_USER_ITEM(_attr, _name, _password, _desc) \ { \ .attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_USER), \ .data.user.name = #_name, \ .data.user.password = #_password, \ .data.user.desc = #_desc \ } /** * @brief shell 按键item定义 * * @param _attr 按键属性 * @param _value 按键键值 * @param _func 按键函数 * @param _desc 按键描述 */ #define SHELL_KEY_ITEM(_attr, _value, _func, _desc) \ { \ .attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_KEY), \ .data.key.value = _value, \ .data.key.function = (void (*)(Shell *))_func, \ .data.key.desc = #_desc \ } #define SHELL_EXPORT_CMD(_attr, _name, _func, _desc) #define SHELL_EXPORT_CMD_AGENCY(_attr, _name, _func, _desc, ...) #define SHELL_EXPORT_VAR(_attr, _name, _value, _desc) #define SHELL_EXPORT_USER(_attr, _name, _password, _desc) #define SHELL_EXPORT_KEY(_attr, _value, _func, _desc) #define SHELL_EXPORT_KEY_AGENCY(_attr, _name, _func, _desc, ...) #endif /** SHELL_USING_CMD_EXPORT == 1 */ /** * @brief shell command类型 */ typedef enum { SHELL_TYPE_CMD_MAIN = 0, /**< main形式命令 */ SHELL_TYPE_CMD_FUNC, /**< C函数形式命令 */ SHELL_TYPE_VAR_INT, /**< int型变量 */ SHELL_TYPE_VAR_SHORT, /**< short型变量 */ SHELL_TYPE_VAR_CHAR, /**< char型变量 */ SHELL_TYPE_VAR_STRING, /**< string型变量 */ SHELL_TYPE_VAR_POINT, /**< 指针型变量 */ SHELL_TYPE_VAR_NODE, /**< 节点变量 */ SHELL_TYPE_USER, /**< 用户 */ SHELL_TYPE_KEY, /**< 按键 */ } ShellCommandType; /** * @brief Shell定义 */ typedef struct shell_def { struct { const struct shell_command *user; /**< 当前用户 */ int activeTime; /**< shell激活时间 */ char *path; /**< 当前shell路径 */ #if SHELL_USING_COMPANION == 1 struct shell_companion_object *companions; /**< 伴生对象 */ #endif } info; struct { unsigned short length; /**< 输入数据长度 */ unsigned short cursor; /**< 当前光标位置 */ char *buffer; /**< 输入缓冲 */ char *param[SHELL_PARAMETER_MAX_NUMBER]; /**< 参数 */ unsigned short bufferSize; /**< 输入缓冲大小 */ unsigned short paramCount; /**< 参数数量 */ int keyValue; /**< 输入按键键值 */ } parser; #if SHELL_HISTORY_MAX_NUMBER > 0 struct { char *item[SHELL_HISTORY_MAX_NUMBER]; /**< 历史记录 */ unsigned short number; /**< 历史记录数 */ unsigned short record; /**< 当前记录位置 */ signed short offset; /**< 当前历史记录偏移 */ } history; #endif /** SHELL_HISTORY_MAX_NUMBER > 0 */ struct { void *base; /**< 命令表基址 */ unsigned short count; /**< 命令数量 */ } commandList; struct { unsigned char isChecked : 1; /**< 密码校验通过 */ unsigned char isActive : 1; /**< 当前活动Shell */ unsigned char tabFlag : 1; /**< tab标志 */ } status; signed short (*read)(char *, unsigned short); /**< shell读函数 */ signed short (*write)(char *, unsigned short); /**< shell写函数 */ #if SHELL_USING_LOCK == 1 int (*lock)(struct shell_def *); /**< shell 加锁 */ int (*unlock)(struct shell_def *); /**< shell 解锁 */ #endif } Shell; /** * @brief shell command定义 */ typedef struct shell_command { union { struct { unsigned char permission : 8; /**< command权限 */ ShellCommandType type : 4; /**< command类型 */ unsigned char enableUnchecked : 1; /**< 在未校验密码的情况下可用 */ unsigned char disableReturn : 1; /**< 禁用返回值输出 */ unsigned char readOnly : 1; /**< 只读 */ unsigned char reserve : 1; /**< 保留 */ unsigned char paramNum : 4; /**< 参数数量 */ } attrs; int value; } attr; /**< 属性 */ union { struct { const char *name; /**< 命令名 */ int (*function)(); /**< 命令执行函数 */ const char *desc; /**< 命令描述 */ } cmd; /**< 命令定义 */ struct { const char *name; /**< 变量名 */ void *value; /**< 变量值 */ const char *desc; /**< 变量描述 */ } var; /**< 变量定义 */ struct { const char *name; /**< 用户名 */ const char *password; /**< 用户密码 */ const char *desc; /**< 用户描述 */ } user; /**< 用户定义 */ struct { int value; /**< 按键键值 */ void (*function)(Shell *); /**< 按键执行函数 */ const char *desc; /**< 按键描述 */ } key; /**< 按键定义 */ } data; } ShellCommand; /** * @brief shell节点变量属性 */ typedef struct { void *var; /**< 变量引用 */ int (*get)(); /**< 变量get方法 */ int (*set)(); /**< 变量set方法 */ } ShellNodeVarAttr; #define shellSetPath(_shell, _path) (_shell)->info.path = _path #define shellGetPath(_shell) ((_shell)->info.path) void shellInit(Shell *shell, char *buffer, unsigned short size); unsigned short shellWriteString(Shell *shell, const char *string); void shellPrint(Shell *shell, char *fmt, ...); void shellScan(Shell *shell, char *fmt, ...); Shell* shellGetCurrent(void); void shellHandler(Shell *shell, char data); void shellWriteEndLine(Shell *shell, char *buffer); void shellTask(void *param); int shellRun(Shell *shell, const char *cmd); #if SHELL_USING_COMPANION == 1 /** * @brief shell伴生对象定义 */ typedef struct shell_companion_object { int id; /**< 伴生对象ID */ void *obj; /**< 伴生对象 */ struct shell_companion_object *next; /**< 下一个伴生对象 */ } ShellCompanionObj; signed char shellCompanionAdd(Shell *shell, int id, void *object); signed char shellCompanionDel(Shell *shell, int id); void *shellCompanionGet(Shell *shell, int id); #endif #endif