Skip to content

Commit

Permalink
drivers: gpio: shell: Improved error reporting
Browse files Browse the repository at this point in the history
Invalid device now generates message and errno return
Arguments checked with shell_strtoul
gpio function call return values checked and passed on

Device name completion and usage text added

SHELL_GPIO enabled when SHELL and GPIO both enabled

Signed-off-by: Andy Sinclair <[email protected]>
  • Loading branch information
aasinclair committed Aug 31, 2023
1 parent 3e398cb commit 0ae51f5
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 100 deletions.
1 change: 1 addition & 0 deletions drivers/gpio/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ source "subsys/logging/Kconfig.template.log_config"

config GPIO_SHELL
bool "GPIO Shell"
default y
depends on SHELL
help
Enable GPIO Shell for testing.
Expand Down
226 changes: 126 additions & 100 deletions drivers/gpio/gpio_shell.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,114 +21,108 @@

LOG_MODULE_REGISTER(gpio_shell);

struct args_index {
uint8_t port;
uint8_t index;
uint8_t mode;
uint8_t value;
};

static const struct args_index args_indx = {
.port = 1,
.index = 2,
.mode = 3,
.value = 3,
};

static int cmd_gpio_conf(const struct shell *sh, size_t argc, char **argv)
{
uint8_t index = 0U;
int type = GPIO_OUTPUT;
const struct device *dev;
unsigned long index;
unsigned long type;
int rc = 0;

dev = device_get_binding(argv[1]);
if (dev == NULL) {
shell_error(sh, "GPIO device %s not available", argv[1]);
return -ENODEV;
}

if (isdigit((unsigned char)argv[args_indx.index][0]) != 0 &&
isalpha((unsigned char)argv[args_indx.mode][0]) != 0) {
index = (uint8_t)atoi(argv[args_indx.index]);
if (!strcmp(argv[args_indx.mode], "in")) {
type = GPIO_INPUT;
} else if (!strcmp(argv[args_indx.mode], "inu")) {
type = GPIO_INPUT | GPIO_PULL_UP;
} else if (!strcmp(argv[args_indx.mode], "ind")) {
type = GPIO_INPUT | GPIO_PULL_DOWN;
} else if (!strcmp(argv[args_indx.mode], "out")) {
type = GPIO_OUTPUT;
} else {
return 0;
}
if (!strcmp(argv[3], "in")) {
type = GPIO_INPUT;
} else if (!strcmp(argv[3], "inu")) {
type = GPIO_INPUT | GPIO_PULL_UP;
} else if (!strcmp(argv[3], "ind")) {
type = GPIO_INPUT | GPIO_PULL_DOWN;
} else if (!strcmp(argv[3], "out")) {
type = GPIO_OUTPUT;
} else {
type = shell_strtoul(argv[3], 0, &rc);
}

index = shell_strtoul(argv[2], 10, &rc);
if ((rc < 0) || (index > UINT8_MAX)) {
shell_error(sh, "Wrong parameters for conf");
return -ENOTSUP;
return rc;
}

dev = device_get_binding(argv[args_indx.port]);
shell_print(sh, "Configuring %s pin %lu with mask %lu", argv[1], index, type);

if (dev != NULL) {
index = (uint8_t)atoi(argv[args_indx.index]);
shell_print(sh, "Configuring %s pin %d",
argv[args_indx.port], index);
gpio_pin_configure(dev, index, type);
rc = gpio_pin_configure(dev, index, type);
if (rc < 0) {
shell_error(sh, "Error %d during config", rc);
}

return 0;
return rc;
}

static int cmd_gpio_get(const struct shell *sh,
size_t argc, char **argv)
{
const struct device *dev;
uint8_t index = 0U;
int rc;
unsigned long index;
int rc = 0;

if (isdigit((unsigned char)argv[args_indx.index][0]) != 0) {
index = (uint8_t)atoi(argv[args_indx.index]);
} else {
dev = device_get_binding(argv[1]);
if (dev == NULL) {
shell_error(sh, "GPIO device %s not available", argv[1]);
return -ENODEV;
}

index = shell_strtoul(argv[2], 10, &rc);
if ((rc < 0) || (index > UINT8_MAX)) {
shell_error(sh, "Wrong parameters for get");
return -EINVAL;
return rc;
}

dev = device_get_binding(argv[args_indx.port]);

if (dev != NULL) {
index = (uint8_t)atoi(argv[2]);
shell_print(sh, "Reading %s pin %d",
argv[args_indx.port], index);
rc = gpio_pin_get(dev, index);
if (rc >= 0) {
shell_print(sh, "Value %d", rc);
} else {
shell_error(sh, "Error %d reading value", rc);
return -EIO;
}
shell_print(sh, "Reading %s pin %lu", argv[1], index);

rc = gpio_pin_get(dev, index);
if (rc < 0) {
shell_error(sh, "Error %d reading value", rc);
return -EIO;
}

shell_print(sh, "Value %d", rc);
return 0;
}

static int cmd_gpio_set(const struct shell *sh,
size_t argc, char **argv)
{
const struct device *dev;
uint8_t index = 0U;
unsigned long index;
uint8_t value = 0U;
int rc = 0;

if (isdigit((unsigned char)argv[args_indx.index][0]) != 0 &&
isdigit((unsigned char)argv[args_indx.value][0]) != 0) {
index = (uint8_t)atoi(argv[args_indx.index]);
value = (uint8_t)atoi(argv[args_indx.value]);
} else {
dev = device_get_binding(argv[1]);
if (dev == NULL) {
shell_error(sh, "GPIO device %s not available", argv[1]);
return -ENODEV;
}

index = shell_strtoul(argv[2], 10, &rc);
value = shell_strtoul(argv[3], 10, &rc);

if ((rc < 0) || (index > UINT8_MAX)) {
shell_print(sh, "Wrong parameters for set");
return -EINVAL;
return rc;
}
dev = device_get_binding(argv[args_indx.port]);

if (dev != NULL) {
index = (uint8_t)atoi(argv[2]);
shell_print(sh, "Writing to %s pin %d",
argv[args_indx.port], index);
gpio_pin_set(dev, index, value);
shell_print(sh, "Writing to %s pin %lu", argv[1], index);

rc = gpio_pin_set(dev, index, value);
if (rc < 0) {
shell_error(sh, "Error %d writing value", rc);
}

return 0;
return rc;
}


Expand All @@ -139,49 +133,81 @@ static int cmd_gpio_blink(const struct shell *sh,
size_t argc, char **argv)
{
const struct device *dev;
uint8_t index = 0U;
unsigned long index = 0U;
uint8_t value = 0U;
size_t count = 0;
char data;
int rc = 0;

if (isdigit((unsigned char)argv[args_indx.index][0]) != 0) {
index = (uint8_t)atoi(argv[args_indx.index]);
} else {
dev = device_get_binding(argv[1]);
if (dev == NULL) {
shell_error(sh, "GPIO device %s not available", argv[1]);
return -ENODEV;
}

index = shell_strtoul(argv[2], 10, &rc);
if ((rc < 0) || (index > UINT8_MAX)) {
shell_error(sh, "Wrong parameters for blink");
return -EINVAL;
return rc;
}
dev = device_get_binding(argv[args_indx.port]);

if (dev != NULL) {
index = (uint8_t)atoi(argv[2]);
shell_fprintf(sh, SHELL_NORMAL, "Blinking port %s index %d.", argv[1], index);
shell_fprintf(sh, SHELL_NORMAL, " Hit any key to exit");
shell_fprintf(sh, SHELL_NORMAL, "Blinking port %s index %lu.", argv[1], index);
shell_fprintf(sh, SHELL_NORMAL, " Hit any key to exit");

/* dummy read to clear any pending input */
(void)sh->iface->api->read(sh->iface, &data, sizeof(data), &count);
/* dummy read to clear any pending input */
(void)sh->iface->api->read(sh->iface, &data, sizeof(data), &count);

while (true) {
(void)sh->iface->api->read(sh->iface, &data, sizeof(data), &count);
if (count != 0) {
break;
}
gpio_pin_set(dev, index, value);
value = !value;
k_msleep(SLEEP_TIME_MS);
while (true) {
(void)sh->iface->api->read(sh->iface, &data, sizeof(data), &count);
if (count != 0) {
break;
}

shell_fprintf(sh, SHELL_NORMAL, "\n");
gpio_pin_set(dev, index, value);
value = !value;
k_msleep(SLEEP_TIME_MS);
}

shell_fprintf(sh, SHELL_NORMAL, "\n");

return 0;
}

SHELL_STATIC_SUBCMD_SET_CREATE(sub_gpio,
SHELL_CMD_ARG(conf, NULL, "Configure GPIO", cmd_gpio_conf, 4, 0),
SHELL_CMD_ARG(get, NULL, "Get GPIO value", cmd_gpio_get, 3, 0),
SHELL_CMD_ARG(set, NULL, "Set GPIO", cmd_gpio_set, 4, 0),
SHELL_CMD_ARG(blink, NULL, "Blink GPIO", cmd_gpio_blink, 3, 0),
SHELL_SUBCMD_SET_END /* Array terminated. */
);
static void device_name_get(size_t idx, struct shell_static_entry *entry)
{
const struct device *dev = shell_device_lookup(idx, NULL);

entry->syntax = (dev != NULL) ? dev->name : NULL;
entry->handler = NULL;
entry->help = NULL;
entry->subcmd = NULL;
}

SHELL_DYNAMIC_CMD_CREATE(dsub_device_name, device_name_get);

SHELL_STATIC_SUBCMD_SET_CREATE(
sub_gpio,
SHELL_CMD_ARG(conf, &dsub_device_name,
"Configure GPIO\n"
"Usage: conf <device> <pin> <mode>\n"
"The mode argument accepts these values:\n"
"'in' - Input\n"
"'inu' - Input with pullup\n"
"'ind' - Input with pulldown\n"
"'out' - Output\n"
"An integer - Passed to gpio_pin_configure flags argument",
cmd_gpio_conf, 4, 0),
SHELL_CMD_ARG(get, &dsub_device_name,
"Get GPIO value\n"
"Usage: get <device> <pin>",
cmd_gpio_get, 3, 0),
SHELL_CMD_ARG(set, &dsub_device_name,
"Set GPIO\n"
"Usage: set <device> <pin> <value>",
cmd_gpio_set, 4, 0),
SHELL_CMD_ARG(blink, &dsub_device_name,
"Blink GPIO\n"
"Usage: blink <device> <pin>",
cmd_gpio_blink, 3, 0),
SHELL_SUBCMD_SET_END);

SHELL_CMD_REGISTER(gpio, &sub_gpio, "GPIO commands", NULL);

0 comments on commit 0ae51f5

Please sign in to comment.