list_for_each_entry(handler, &input_handler_list, node)的理解

在研究Linux input子系统时,遇到list_for_each_entry宏的使用,该宏用于遍历handler链表。文章解析了在input_register_device()函数中调用此宏的含义,指出它不是函数而是宏定义,且没有分号。通过实例化宏,解释了其作用,帮助新手理解这一常见困惑。虽然未深入讲解container_of等细节,但旨在提供整体理解,避免在学习过程中迷失方向。

近期,作为一个新手在研究input子系统的过程中,发现这么一句话list_for_each_entry(handler, &input_handler_list, node),当时也是在听一些课程,在input_register_device()函数中调用了list_for_each_entry(handler, &input_handler_list, node),说此处为遍历handler链表进行匹配,如下所示。

int input_register_device(struct input_dev *dev)
{
        struct input_handler *handler;
        ...
        //加入链表尾部
	    list_add_tail(&dev->node, &input_dev_list);
	    //遍历handler链表进行匹配
	    list_for_each_entry(handler, &input_handler_list, node)
		    input_attach_handler(dev, handler);
        ...

}

其中卡在了对于下属函数的分析:

list_for_each_entry(handler, &input_handler_list, node)

上述是个函数这句话就是错误的!,所以一开始一直分析不出handler这个局部变量一直没有赋值,那这个传参有什么意义呢?说是对链表进行遍历,然后遍历了一遍赋给handler的是什么呢?最后一个元素?那显然不合理呀!经过层层分析,网上查看blog,在一些小地方恍然大悟!

因为上一句话是一个宏,而且其最后是没有分号的!

那么现在将这个宏

#include "devmgr_dev_ctrl.h" #include "devmgr_global.h" #include "devmgr_config.h" #include "devmgr_dev_api.h" #ifdef CFG_DEVMGR_SLAVER #include "devmgr_ubus_slaver.h" #endif #include "devmgr_decouple.h" extern int __start_model; extern int __stop_model; struct dev_model_list g_models; struct api_info { struct list_head list; char name[256]; int enable; }; struct api_module { struct list_head list; char name[256]; struct api_info api_list; }; static struct api_module* api_module_sch(struct api_module *head, char *name) { if (!head || !name) { return NULL; } struct api_module *entry = NULL; list_for_each_entry(entry, &head->list, list) { if (entry && !strcmp(entry->name, name)) { return entry; } } return NULL; } static struct api_info *api_info_sch(struct api_info *head, char *name) { if (!head || !name) { return NULL; } struct api_info *entry = NULL; list_for_each_entry(entry, &head->list, list) { if (entry && !strcmp(entry->name, name)) { return entry; } } return NULL; } static struct api_info* api_info_creat(char *name, int enable) { if (!name) { return NULL; } struct api_info *p = malloc(sizeof(struct api_info)); if (!p) { return NULL; } memset(p, 0, sizeof(struct api_info)); strncpy(p->name, name, sizeof(p->name) - 1); p->enable = enable; INIT_LIST_HEAD(&p->list); return p; } static void api_info_free(struct api_info *info) { if (!info) { return; } list_del(&info->list); free(info); } static struct api_module* api_module_creat(char *name) { if (!name) { return NULL; } struct api_module *p = malloc(sizeof(struct api_module)); if (!p) { return NULL; } memset(p, 0, sizeof(struct api_module)); strncpy(p->name, name, sizeof(p->name) - 1); INIT_LIST_HEAD(&p->list); INIT_LIST_HEAD(&p->api_list.list); return p; } static void api_module_free(struct api_module *module) { if (!module) { return; } list_del(&module->list); struct api_info *entry, *tmp; list_for_each_entry_safe(entry, tmp, &module->api_list.list, list) { api_info_free(entry); } free(module); } static int _is_same_model(const char *src_model, const char *dst_model) { if (!src_model || !dst_model) { DM_PRINT("param[src_model/dst_model] is null\n"); return 0; } int len = strlen(dst_model); if (!strncmp(src_model, dst_model, len) && (src_model[len] == '\0' || src_model[len] == '(')) { return 1; } return 0; } #ifdef CFG_DEVMGR_MASTER #include "devmgr_dev_list.h" #include "devmgr_ubus_master.h" static int devmgr_master_module_dispatch( struct ubus_app *svr_ubus_app, struct blob_buf* bBuf, struct blob_attr *msg, struct dev_model *model) { struct dev_module *entry = NULL, *mod = NULL; struct blob_attr *cur; int rem, i, j = 0; int wake_up_flag = 0; void *cmd_name; char domain[256] = {}; strncpy(domain, blobmsg_name(msg), sizeof(domain) - 1); struct ubus_app_ext *uapp_ext = container_of(svr_ubus_app, struct ubus_app_ext, uapp); struct dev_node *dev = (struct dev_node *)uapp_ext->arg; blobmsg_for_each_attr(cur, msg, rem) { cmd_name = blobmsg_open_table(bBuf, blobmsg_name(cur)); if (NULL == cmd_name) { continue; } j++; struct dev_model *cur_model = model; while (cur_model) { mod = NULL; list_for_each_entry(entry, &(cur_model->module_list->list), list) { if (!entry || !strcmp(entry->domain, domain)) { mod = entry; break; } } if (!mod) { cur_model = cur_model->inherit; continue; } i = 0; while (mod->hdl[i].cmd_name) { if (!strcmp(mod->hdl[i].cmd_name, blobmsg_name(cur))) { break; } i++; } if (!mod->hdl[i].cmd_name) { cur_model = cur_model->inherit; continue; } break; } if (!cur_model) { common_end(bBuf, COMMON_UNSUPPORTED_API); blobmsg_close_table(bBuf, cmd_name); continue; } if (mod->hdl[i].cmd_name && mod->hdl[i].handler) { if (mod->hdl[i].handler(svr_ubus_app, bBuf, cur) == DEVICE_OK) { if ((mod->hdl[i].cmd_mode & DEVCTL_CMD_W) && 0 == wake_up_flag) { wake_handler_t *hdl = NULL; int type = (mod->hdl[i].cmd_mode >> 16); wake_up_flag = 1; if (mod->hdl[i].wake_up_cb) { hdl = wake_handler_new(mod->hdl[i].wake_up_cb, cur, NULL); } wake_task_new(dev, type, hdl); } } } else { common_end(bBuf, COMMON_UNSUPPORTED_API); } blobmsg_close_table(bBuf, cmd_name); } if (0 == j) { return COMMON_FORMAT_INVALID; } if (mod && wake_up_flag) { devmgr_sub_dev_config_sync(dev, mod->name, mod->domain, mod->config); } /* do not return error code in module domain */ return DEVICE_OK; } int devmgr_master_devctl_api_list(struct blob_attr *in, struct blob_buf *out) { if (!in || !out) { DM_PRINT("param[in/out] is null\n"); return DEVICE_PARAM_ERR; } DEV_MODEL_LIST *entry = NULL; struct ubus_app *uapp = master_ubus_get(); struct blobmsg( blobmsg_string deviceId, ) (arg, in, false); struct dev_node *dev = device_list_search(in); list_for_each_entry(entry, &g_models.list, list) { if (!strcmp("COMMON", entry->model->name)) { continue; } if (!arg.deviceId || (dev && _is_same_model(dev->model, entry->model->name))) { struct blob_buf b = {0}; blobmsg_buf_init(&b); blobmsg_add_string(&b, "model", entry->model->name); if (entry->model->api_list) { entry->model->api_list(uapp, out, b.head); } blob_buf_free(&b); } } return DEVICE_OK; } static int devmgr_master_tapo_module_dispatch( struct ubus_app *svr_ubus_app, struct blob_buf* bBuf, struct blob_attr *msg, const char *method, struct blob_attr *one_request_msg, struct dev_model *model) { struct dev_module *entry = NULL, *mod = NULL; int i = 0; int wake_up_flag = 0; char domain[256] = {}; void* table = NULL; struct dev_model *cur_model = NULL; DEVMGR_DECOUPLE_CONTEXT* ctx = NULL; strncpy(domain, blobmsg_name(msg), sizeof(domain) - 1); struct ubus_app_ext *uapp_ext = container_of(svr_ubus_app, struct ubus_app_ext, uapp); struct dev_node *dev = (struct dev_node *)uapp_ext->arg; if (DEVICE_DS_DECOUPLE_SUPPORT(dev)) { ctx = (DEVMGR_DECOUPLE_CONTEXT*)dev->decoup_cxt; if (ctx->tapo_api_handle_v2) { int ret = 0; blobmsg_add_string(bBuf, "method", method); table = blobmsg_open_table(bBuf, "result"); if (table) { ret = ctx->tapo_api_handle_v2(dev, method, one_request_msg, bBuf); blobmsg_close_table(bBuf, table); switch (ret) { case DEVMGR_DECOUPLE_PARAM_INVALID: case DEVMGR_DECOUPLE_BLOB_TABLE_ADD_FAILED: case DEVMGR_DECOUPLE_LOAD_CONFIG_ERROR: case DEVMGR_DECOUPLE_STATELIST_FORMAT_INVALID: case DEVMGR_DECOUPLE_APILIST_FORMAT_INVALID: ret = COMMON_INTERNAL_ERR; break; case DEVMGR_DECOUPLE_REQUEST_INVALID: ret = COMMON_FORMAT_INVALID; break; case DEVMGR_DECOUPLE_METHOD_NOT_FOUND: DBG_ERR("decoupling version is 2.0, but no handler or not a new ds interface, goto the old flow!"); goto __DS_INTERFACE_V1; default: ret = COMMON_OK; } blobmsg_add_u32(bBuf, "error_code", ret); return DEVICE_OK; } else { common_end(bBuf, COMMON_INTERNAL_ERR); return DEVICE_OK; } } } __DS_INTERFACE_V1: cur_model = model; while (cur_model) { mod = NULL; list_for_each_entry(entry, &(cur_model->module_list->list), list) { if (!entry || !strcmp(entry->domain, domain)) { mod = entry; i = 0; while (mod->hdl[i].cmd_name) { if (!strcmp(mod->hdl[i].cmd_name, method)) { break; } i++; } if (mod->hdl[i].cmd_name) { break; } } } if (!mod) { cur_model = cur_model->inherit; continue; } if (!mod->hdl[i].cmd_name) { cur_model = cur_model->inherit; continue; } break; } if (!cur_model) { common_end(bBuf, COMMON_UNSUPPORTED_API); return DEVICE_OK; } if (mod->hdl[i].cmd_name && mod->hdl[i].handler) { if (mod->hdl[i].handler(svr_ubus_app, bBuf, msg) == DEVICE_OK) { if ((mod->hdl[i].cmd_mode & DEVCTL_CMD_W) && 0 == wake_up_flag) { wake_handler_t *hdl = NULL; int type = (mod->hdl[i].cmd_mode >> 16); wake_up_flag = 1; if (mod->hdl[i].wake_up_cb) { hdl = wake_handler_new(mod->hdl[i].wake_up_cb, msg, NULL); } wake_task_new(dev, type, hdl); } } } else { common_end(bBuf, COMMON_UNSUPPORTED_API); } if (mod && wake_up_flag) { devmgr_sub_dev_config_sync(dev, mod->name, mod->domain, mod->config); } /* do not return error code in module domain */ return DEVICE_OK; } #else int devmgr_slaver_module_dispatch( struct ubus_app *svr_ubus_app, struct blob_buf* bBuf, struct blob_attr *msg, int dispatch_mode) { if (!svr_ubus_app || !bBuf || !msg) { DM_PRINT("param[svr_ubus_app/bBuf/msg] is null\n"); return DEVICE_PARAM_ERR; } struct dev_module *entry, *module = NULL; struct dev_model_list *list_entry = NULL; struct dev_model *cur_model = NULL; list_for_each_entry(list_entry, &g_models.list, list) { if (list_entry && strcmp(list_entry->model->name, "TAPO") && strcmp(list_entry->model->name, "COMMON")) { cur_model = list_entry->model; break; } } int rem; struct blob_attr *cur; blobmsg_for_each_attr(cur, msg, rem) { void *cmd_name = blobmsg_open_table(bBuf, blobmsg_name(cur)); if (NULL == cmd_name) { continue; } int i; while (cur_model) { module = NULL; list_for_each_entry(entry, &(cur_model->module_list->list), list) { if (!entry || !strcmp(entry->domain, blobmsg_name(msg))) { module = entry; break; } } if (!module) { cur_model = cur_model->inherit; continue; } i = 0; while (module->hdl[i].cmd_name) { if (!strcmp(module->hdl[i].cmd_name, blobmsg_name(cur))) { if (dispatch_mode != DISPATCH_MODE_LINKIE || !(module->hdl[i].cmd_mode & DEVCTL_CMD_I)) { break; } } i++; } if (!module->hdl[i].cmd_name) { cur_model = cur_model->inherit; continue; } break; } if (!cur_model) { common_end(bBuf, COMMON_UNSUPPORTED_API); blobmsg_close_table(bBuf, cmd_name); continue; } if (module->hdl[i].cmd_name && module->hdl[i].handler) { module->hdl[i].handler(svr_ubus_app, bBuf, cur); } else { common_end(bBuf, COMMON_UNSUPPORTED_API); } blobmsg_close_table(bBuf, cmd_name); } return DEVICE_OK; } /******************************************************************************* Function : devmgr_slaver_cmd_proc Description : process device control request Input : in @ input data Output : out @ output data Return : DEVICE_OK @ success other @ failed *******************************************************************************/ int devmgr_slaver_cmd_proc(struct blob_attr *in, struct blob_buf *out) { int err = DEVICE_OK; struct blob_attr *cur; int rem; struct ubus_app *uapp = slaver_ubus_get(); blobmsg_for_each_attr(cur, in, rem) { if (BLOBMSG_TYPE_TABLE != blobmsg_type(cur)) { continue; } void *mod_name = blobmsg_open_table(out, blobmsg_name(cur)); if (mod_name) { err = devmgr_slaver_module_dispatch(uapp, out, cur, DISPATCH_MODE_REMOTE_CTRL); common_end(out, err); blobmsg_close_table(out, mod_name); } } return err; } int devmgr_slaver_devctl_api_list(struct blob_attr *in, struct blob_buf *out) { if (!in || !out) { DM_PRINT("param[in/out] is null\n"); return DEVICE_PARAM_ERR; } DEV_MODEL_LIST *entry = NULL; struct ubus_app *uapp = slaver_ubus_get(); list_for_each_entry(entry, &g_models.list, list) { struct blob_buf b = {0}; blobmsg_buf_init(&b); blobmsg_add_string(&b, "model", entry->model->name); if (entry->model->api_list) { entry->model->api_list(uapp, out, b.head); } blob_buf_free(&b); } return DEVICE_OK; } int devmgr_slaver_tapo_cmd_proc(struct blob_attr *in, struct blob_buf *out) { int err = DEVICE_OK; struct blob_attr *cur1 = NULL, *cur2 = NULL; int rem1, rem2; struct ubus_app *uapp = slaver_ubus_get(); void *table = NULL, *table1 = NULL; void *array = NULL; if (!in) { return COMMON_FORMAT_INVALID; } struct blobmsg ( blobmsg_table params, ) (req, in, false); if (!req.params) { return COMMON_FORMAT_INVALID; } struct blobmsg ( blobmsg_array requests, ) (params, req.params, false); if (!params.requests) { return COMMON_FORMAT_INVALID; } blobmsg_add_u32(out, "error_code", 0); table = blobmsg_open_table(out, "result"); if (table) { array = blobmsg_open_array(out, "responses"); if (array) { blobmsg_for_each_attr(cur1, params.requests, rem1) { if (BLOBMSG_TYPE_TABLE != blobmsg_type(cur1)) { continue; } struct blobmsg ( blobmsg_string method, blobmsg_table params ) (req, cur1, false); if (!req.method || !req.params) { continue; } table1 = blobmsg_open_table(out, NULL); if (table1) { blobmsg_for_each_attr(cur2, req.params, rem2) { devmgr_slaver_tapo_module_dispatch(uapp, out, cur2, blobmsg_get_string(req.method), DISPATCH_MODE_REMOTE_CTRL); break; } blobmsg_close_table(out, table1); } } blobmsg_close_array(out, array); } blobmsg_close_table(out, table); } return err; } int devmgr_slaver_tapo_module_dispatch( struct ubus_app *svr_ubus_app, struct blob_buf* bBuf, struct blob_attr *msg, const char *method, int dispatch_mode) { if (!svr_ubus_app || !bBuf || !msg) { DM_PRINT("param[svr_ubus_app/bBuf/msg] is null\n"); return DEVICE_PARAM_ERR; } struct dev_module *entry, *module = NULL; struct dev_model_list *list_entry = NULL; struct dev_model *cur_model = NULL; int i = 0; list_for_each_entry(list_entry, &g_models.list, list) { if (list_entry && strcmp(list_entry->model->name, "TAPO") && strcmp(list_entry->model->name, "COMMON")) { cur_model = list_entry->model; break; } } while (cur_model) { module = NULL; list_for_each_entry(entry, &(cur_model->module_list->list), list) { if (!entry || !strcmp(entry->domain, blobmsg_name(msg))) { module = entry; i = 0; while (module->hdl[i].cmd_name) { if (!strcmp(module->hdl[i].cmd_name, method)) { if (dispatch_mode != DISPATCH_MODE_LINKIE || !(module->hdl[i].cmd_mode & DEVCTL_CMD_I)) { break; } } i++; } if (module->hdl[i].cmd_name) { break; } } } if (!module) { cur_model = cur_model->inherit; continue; } if (!module->hdl[i].cmd_name) { cur_model = cur_model->inherit; continue; } break; } if (!cur_model) { common_end(bBuf, COMMON_UNSUPPORTED_API); return DEVICE_OK; } if (module->hdl[i].cmd_name && module->hdl[i].handler) { module->hdl[i].handler(svr_ubus_app, bBuf, msg); } else { common_end(bBuf, COMMON_UNSUPPORTED_API); } return DEVICE_OK; } struct component_list *devmgr_slaver_component_get() { struct dev_model_list *list_entry = NULL; struct dev_model *cur_model = NULL; list_for_each_entry(list_entry, &g_models.list, list) { if (list_entry && strcmp(list_entry->model->name, "TAPO") && strcmp(list_entry->model->name, "COMMON")) { cur_model = list_entry->model; break; } } if (cur_model) { return cur_model->component; } return NULL; } #endif static int devmgr_module_dispatch( struct ubus_app *svr_ubus_app, struct blob_buf* bBuf, struct blob_attr *msg, struct dev_model *model) { #ifdef CFG_DEVMGR_MASTER return devmgr_master_module_dispatch(svr_ubus_app, bBuf, msg, model); #else return devmgr_slaver_module_dispatch(svr_ubus_app, bBuf, msg, DISPATCH_MODE_LINKIE); #endif } static int devmgr_tapo_module_dispatch( struct ubus_app *svr_ubus_app, struct blob_buf* bBuf, struct blob_attr *msg, const char *method, struct blob_attr *one_request_msg, struct dev_model *model) { #ifdef CFG_DEVMGR_MASTER return devmgr_master_tapo_module_dispatch(svr_ubus_app, bBuf, msg, method, one_request_msg, model); #else return devmgr_slaver_tapo_module_dispatch(svr_ubus_app, bBuf, msg, method, DISPATCH_MODE_LINKIE); #endif } void devmgr_model_list_init() { INIT_LIST_HEAD(&g_models.list); DEVMGR_MODEL_LIST_T *p = (DEVMGR_MODEL_LIST_T *)&__start_model; for (; p < (DEVMGR_MODEL_LIST_T *)&__stop_model; p++) { struct dev_model_list *mod = malloc(sizeof(struct dev_model_list)); if (!mod) { return; } memset(mod, 0, sizeof(struct dev_model_list)); mod->model = p->model; list_add_tail(&mod->list, &g_models.list); if (p->init_proc) { p->init_proc(); } } } struct dev_model_list* devmgr_model_list_get() { return &g_models; } DEV_MODEL* devmgr_model_info_get(const char *model) { DEV_MODEL_LIST *entry; list_for_each_entry(entry, &g_models.list, list) { if (_is_same_model(model, entry->model->name)) { return entry->model; } } return NULL; } int devmgr_cmd_proc( struct ubus_app *svr_ubus_app, struct blob_buf* bBuf, struct blob_attr *msg, struct dev_model *model) { int err = DEVICE_OK; struct blob_attr *cur; int rem, i = 0; struct blobmsg( blobmsg_table request_data ) (arg, msg, false); if (!arg.request_data || !blobmsg_len(arg.request_data)) { return COMMON_FORMAT_INVALID; } void *table = blobmsg_open_table(bBuf, "response_data"); if (table) { blobmsg_for_each_attr(cur, arg.request_data, rem) { if (BLOBMSG_TYPE_TABLE != blobmsg_type(cur)) { continue; } i++; if (!blobmsg_len(cur)) { err = COMMON_FORMAT_INVALID; continue; } void *domain = blobmsg_open_table(bBuf, blobmsg_name(cur)); if (NULL == domain) { err = DEVICE_OTHER_ERR; break; } int ret = devmgr_module_dispatch(svr_ubus_app, bBuf, cur, model); if (COMMON_FORMAT_INVALID == ret) { err = ret; } blobmsg_close_table(bBuf, domain); } blobmsg_close_table(bBuf, table); } if (0 == i) { err = COMMON_FORMAT_INVALID; } return err; } int devmgr_cmd_list( struct ubus_app *svr_ubus_app, struct blob_buf* bBuf, struct blob_attr *msg) { if (!bBuf || !msg) { return -1; } struct dev_module *entry = NULL; const char *model = NULL; struct blobmsg( blobmsg_string model, ) (arg, msg, false); if (arg.model) { model = blobmsg_get_string(arg.model); } if (!model) { return -1; } DEV_MODEL *model_info = devmgr_model_info_get(model); if (!model_info) { return -1; } struct api_module api_mod; memset(&api_mod, 0, sizeof(api_mod)); INIT_LIST_HEAD(&api_mod.list); while (model_info) { list_for_each_entry(entry, &(model_info->module_list->list), list) { if (!entry) { break; } struct api_module *mod = api_module_sch(&api_mod, entry->domain); if (!mod) { mod = api_module_creat(entry->domain); if (mod) { list_add_tail(&mod->list, &api_mod.list); } } if (!mod) { break; } struct cmd_handler *hdl = entry->hdl; while (hdl && hdl->cmd_name) { struct api_info *info = api_info_sch(&mod->api_list, hdl->cmd_name); if (!info) { info = api_info_creat(hdl->cmd_name, hdl->handler ? 1 : 0); if (info) { list_add_tail(&info->list, &mod->api_list.list); } } hdl++; } } model_info = model_info->inherit; } void *t = blobmsg_open_table(bBuf, model); struct api_module *mod_entry = NULL; struct api_module *tmp_entry = NULL; if (t) { list_for_each_entry(mod_entry, &api_mod.list, list) { void *a = NULL; struct api_info *info_entry = NULL; if (mod_entry) { list_for_each_entry(info_entry, &mod_entry->api_list.list, list) { if (info_entry && info_entry->enable) { if (!a) { a = blobmsg_open_array(bBuf, mod_entry->name); } if (a) { blobmsg_add_string(bBuf, NULL, info_entry->name); } } } if (a) { blobmsg_close_array(bBuf, a); } } } blobmsg_close_table(bBuf, t); } mod_entry = NULL; list_for_each_entry_safe(mod_entry, tmp_entry, &api_mod.list, list) { api_module_free(mod_entry); } return 0; } int devmgr_tapo_cmd_multiple_proc( struct ubus_app *svr_ubus_app, struct blob_buf *bBuf, struct blob_attr *msg, struct dev_model *model) { const char *method = NULL; struct blob_attr *cur1, *cur2; int rem1, rem2; void *table1 = NULL, *table2 = NULL, *table3 = NULL; void *array = NULL; struct blobmsg( blobmsg_string method, blobmsg_table params ) (req_data, msg, false); if (!req_data.method || !req_data.params) { return COMMON_FORMAT_INVALID; } method = blobmsg_get_string(req_data.method); if (strcmp(method, "multipleRequest") != 0) { return COMMON_FORMAT_INVALID; } struct blobmsg( blobmsg_array requests ) (params, req_data.params, false); if (!params.requests) { return COMMON_FORMAT_INVALID; } #ifdef CFG_DEVMGR_MASTER table1 = blobmsg_open_table(bBuf, "response_data"); if (table1) { #endif blobmsg_add_u32(bBuf, "error_code", 0); table2 = blobmsg_open_table(bBuf, "result"); if (table2) { array = blobmsg_open_array(bBuf, "responses"); if (array) { blobmsg_for_each_attr(cur1, params.requests, rem1) { if (BLOBMSG_TYPE_TABLE != blobmsg_type(cur1)) { continue; } struct blobmsg ( blobmsg_string method, blobmsg_table params ) (req, cur1, false); if (!req.method || !req.params) { continue; } table3 = blobmsg_open_table(bBuf, NULL); if (table3) { blobmsg_for_each_attr(cur2, req.params, rem2) { devmgr_tapo_module_dispatch(svr_ubus_app, bBuf, cur2, blobmsg_get_string(req.method), cur1, model); break; } blobmsg_close_table(bBuf, table3); } } blobmsg_close_array(bBuf, array); } blobmsg_close_table(bBuf, table2); } #ifdef CFG_DEVMGR_MASTER blobmsg_close_table(bBuf, table1); } #endif return DEVICE_OK; } int devmgr_tapo_cmd_single_proc( struct ubus_app *svr_ubus_app, struct blob_buf *bBuf, struct blob_attr *msg, struct dev_model *model) { struct blob_attr *cur = NULL; int rem; #ifdef CFG_DEVMGR_MASTER void *table1 = NULL; #endif struct blobmsg( blobmsg_string method, blobmsg_table params ) (req_data, msg, false); if (!req_data.method || !req_data.params) { return COMMON_FORMAT_INVALID; } #ifdef CFG_DEVMGR_MASTER table1 = blobmsg_open_table(bBuf, "response_data"); if (table1) { #endif blobmsg_for_each_attr(cur, req_data.params, rem) { devmgr_tapo_module_dispatch(svr_ubus_app, bBuf, cur, blobmsg_get_string(req_data.method), msg, model); break; } #ifdef CFG_DEVMGR_MASTER blobmsg_close_table(bBuf, table1); } #endif return DEVICE_OK; } int devmgr_tapo_cmd_proc( struct ubus_app *svr_ubus_app, struct blob_buf *bBuf, struct blob_attr *msg, struct dev_model *model) { const char *method = NULL; #ifdef CFG_DEVMGR_MASTER struct blobmsg( blobmsg_table request_data ) (arg, msg, false); if (!arg.request_data || !blobmsg_len(arg.request_data)) { return COMMON_FORMAT_INVALID; } msg = arg.request_data; #endif struct blobmsg( blobmsg_string method, blobmsg_table params ) (req_data, msg, false); if (!req_data.method || !req_data.params) { return COMMON_FORMAT_INVALID; } method = blobmsg_get_string(req_data.method); if (strcmp(method, "multipleRequest") == 0) { return devmgr_tapo_cmd_multiple_proc(svr_ubus_app, bBuf, msg, model); } else { return devmgr_tapo_cmd_single_proc(svr_ubus_app, bBuf, msg, model); } } int devmgr_tapo_cmd_list( struct ubus_app *svr_ubus_app, struct blob_buf* bBuf, struct blob_attr *msg) { if (!bBuf || !msg) { return -1; } struct dev_module *entry = NULL; const char *model = NULL; struct blobmsg( blobmsg_string model, ) (arg, msg, false); if (arg.model) { model = blobmsg_get_string(arg.model); } if (!model) { return -1; } DEV_MODEL *model_info = devmgr_model_info_get(model); if (!model_info) { return -1; } struct api_module api_mod; memset(&api_mod, 0, sizeof(api_mod)); INIT_LIST_HEAD(&api_mod.list); while (model_info) { list_for_each_entry(entry, &(model_info->module_list->list), list) { if (!entry) { break; } struct api_module *mod = api_module_sch(&api_mod, entry->domain); if (!mod) { mod = api_module_creat(entry->domain); if (mod) { list_add_tail(&mod->list, &api_mod.list); } } if (!mod) { break; } struct cmd_handler *hdl = entry->hdl; while (hdl && hdl->cmd_name) { struct api_info *info = api_info_sch(&mod->api_list, hdl->cmd_name); if (!info) { info = api_info_creat(hdl->cmd_name, hdl->handler ? 1 : 0); if (info) { list_add_tail(&info->list, &mod->api_list.list); } } hdl++; } } model_info = model_info->inherit; } void *t = blobmsg_open_table(bBuf, model); struct api_module *mod_entry = NULL; struct api_module *tmp_entry = NULL; if (t) { list_for_each_entry(mod_entry, &api_mod.list, list) { void *a = NULL; struct api_info *info_entry = NULL; if (mod_entry) { list_for_each_entry(info_entry, &mod_entry->api_list.list, list) { if (info_entry && info_entry->enable) { if (!a) { a = blobmsg_open_array(bBuf, mod_entry->name); } if (a) { blobmsg_add_string(bBuf, NULL, info_entry->name); } } } if (a) { blobmsg_close_array(bBuf, a); } } } blobmsg_close_table(bBuf, t); } mod_entry = NULL; list_for_each_entry_safe(mod_entry, tmp_entry, &api_mod.list, list) { api_module_free(mod_entry); } return 0; }
09-17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值