blob: e0912561fe53653ead65701cda313d0ca8202529 [file] [log] [blame]
/*
* Copyright (c) 2013, 2017, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "shell.h"
#include "shell_io.h"
#include "shell_sw.h"
#include "shell_config.h"
#include "api_access.h"
unsigned long ioctl_buf[IOCTL_BUF_SIZE];
unsigned long ioctl_argp[CMDSTR_ARGS_MAX*4];
void
cmd_print_error(sw_error_t rtn)
{
}
void
cmd_print(char *fmt, ...)
{
}
static sw_error_t
cmd_input_parser(unsigned long *arg_val, a_uint32_t arg_index, sw_api_param_t *pp)
{
a_int16_t i;
unsigned long *pbuf;
a_uint16_t rtn_size = 1;
sw_api_param_t *pptmp = NULL;;
pbuf = ioctl_buf + rtn_size; /*reserve for return value */
for (i = 0; i < arg_index; i++)
{
pptmp = pp + i;
if (pptmp->param_type & SW_PARAM_PTR)
{
pbuf += (pptmp->data_size + 3) / 4;
}
}
if (pptmp == NULL)
return SW_BAD_PTR;
if ((pbuf - ioctl_buf + (pptmp->data_size + 3) / 4) > (IOCTL_BUF_SIZE/4))
{
return SW_NO_RESOURCE;
}
*arg_val = (unsigned long) pbuf;
return SW_OK;
}
static sw_error_t
cmd_api_func(sw_api_func_t *fp, a_uint32_t nr_param, unsigned long * args)
{
unsigned long *p = &args[2];
sw_error_t rv;
switch (nr_param)
{
case 0:
{
sw_error_t(*func) (void);
func = fp->func;
rv = (func) ();
break;
}
case 1:
{
sw_error_t(*func1) (unsigned long);
func1 = fp->func;
rv = (func1) (p[0]);
break;
}
case 2:
{
sw_error_t(*func2) (unsigned long, unsigned long);
func2 = fp->func;
rv = (func2) (p[0], p[1]);
break;
}
case 3:
{
sw_error_t(*func3) (unsigned long, unsigned long, unsigned long);
func3 = fp->func;
rv = (func3) (p[0], p[1], p[2]);
break;
}
case 4:
{
sw_error_t(*func4) (unsigned long, unsigned long, unsigned long, \
unsigned long);
func4 = fp->func;
rv = (func4) (p[0], p[1], p[2], p[3]);
break;
}
case 5:
{
sw_error_t(*func5) (unsigned long, unsigned long, unsigned long, \
unsigned long, unsigned long);
func5 = fp->func;
rv = (func5) (p[0], p[1], p[2], p[3], p[4]);
break;
}
case 6:
{
sw_error_t(*func6) (unsigned long, unsigned long, unsigned long, \
unsigned long, unsigned long, unsigned long);
func6 = fp->func;
rv = (func6) (p[0], p[1], p[2], p[3], p[4], p[5]);
break;
}
case 7:
{
sw_error_t(*func7) (unsigned long, unsigned long, unsigned long, \
unsigned long, unsigned long, unsigned long, unsigned long);
func7 = fp->func;
rv = (func7) (p[0], p[1], p[2], p[3], p[4], p[5], p[6]);
break;
}
case 8:
{
sw_error_t(*func8) (unsigned long, unsigned long, unsigned long, \
unsigned long, unsigned long, unsigned long, unsigned long, \
unsigned long);
func8 = fp->func;
rv = (func8) (p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
break;
}
case 9:
{
sw_error_t(*func9) (unsigned long, unsigned long, unsigned long, \
unsigned long, unsigned long, unsigned long, unsigned long, \
unsigned long, unsigned long);
func9 = fp->func;
rv = (func9) (p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8]);
break;
}
case 10:
{
sw_error_t(*func10) (unsigned long, unsigned long, unsigned long, \
unsigned long, unsigned long, unsigned long, unsigned long, \
unsigned long, unsigned long, unsigned long);
func10 = fp->func;
rv = (func10) (p[0], p[1], p[2], p[3], p[4], p[5],
p[6], p[7], p[8], p[9]);
break;
}
default:
rv = SW_OUT_OF_RANGE;
}
*(unsigned long *) args[1] = rv;
return rv;
}
#if 0
static sw_error_t
cmd_api_output(sw_api_param_t *pp, a_uint32_t nr_param, a_uint32_t * args)
{
a_uint16_t i;
a_uint32_t *pbuf;
a_uint16_t rtn_size = 1;
sw_error_t rtn = (sw_error_t) (*ioctl_buf);
sw_api_param_t *pptmp = NULL;
if (rtn != SW_OK)
{
cmd_print_error(rtn);
return rtn;
}
pbuf = ioctl_buf + rtn_size;
for (i = 0; i < nr_param; i++)
{
pptmp = pp + i;
if (pptmp->param_type & SW_PARAM_PTR)
{
if (pptmp->param_type & SW_PARAM_OUT)
{
sw_data_type_t *data_type;
if (!(data_type = cmd_data_type_find(pptmp->data_type)))
return SW_NO_SUCH;
if (data_type->show_func)
{
data_type->show_func(pptmp->param_name, pbuf, pptmp->data_size);
}
else
{
dprintf("\n Error, not define output print function!");
}
}
if ((pbuf - ioctl_buf +
(pptmp->data_size + 3) / 4) > (IOCTL_BUF_SIZE/4))
return SW_NO_RESOURCE;
pbuf += (pptmp->data_size + 3) / 4;
}
}
return SW_OK;
}
#endif
void
cmd_strtol(char *str, a_uint32_t * arg_val)
{
if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
sscanf(str, "%x", arg_val);
else
sscanf(str, "%d", arg_val);
}
static sw_error_t
cmd_parse_api(char **cmd_str, unsigned long * arg_val)
{
char *tmp_str;
a_uint32_t arg_index, arg_start = 2, reserve_index = 1; /*reserve for dev_id */
a_uint32_t last_param_in = 0;
unsigned long *temp;
void *pentry;
sw_api_param_t *pptmp = NULL;
sw_api_t sw_api;
a_uint32_t ignorecnt = 0, jump = 0;
sw_data_type_t *data_type;
sw_api.api_id = arg_val[0];
SW_RTN_ON_ERROR(sw_api_get(&sw_api));
/*set device id */
arg_val[arg_start] = get_devid();
for (arg_index = reserve_index; arg_index < sw_api.api_nr; arg_index++)
{
tmp_str = NULL;
pptmp = sw_api.api_pp + arg_index;
if (!(pptmp->param_type & SW_PARAM_IN))
{
ignorecnt++;
}
if (pptmp->param_type & SW_PARAM_IN)
{
tmp_str = cmd_str[arg_index - reserve_index - ignorecnt + jump];
last_param_in = arg_index;
if((pptmp->api_id == 314) && last_param_in == 2) last_param_in = 4;//SW_API_FDB_EXTEND_NEXT wr
if((pptmp->api_id == 327) && last_param_in == 2) last_param_in = 4;//SW_API_FDB_EXTEND_FIRST wr
}
temp = &arg_val[arg_start + arg_index];
if (!(data_type = cmd_data_type_find(pptmp->data_type)))
return SW_NO_SUCH;
pentry = temp;
if (pptmp->param_type & SW_PARAM_PTR)
{
if (cmd_input_parser(temp, arg_index, sw_api.api_pp) != SW_OK)
return SW_NO_RESOURCE;
pentry = (void *) *temp;
}
if (pptmp->param_type & SW_PARAM_IN)
{
#if 1
if(pptmp->param_type & SW_PARAM_PTR) //quiet mode
{
if(!get_talk_mode())
set_full_cmdstrp((char **)(cmd_str + (last_param_in - reserve_index) + jump));
}
#endif
/*check and convert input param */
if (data_type->param_check != NULL)
{
if (data_type->param_check(tmp_str, (a_uint32_t *)pentry, (a_uint32_t)pptmp->data_size) != SW_OK)
return SW_BAD_PARAM;
if(!get_talk_mode() && (pptmp->param_type & SW_PARAM_PTR)) {
if (get_jump())
jump += get_jump() -1;
}
}
}
}
/*superfluous args */
/*
if(cmd_str[last_param_in] != NULL)
return SW_BAD_PARAM;
*/
return SW_OK;
}
/*user command api*/
sw_error_t
cmd_exec_api(unsigned long *arg_val)
{
sw_error_t rv;
sw_api_t sw_api;
sw_api.api_id = arg_val[0];
SW_RTN_ON_ERROR(sw_api_get(&sw_api));
/*save cmd return value */
arg_val[1] = (unsigned long) ioctl_buf;
/*save set device id */
arg_val[2] = get_devid();
rv = cmd_api_func(sw_api.api_fp, sw_api.api_nr, arg_val);
SW_RTN_ON_ERROR(rv);
#if 0
rv = cmd_api_output(sw_api.api_pp, sw_api.api_nr, arg_val);
SW_RTN_ON_ERROR(rv);
#endif
return rv;
}
void
cmd_print_usage (int cmd_index, int cmd_index_sub)
{
#if 0
if(GCMD_NAME(cmd_index))
dprintf("usage: %s", GCMD_NAME(cmd_index));
if (GCMD_SUB_NAME(cmd_index, cmd_index_sub))
dprintf(" %s", GCMD_SUB_NAME(cmd_index, cmd_index_sub));
if(GCMD_SUB_ACT(cmd_index, cmd_index_sub) && GCMD_SUB_USAGE(cmd_index, cmd_index_sub))
dprintf(" %s %s\n\n", GCMD_SUB_ACT(cmd_index, cmd_index_sub),
GCMD_SUB_USAGE(cmd_index, cmd_index_sub));
#endif
}
/*
main function
input args:
arg_val[0] = cmd_num
arg_val[1] = rtn_code
arg_val[2] = dev_id
arg_val[3] = dbg_cmd_num or other
*/
/*command string lookup*/
a_uint32_t
cmd_lookup(char **cmd_str, int *cmd_index, int *cmd_index_sub)
{
a_uint32_t no, sub_no;
a_uint32_t cmd_deepth = 0;
*cmd_index = GCMD_DESC_NO_MATCH;
*cmd_index_sub = GCMD_DESC_NO_MATCH;
if (cmd_str[0] == NULL)
return cmd_deepth;
for (no = 0; GCMD_DESC_VALID(no); no++)
{
if (strcasecmp(cmd_str[0], GCMD_NAME(no)))
continue;
for (sub_no = 0; GCMD_SUB_DESC_VALID(no, sub_no); sub_no++)
{
if (cmd_str[1] != NULL && cmd_str[2] != NULL)
{
if (GCMD_SUB_NAME(no, sub_no) && GCMD_SUB_ACT(no, sub_no)
&& !strcasecmp(cmd_str[1], GCMD_SUB_NAME(no, sub_no))
&& !strcasecmp(cmd_str[2], GCMD_SUB_ACT(no, sub_no)))
{
*cmd_index = no;
*cmd_index_sub = sub_no;
cmd_deepth = 3;
return cmd_deepth;
}
else if (!GCMD_SUB_NAME(no, sub_no) && GCMD_SUB_ACT(no, sub_no)
&& !strcasecmp(cmd_str[1], GCMD_SUB_ACT(no, sub_no)))
{
*cmd_index = no;
*cmd_index_sub = sub_no;
cmd_deepth = 2;
return cmd_deepth;
}
}
else if (cmd_str[1] != NULL && cmd_str[2] == NULL)
{
if (!GCMD_SUB_NAME(no, sub_no) && GCMD_SUB_ACT(no, sub_no)
&& !strcasecmp(cmd_str[1], GCMD_SUB_ACT(no, sub_no)))
{
*cmd_index = no;
*cmd_index_sub = sub_no;
cmd_deepth = 2;
return cmd_deepth;
}
}
}
}
return cmd_deepth;
}
static unsigned long *
cmd_parse(char *cmd_str, int *cmd_index, int *cmd_index_sub)
{
int cmd_nr = 0;
unsigned long *arg_val = ioctl_argp;
char *tmp_str[CMDSTR_ARGS_MAX];
int rtn_code = 0;
int cmd_depth;
if (cmd_str == NULL)
return NULL;
memset(arg_val, 0, CMDSTR_ARGS_MAX * sizeof (unsigned long));
/* split string into array */
if ((tmp_str[cmd_nr] = (void *) strsep(&cmd_str, " ")) == NULL)
return NULL;
/*handle help */
if (!strcasecmp(tmp_str[cmd_nr], "help"))
{
return NULL;
}
while (tmp_str[cmd_nr])
{
if (++cmd_nr == 3)
break;
tmp_str[cmd_nr] = (void *) strsep(&cmd_str, " ");
}
/*commond string lookup */
cmd_depth = cmd_lookup(tmp_str, cmd_index, cmd_index_sub);
if (*cmd_index == GCMD_DESC_NO_MATCH || *cmd_index_sub == GCMD_DESC_NO_MATCH)
{
return NULL;
}
/*parse param */
cmd_nr = 0;
if (cmd_depth == 2)
{
tmp_str[cmd_nr] = tmp_str[2];
cmd_nr++;
}
tmp_str[cmd_nr] = (void *) strsep(&cmd_str, " ");
while (tmp_str[cmd_nr])
{
if (strcmp(tmp_str[cmd_nr], ""))
if (++cmd_nr == CMDSTR_ARGS_MAX)
break;
tmp_str[cmd_nr] = (void *) strsep(&cmd_str, " ");
}
arg_val[0] = GCMD_SUB_API(*cmd_index, *cmd_index_sub);
arg_val[1] = (unsigned long) ioctl_buf;
if (arg_val[0] < SW_API_MAX)
{
/*api command parse */
rtn_code = cmd_parse_api(tmp_str, arg_val);
}
else
{
rtn_code = SW_BAD_PARAM;
}
if(rtn_code != SW_OK)
{
cmd_print_error(rtn_code);
if(rtn_code == SW_BAD_PARAM)
cmd_print_usage(*cmd_index, *cmd_index_sub);
return NULL;
}
return arg_val;
}
static int
cmd_exec(unsigned long *arg_val, int cmd_index, int cmd_index_sub)
{
unsigned long api_id = arg_val[0];
sw_error_t rtn = SW_OK;
if( api_id < SW_API_MAX )
{
rtn = cmd_exec_api(arg_val);
}
else if ((api_id > SW_API_MAX ) && (api_id < SW_CMD_MAX))
{
}
else
{
rtn = SW_BAD_PARAM;
}
if(rtn != SW_OK)
cmd_print_error(rtn);
return 0;
}
int
cmd_run_one(char *cmd_str)
{
unsigned long *arg_list;
int cmd_index = 0, cmd_index_sub = 0;
if ((arg_list = cmd_parse(cmd_str, &cmd_index, &cmd_index_sub)) != NULL)
{
cmd_exec(arg_list, cmd_index, cmd_index_sub);
}
return SW_OK;
}
/* Dummy function to avoid linker complaints */
void __aeabi_unwind_cpp_pr0(void)
{
};
void __aeabi_unwind_cpp_pr1(void)
{
};