drivers: can: shell: add command for configuring a CAN controller

Add shell command for configuring the mode and bitrate of a CAN
controller.

Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
This commit is contained in:
Henrik Brix Andersen 2020-04-21 12:06:28 +02:00 committed by Carles Cufí
commit 42af963db2

View file

@ -12,8 +12,42 @@
static struct zcan_work work;
static inline int read_options(const struct shell *shell, int pos, char **argv,
bool *rtr, bool *ext)
static inline int read_config_options(const struct shell *shell, int pos,
char **argv, bool *silent, bool *loopback)
{
char *arg = argv[pos];
if (arg[0] != '-') {
return pos;
}
for (arg = &arg[1]; *arg; arg++) {
switch (*arg) {
case 's':
if (silent == NULL) {
shell_error(shell, "unknown option %c", *arg);
} else {
*silent = true;
}
break;
case 'l':
if (loopback == NULL) {
shell_error(shell, "unknown option %c", *arg);
} else {
*loopback = true;
}
break;
default:
shell_error(shell, "unknown option %c", *arg);
return -EINVAL;
}
}
return ++pos;
}
static inline int read_frame_options(const struct shell *shell, int pos,
char **argv, bool *rtr, bool *ext)
{
char *arg = argv[pos];
@ -46,6 +80,23 @@ static inline int read_options(const struct shell *shell, int pos, char **argv,
return ++pos;
}
static inline int read_bitrate(const struct shell *shell, int pos, char **argv,
u32_t *bitrate)
{
char *end_ptr;
long val;
val = strtol(argv[pos], &end_ptr, 0);
if (*end_ptr != '\0') {
shell_error(shell, "bitrate is not a number");
return -EINVAL;
}
*bitrate = (u32_t)val;
return ++pos;
}
static inline int read_id(const struct shell *shell, int pos, char **argv,
bool ext, u32_t *id)
{
@ -156,6 +207,54 @@ static void print_frame(struct zcan_frame *frame, void *arg)
shell_fprintf(shell, SHELL_NORMAL, "|\n");
}
static int cmd_config(const struct shell *shell, size_t argc, char **argv)
{
struct device *can_dev;
int pos = 1;
bool silent = false, loopback = false;
enum can_mode mode;
u32_t bitrate;
int ret;
can_dev = device_get_binding(argv[pos]);
if (!can_dev) {
shell_error(shell, "Can't get binding to device \"%s\"",
argv[pos]);
return -EINVAL;
}
pos++;
pos = read_config_options(shell, pos, argv, &silent, &loopback);
if (pos < 0) {
return -EINVAL;
}
if (silent && loopback) {
mode = CAN_SILENT_LOOPBACK_MODE;
} else if (silent) {
mode = CAN_SILENT_MODE;
} else if (loopback) {
mode = CAN_LOOPBACK_MODE;
} else {
mode = CAN_NORMAL_MODE;
}
pos = read_bitrate(shell, pos, argv, &bitrate);
if (pos < 0) {
return -EINVAL;
}
ret = can_configure(can_dev, mode, bitrate);
if (ret) {
shell_error(shell, "Failed to configure CAN controller [%d]",
ret);
return ret;
}
return 0;
}
static int cmd_send(const struct shell *shell, size_t argc, char **argv)
{
struct device *can_dev;
@ -174,7 +273,7 @@ static int cmd_send(const struct shell *shell, size_t argc, char **argv)
pos++;
pos = read_options(shell, pos, argv, &rtr, &ext);
pos = read_frame_options(shell, pos, argv, &rtr, &ext);
if (pos < 0) {
return -EINVAL;
}
@ -225,7 +324,7 @@ static int cmd_attach(const struct shell *shell, size_t argc, char **argv)
pos++;
pos = read_options(shell, pos, argv, &rtr, &ext);
pos = read_frame_options(shell, pos, argv, &rtr, &ext);
if (pos < 0) {
return -EINVAL;
}
@ -251,7 +350,7 @@ static int cmd_attach(const struct shell *shell, size_t argc, char **argv)
}
if (pos != argc) {
pos = read_options(shell, pos, argv, &rtr_mask, NULL);
pos = read_frame_options(shell, pos, argv, &rtr_mask, NULL);
if (pos < 0) {
return -EINVAL;
}
@ -314,6 +413,12 @@ static int cmd_detach(const struct shell *shell, size_t argc, char **argv)
}
SHELL_STATIC_SUBCMD_SET_CREATE(sub_can,
SHELL_CMD_ARG(config, NULL,
"Configure CAN controller.\n"
" Usage: config device_name [-sl] bitrate\n"
" -s Silent mode\n"
" -l Listen-only mode",
cmd_config, 3, 1),
SHELL_CMD_ARG(send, NULL,
"Send a CAN frame.\n"
" Usage: send device_name [-re] id [byte_1 byte_2 ...]\n"