#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;
}