nuttx-apps/system/cfgdata/cfgdata_main.c
Xiang Xiao 857158451b Unify the void cast usage
1.Remove void cast for function because many place ignore the returned value witout cast
2.Replace void cast for variable with UNUSED macro

Change-Id: Ie644129a563244a6397036789c4c3ea83c4e9b09
Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
2020-01-02 23:21:01 +08:00

745 lines
17 KiB
C

/****************************************************************************
* apps/system/cfgdata/cfgdata_main.c
*
* Copyright (C) 2018 Ken Pettit. All rights reserved.
* Author: Ken Pettit <pettitkd@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/mtd/configdata.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
/****************************************************************************
* Private data
****************************************************************************/
static const char *g_config_dev = "/dev/config";
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Print usage information
****************************************************************************/
static void cfgdatacmd_help(void)
{
printf("\nUsage: cfgdata <cmd> [argumens]\n");
printf("Where <cmd> is one of:\n\n");
printf(" all: show all config entries\n");
printf(" print: display a specific config entry\n");
printf(" set: set or change a config entry\n");
printf(" unset: delete a config entry\n\n");
printf("Syntax for 'set' cmd:\n");
#ifdef CONFIG_MTD_CONFIG_NAMED
printf(" set name [hex_byte,hex_byte,etc.]\n");
printf(" set name \"string\"\n\n");
#else
printf(" set id,instance [bytes]\n");
printf(" set id,instance \"string\"\n\n");
#endif
printf("Syntax for 'print' cmd:\n");
#ifdef CONFIG_MTD_CONFIG_NAMED
printf(" print name\n");
#else
printf(" print id,instance\n");
#endif
printf("Syntax for 'unset' cmd:\n");
#ifdef CONFIG_MTD_CONFIG_NAMED
printf(" unset name\n");
#else
printf(" unset id,instance\n");
#endif
}
/****************************************************************************
* Parse out the id,inst,name tokens
****************************************************************************/
#ifndef CONFIG_MTD_CONFIG_NAMED
static int cfgdatacmd_idtok(int startpos, char *token)
{
while (token[startpos] != ',' && token[startpos] != '\0')
startpos++;
if (token[startpos] != ',')
{
/* Error in format */
printf("Expected config identifer in 'id,instance' format\n");
return 0;
}
/* return, skipping the ',' */
return startpos + 1;
}
#endif
/****************************************************************************
* Set a config item value
*
* config set 1,0,wr_width_cs0 [0x3]
* config set 1,1,wr_width_cs1 [0x2]
*
****************************************************************************/
static void cfgdatacmd_parse_byte_array(struct config_data_s *cfg,
int argc, char *argv[])
{
int x;
int c;
int count;
int val;
/* Start with arg3 */
x = 3;
c = 1;
count = 0;
/* Loop for all remaining arguments until ']' found */
while (x < argc && argv[x][c] != ']' && argv[x][c] != '\0')
{
/* Count this item */
count++;
/* Skip to next item */
while (argv[x][c] != ',' && argv[x][c] != ']' && argv[x][c] != 0)
{
c++;
}
/* Test for comma separator */
if (argv[x][c] == ',')
{
c++;
}
/* Test for space separated items */
if (argv[x][c] == 0)
{
x++;
c = 0;
}
}
/* Test if static stack space allocation is big enough for data */
if (count > cfg->len)
{
/* Perform dynamic memory allocation */
cfg->configdata = (FAR uint8_t *) malloc(count);
cfg->len = count;
}
/* Count determined. Start with arg3 again and parse the bytes */
x = 3;
c = 1;
count = 0;
/* Loop for all remaining arguments until ']' found */
while (x < argc && argv[x][c] != ']' && argv[x][c] != '\0')
{
/* Parse this item */
if (strncmp(&argv[x][c], "0x", 2) == 0)
{
/* Hex byte */
sscanf(&argv[x][c+2], "%x", &val);
cfg->configdata[count] = (uint8_t) val;
}
else
{
/* Decimal value */
cfg->configdata[count] = (uint8_t) atoi(&argv[x][c]);
}
/* Increment the count */
count++;
/* Skip to next item */
while (argv[x][c] != ',' && argv[x][c] != ']' && argv[x][c] != 0)
{
c++;
}
/* Test for comma separator */
if (argv[x][c] == ',')
{
c++;
}
/* Test for space separated items */
if (argv[x][c] == 0)
{
x++;
c = 0;
}
}
cfg->len = count;
}
/****************************************************************************
* Set a config item value
*
* config set 1,0,wr_width_cs0 [0x3]
* config set 1,1,wr_width_cs1 [0x2]
*
****************************************************************************/
static void cfgdatacmd_set(int argc, char *argv[])
{
int ret;
int fd;
struct config_data_s cfg;
uint8_t data[32];
#ifdef CONFIG_MTD_CONFIG_NAMED
/* Copy the name to the cfg struct */
strncpy(cfg.name, argv[2], CONFIG_MTD_CONFIG_NAME_LEN);
#else
int x;
/* Parse the id and instance */
cfg.id = atoi(argv[2]);
/* Advance past ',' to instance number */
x = cfgdatacmd_idtok(0, argv[2]);
if (x == 0)
{
return;
}
/* Convert instance to integer */
cfg.instance = atoi(&argv[2][x]);
#endif
/* Test if data is an array of bytes or simple string */
if (argv[3][0] == '[')
{
/* It is an array of bytes. Count the number of bytes */
cfg.configdata = data;
cfg.len = sizeof(data);
cfgdatacmd_parse_byte_array(&cfg, argc, argv);
}
else
{
bool isnumber = true;
/* It is a simple string. Test if it looks like a number */
cfg.configdata = data;
if (strncmp(argv[3], "0x", 2) == 0)
{
/* Test for all hex digit values */
for (x = 2; x < strlen(argv[3]); x++)
{
if (!isxdigit(argv[3][x]))
{
isnumber = false;
break;
}
}
if (isnumber)
{
sscanf(&argv[3][2], "%x", (int32_t *) &cfg.configdata);
cfg.len = 4;
}
}
else
{
/* Test for all hex digit values */
for (x = 0; x < strlen(argv[3]); x++)
{
if (!isdigit(argv[3][x]))
{
isnumber = false;
break;
}
}
if (isnumber)
{
int32_t temp = atoi(argv[3]);
*((int32_t *) cfg.configdata) = temp;
cfg.len = 4;
}
}
if (!isnumber)
{
/* Point to the string and calculate the length */
cfg.configdata = (FAR uint8_t *) argv[3];
cfg.len = strlen(argv[3]) + 1;
}
}
/* Now open the /dev/config file and set the config item */
if ((fd = open(g_config_dev, O_RDONLY)) < 2)
{
/* Display error */
printf("error: unable to open %s\n", g_config_dev);
return;
}
ret = ioctl(fd, CFGDIOC_SETCONFIG, (unsigned long) &cfg);
/* Close the file and report error if any */
close(fd);
if (ret != OK)
{
printf("Error %d setting config entry\n", errno);
}
/* Free the cfg.configdata if needed */
if (cfg.configdata != (FAR uint8_t *) argv[3] &&
cfg.configdata != data)
{
free(cfg.configdata);
}
}
/****************************************************************************
* Unset a config item value
****************************************************************************/
static void cfgdatacmd_unset(int argc, char *argv[])
{
int ret;
int fd;
struct config_data_s cfg;
#ifdef CONFIG_MTD_CONFIG_NAMED
/* Copy the name to the cfg struct */
strncpy(cfg.name, argv[2], CONFIG_MTD_CONFIG_NAME_LEN);
#else
int x;
/* Parse the id and instance */
cfg.id = atoi(argv[2]);
/* Advance past ',' to instance number */
x = cfgdatacmd_idtok(0, argv[2]);
if (x == 0)
{
return;
}
/* Convert instance to integer */
cfg.instance = atoi(&argv[2][x]);
#endif
cfg.configdata = NULL;
cfg.len = 0;
/* Try to open the /dev/config file */
if ((fd = open(g_config_dev, O_RDONLY)) < 2)
{
/* Display error */
printf("error: unable to open %s\n", g_config_dev);
return;
}
/* Delete the config item */
ret = ioctl(fd, CFGDIOC_DELCONFIG, (unsigned long) &cfg);
close(fd);
if (ret != OK)
{
printf("Error deletign config entry '%s'\n", argv[2]);
}
}
/****************************************************************************
* Print a config item value
*
* config print 1,1
* config print wr_width_cs0
*
****************************************************************************/
static void cfgdatacmd_print(int argc, char *argv[])
{
struct config_data_s cfg;
int ret;
int fd;
bool isstring;
#ifdef CONFIG_MTD_CONFIG_NAMED
/* Copy the name to the cfg struct */
strncpy(cfg.name, argv[2], CONFIG_MTD_CONFIG_NAME_LEN);
#else
int x;
/* Parse the id and instance */
cfg.id = atoi(argv[2]);
/* Advance past ',' to instance number */
x = cfgdatacmd_idtok(0, argv[2]);
if (x == 0)
{
return;
}
/* Convert instance to integer */
cfg.instance = atoi(&argv[2][x]);
#endif
/* Try to open the /dev/config file */
if ((fd = open(g_config_dev, O_RDONLY)) < 2)
{
/* Display error */
printf("error: unable to open %s\n", g_config_dev);
return;
}
cfg.configdata = (FAR uint8_t *) malloc(256);
cfg.len = 256;
if (cfg.configdata == NULL)
{
printf("Error allocating buffer\n");
return;
}
/* Get the config item */
ret = ioctl(fd, CFGDIOC_GETCONFIG, (unsigned long) &cfg);
close(fd);
if (ret != OK)
{
printf("Error reading config entry '%s'\n", argv[2]);
free(cfg.configdata);
return;
}
/* Display the data */
isstring = cfg.configdata[cfg.len-1] == 0;
for (x = 0; x < cfg.len - 1; x++)
{
/* Test for all ascii characters */
if (cfg.configdata[x] < ' ' || cfg.configdata[x] > '~')
{
isstring = false;
break;
}
}
/* Display the data */
if (isstring)
{
printf("%s\n", cfg.configdata);
}
else
{
/* Loop though all bytes and display them */
for (x = 0; x < cfg.len; x++)
{
/* Print the next byte */
printf("0x%02X ", cfg.configdata[x]);
if (((x + 1) & 7) == 0 && x+1 != cfg.len)
{
printf("\n");
}
}
printf("\n");
}
free(cfg.configdata);
}
/****************************************************************************
* Enumerate and display all config items
****************************************************************************/
static void cfgdatacmd_show_all_config_items(void)
{
int fd;
int ret, x;
struct config_data_s cfg;
char fmtstr[24];
bool isstring;
/* Try to open the /dev/config file */
if ((fd = open(g_config_dev, O_RDONLY)) < 2)
{
/* Display error */
printf("error: unable to open %s\n", g_config_dev);
return;
}
/* Print header */
#ifdef CONFIG_MTD_CONFIG_NAMED
sprintf(fmtstr, "%%-%ds%%-6sData\n", CONFIG_MTD_CONFIG_NAME_LEN);
printf(fmtstr, "Name", "Len");
sprintf(fmtstr, "%%-%ds%%-6d", CONFIG_MTD_CONFIG_NAME_LEN);
#else
strcpy(fmtstr, "%-6s%-6s%-6sData\n");
printf(fmtstr, "ID", "Inst", "Len");
strcpy(fmtstr, "%-6d%-6d%-6d");
#endif
/* Get the first config item */
cfg.configdata = (FAR uint8_t *) malloc(256);
cfg.len = 256;
if (cfg.configdata == NULL)
{
printf("Error allocating buffer\n");
return;
}
ret = ioctl(fd, CFGDIOC_FIRSTCONFIG, (unsigned long) &cfg);
while (ret != -1)
{
/* Print this entry */
#ifdef CONFIG_MTD_CONFIG_NAMED
printf(fmtstr, cfg.name, cfg.len);
#else
printf(fmtstr, cfg.id, cfg.instance, cfg.len);
#endif
/* Test if data is a string */
isstring = cfg.configdata[cfg.len-1] == 0;
for (x = 0; x < cfg.len - 1; x++)
{
/* Test for all ascii characters */
if (cfg.configdata[x] < ' ' || cfg.configdata[x] > '~')
{
isstring = false;
break;
}
}
/* Display the data */
if (isstring)
{
printf("%s\n", cfg.configdata);
}
else
{
char fmtstr2[10];
#ifdef CONFIG_MTD_CONFIG_NAMED
sprintf(fmtstr2, "\n%ds", CONFIG_MTD_CONFIG_NAME_LEN+6);
#else
strcpy(fmtstr2, "\n%18s");
#endif
/* Loop though all bytes and display them */
for (x = 0; x < cfg.len; x++)
{
/* Print the next byte */
printf("0x%02X ", cfg.configdata[x]);
if (((x + 1) & 7) == 0 && x+1 != cfg.len)
{
printf(fmtstr2, " ");
}
}
printf("\n");
}
/* Get the next config item */
cfg.len = 256;
ret = ioctl(fd, CFGDIOC_NEXTCONFIG, (unsigned long) &cfg);
}
close(fd);
free(cfg.configdata);
}
/****************************************************************************
* Public Functions
****************************************************************************/
int main(int argc, FAR char *argv[])
{
/* Argument given? */
if (argc == 1)
{
/* Show usage info and exit */
cfgdatacmd_help();
return 0;
}
/* Test for "all" cmd */
if (strcmp(argv[1], "all") == 0)
{
/* Print the existing config items */
cfgdatacmd_show_all_config_items();
return 0;
}
/* Test for "set" cmd */
if (strcmp(argv[1], "set") == 0)
{
if (argc < 4)
{
printf("At least 2 arguments needed for 'set' command\n");
return 0;
}
/* Call the routine to set a config item */
cfgdatacmd_set(argc, argv);
return 0;
}
/* Test for "print" cmd */
if (strcmp(argv[1], "print") == 0)
{
/* Test for print all */
if (strcmp(argv[2], "all") == 0)
{
cfgdatacmd_show_all_config_items();
}
else
{
/* Call the routine to print a config item */
cfgdatacmd_print(argc, argv);
}
return 0;
}
/* Test for "unset" cmd */
if (strcmp(argv[1], "unset") == 0)
{
if (argc < 3)
{
printf("Need 1 argument for 'unset' command\n");
return 0;
}
/* Call the routine to set a config item */
cfgdatacmd_unset(argc, argv);
return 0;
}
/* Unknown cmd */
printf("Unknown config command: %s\n", argv[1]);
return 0;
}