2019-04-24 20:09:34 +02:00
|
|
|
/*
|
2022-08-26 12:50:16 +02:00
|
|
|
* Copyright (c) 2022 Vestas Wind Systems A/S
|
2019-04-24 20:09:34 +02:00
|
|
|
* Copyright (c) 2019 Alexander Wachter
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
2022-08-26 12:50:16 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include <zephyr/device.h>
|
|
|
|
#include <zephyr/drivers/can.h>
|
|
|
|
#include <zephyr/logging/log.h>
|
|
|
|
#include <zephyr/shell/shell.h>
|
|
|
|
|
|
|
|
LOG_MODULE_REGISTER(can_shell, CONFIG_CAN_LOG_LEVEL);
|
2019-04-24 20:09:34 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
struct can_shell_tx_event {
|
|
|
|
unsigned int frame_no;
|
|
|
|
int error;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct can_shell_mode_mapping {
|
|
|
|
const char *name;
|
|
|
|
can_mode_t mode;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define CAN_SHELL_MODE_MAPPING(_name, _mode) { .name = _name, .mode = _mode }
|
|
|
|
|
|
|
|
static const struct can_shell_mode_mapping can_shell_mode_map[] = {
|
|
|
|
/* Array sorted alphabetically based on name */
|
|
|
|
CAN_SHELL_MODE_MAPPING("fd", CAN_MODE_FD),
|
|
|
|
CAN_SHELL_MODE_MAPPING("listen-only", CAN_MODE_LISTENONLY),
|
|
|
|
CAN_SHELL_MODE_MAPPING("loopback", CAN_MODE_LOOPBACK),
|
|
|
|
CAN_SHELL_MODE_MAPPING("normal", CAN_MODE_NORMAL),
|
|
|
|
CAN_SHELL_MODE_MAPPING("one-shot", CAN_MODE_ONE_SHOT),
|
|
|
|
CAN_SHELL_MODE_MAPPING("triple-sampling", CAN_MODE_3_SAMPLES),
|
|
|
|
};
|
|
|
|
|
|
|
|
K_MSGQ_DEFINE(can_shell_tx_msgq, sizeof(struct can_shell_tx_event),
|
|
|
|
CONFIG_CAN_SHELL_TX_QUEUE_SIZE, 4);
|
|
|
|
const struct shell *can_shell_tx_msgq_sh;
|
|
|
|
static struct k_work_poll can_shell_tx_msgq_work;
|
|
|
|
static struct k_poll_event can_shell_tx_msgq_events[] = {
|
2021-12-16 12:13:33 +01:00
|
|
|
K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_MSGQ_DATA_AVAILABLE,
|
|
|
|
K_POLL_MODE_NOTIFY_ONLY,
|
2022-08-26 12:50:16 +02:00
|
|
|
&can_shell_tx_msgq, 0)
|
2021-12-16 12:13:33 +01:00
|
|
|
};
|
2019-04-24 20:09:34 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
CAN_MSGQ_DEFINE(can_shell_rx_msgq, CONFIG_CAN_SHELL_RX_QUEUE_SIZE);
|
|
|
|
const struct shell *can_shell_rx_msgq_sh;
|
|
|
|
static struct k_work_poll can_shell_rx_msgq_work;
|
|
|
|
static struct k_poll_event can_shell_rx_msgq_events[] = {
|
|
|
|
K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_MSGQ_DATA_AVAILABLE,
|
|
|
|
K_POLL_MODE_NOTIFY_ONLY,
|
|
|
|
&can_shell_rx_msgq, 0)
|
|
|
|
};
|
2020-04-21 12:06:28 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
/* Forward declarations */
|
|
|
|
static void can_shell_tx_msgq_triggered_work_handler(struct k_work *work);
|
|
|
|
static void can_shell_rx_msgq_triggered_work_handler(struct k_work *work);
|
2020-04-21 12:06:28 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
static void can_shell_print_frame(const struct shell *sh, const struct can_frame *frame)
|
|
|
|
{
|
|
|
|
uint8_t nbytes = can_dlc_to_bytes(frame->dlc);
|
|
|
|
int i;
|
|
|
|
|
|
|
|
#ifdef CONFIG_CAN_RX_TIMESTAMP
|
|
|
|
/* Timestamp */
|
|
|
|
shell_fprintf(sh, SHELL_NORMAL, "(%05d) ", frame->timestamp);
|
|
|
|
#endif /* CONFIG_CAN_RX_TIMESTAMP */
|
|
|
|
|
|
|
|
#ifdef CONFIG_CAN_FD_MODE
|
|
|
|
/* Flags */
|
2023-03-10 19:37:29 +01:00
|
|
|
shell_fprintf(sh, SHELL_NORMAL, "%c%c ",
|
|
|
|
(frame->flags & CAN_FRAME_BRS) == 0 ? '-' : 'B',
|
|
|
|
(frame->flags & CAN_FRAME_ESI) == 0 ? '-' : 'P');
|
2022-08-26 12:50:16 +02:00
|
|
|
#endif /* CONFIG_CAN_FD_MODE */
|
|
|
|
|
|
|
|
/* CAN ID */
|
|
|
|
shell_fprintf(sh, SHELL_NORMAL, "%*s%0*x ",
|
drivers: can: use flags fields for can_frame and can_filter structs
The can_frame and can_filter structs support a number of different flags
(standard/extended CAN ID type, Remote Transmission Request, CAN-FD format,
Bit Rate Switch, ...). Each of these flags is represented as a discrete bit
in the given structure.
This design pattern requires every user of these structs to initialize all
of these flags to either 0 or 1, which does not scale well for future flag
additions.
Some of these flags have associated enumerations to be used for assignment,
some do not. CAN drivers and protocols tend to rely on the logical value of
the flag instead of using the enumeration, leading to a very fragile
API. The enumerations are used inconsistently between the can_frame and
can_filter structures, which further complicates the API.
Instead, convert these flags to bitfields with separate flag definitions
for the can_frame and can_filter structures. This API allows for future
extensions without having to revisit existing users of the two
structures. Furthermore, this allows driver to easily check for unsupported
flags in the respective API calls.
As this change leads to the "id_mask" field of the can_filter to be the
only mask present in that structure, rename it to "mask" for simplicity.
Fixes: #50776
Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
2022-09-30 14:44:16 +02:00
|
|
|
(frame->flags & CAN_FRAME_IDE) != 0 ? 0 : 5, "",
|
|
|
|
(frame->flags & CAN_FRAME_IDE) != 0 ? 8 : 3,
|
|
|
|
(frame->flags & CAN_FRAME_IDE) != 0 ?
|
|
|
|
frame->id & CAN_EXT_ID_MASK : frame->id & CAN_STD_ID_MASK);
|
2022-08-26 12:50:16 +02:00
|
|
|
|
|
|
|
/* DLC as number of bytes */
|
|
|
|
shell_fprintf(sh, SHELL_NORMAL, "%s[%0*d] ",
|
drivers: can: use flags fields for can_frame and can_filter structs
The can_frame and can_filter structs support a number of different flags
(standard/extended CAN ID type, Remote Transmission Request, CAN-FD format,
Bit Rate Switch, ...). Each of these flags is represented as a discrete bit
in the given structure.
This design pattern requires every user of these structs to initialize all
of these flags to either 0 or 1, which does not scale well for future flag
additions.
Some of these flags have associated enumerations to be used for assignment,
some do not. CAN drivers and protocols tend to rely on the logical value of
the flag instead of using the enumeration, leading to a very fragile
API. The enumerations are used inconsistently between the can_frame and
can_filter structures, which further complicates the API.
Instead, convert these flags to bitfields with separate flag definitions
for the can_frame and can_filter structures. This API allows for future
extensions without having to revisit existing users of the two
structures. Furthermore, this allows driver to easily check for unsupported
flags in the respective API calls.
As this change leads to the "id_mask" field of the can_filter to be the
only mask present in that structure, rename it to "mask" for simplicity.
Fixes: #50776
Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
2022-09-30 14:44:16 +02:00
|
|
|
(frame->flags & CAN_FRAME_FDF) != 0 ? "" : " ",
|
|
|
|
(frame->flags & CAN_FRAME_FDF) != 0 ? 2 : 1,
|
|
|
|
nbytes);
|
2022-08-26 12:50:16 +02:00
|
|
|
|
|
|
|
/* Data payload */
|
drivers: can: use flags fields for can_frame and can_filter structs
The can_frame and can_filter structs support a number of different flags
(standard/extended CAN ID type, Remote Transmission Request, CAN-FD format,
Bit Rate Switch, ...). Each of these flags is represented as a discrete bit
in the given structure.
This design pattern requires every user of these structs to initialize all
of these flags to either 0 or 1, which does not scale well for future flag
additions.
Some of these flags have associated enumerations to be used for assignment,
some do not. CAN drivers and protocols tend to rely on the logical value of
the flag instead of using the enumeration, leading to a very fragile
API. The enumerations are used inconsistently between the can_frame and
can_filter structures, which further complicates the API.
Instead, convert these flags to bitfields with separate flag definitions
for the can_frame and can_filter structures. This API allows for future
extensions without having to revisit existing users of the two
structures. Furthermore, this allows driver to easily check for unsupported
flags in the respective API calls.
As this change leads to the "id_mask" field of the can_filter to be the
only mask present in that structure, rename it to "mask" for simplicity.
Fixes: #50776
Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
2022-09-30 14:44:16 +02:00
|
|
|
if ((frame->flags & CAN_FRAME_RTR) != 0) {
|
|
|
|
shell_fprintf(sh, SHELL_NORMAL, "remote transmission request");
|
|
|
|
} else {
|
2022-08-26 12:50:16 +02:00
|
|
|
for (i = 0; i < nbytes; i++) {
|
|
|
|
shell_fprintf(sh, SHELL_NORMAL, "%02x ", frame->data[i]);
|
2020-04-21 12:06:28 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
shell_fprintf(sh, SHELL_NORMAL, "\n");
|
2020-04-21 12:06:28 +02:00
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
static int can_shell_tx_msgq_poll_submit(const struct shell *sh)
|
2019-04-24 20:09:34 +02:00
|
|
|
{
|
2022-08-26 12:50:16 +02:00
|
|
|
int err;
|
2019-04-24 20:09:34 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
if (can_shell_tx_msgq_sh == NULL) {
|
|
|
|
can_shell_tx_msgq_sh = sh;
|
|
|
|
k_work_poll_init(&can_shell_tx_msgq_work, can_shell_tx_msgq_triggered_work_handler);
|
2019-04-24 20:09:34 +02:00
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
err = k_work_poll_submit(&can_shell_tx_msgq_work, can_shell_tx_msgq_events,
|
|
|
|
ARRAY_SIZE(can_shell_tx_msgq_events), K_FOREVER);
|
|
|
|
if (err != 0) {
|
|
|
|
shell_error(can_shell_tx_msgq_sh, "failed to submit tx msgq polling (err %d)",
|
|
|
|
err);
|
2019-04-24 20:09:34 +02:00
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
return err;
|
2019-04-24 20:09:34 +02:00
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
static void can_shell_tx_msgq_triggered_work_handler(struct k_work *work)
|
2020-04-21 12:06:28 +02:00
|
|
|
{
|
2022-08-26 12:50:16 +02:00
|
|
|
struct can_shell_tx_event event;
|
2020-04-21 12:06:28 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
while (k_msgq_get(&can_shell_tx_msgq, &event, K_NO_WAIT) == 0) {
|
|
|
|
if (event.error == 0) {
|
|
|
|
shell_print(can_shell_tx_msgq_sh, "CAN frame #%u successfully sent",
|
|
|
|
event.frame_no);
|
|
|
|
} else {
|
|
|
|
shell_error(can_shell_tx_msgq_sh, "failed to send CAN frame #%u (err %d)",
|
|
|
|
event.frame_no, event.error);
|
|
|
|
}
|
2020-04-21 12:06:28 +02:00
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
(void)can_shell_tx_msgq_poll_submit(can_shell_tx_msgq_sh);
|
2020-04-21 12:06:28 +02:00
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
static void can_shell_tx_callback(const struct device *dev, int error, void *user_data)
|
2019-04-24 20:09:34 +02:00
|
|
|
{
|
2022-08-26 12:50:16 +02:00
|
|
|
struct can_shell_tx_event event;
|
|
|
|
int err;
|
2019-04-24 20:09:34 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
ARG_UNUSED(dev);
|
|
|
|
|
|
|
|
event.frame_no = POINTER_TO_UINT(user_data);
|
|
|
|
event.error = error;
|
|
|
|
|
|
|
|
err = k_msgq_put(&can_shell_tx_msgq, &event, K_NO_WAIT);
|
|
|
|
if (err != 0) {
|
|
|
|
LOG_ERR("CAN shell tx event queue full");
|
2019-04-24 20:09:34 +02:00
|
|
|
}
|
2022-08-26 12:50:16 +02:00
|
|
|
}
|
2019-04-24 20:09:34 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
static int can_shell_rx_msgq_poll_submit(const struct shell *sh)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (can_shell_rx_msgq_sh == NULL) {
|
|
|
|
can_shell_rx_msgq_sh = sh;
|
|
|
|
k_work_poll_init(&can_shell_rx_msgq_work, can_shell_rx_msgq_triggered_work_handler);
|
2019-04-24 20:09:34 +02:00
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
err = k_work_poll_submit(&can_shell_rx_msgq_work, can_shell_rx_msgq_events,
|
|
|
|
ARRAY_SIZE(can_shell_rx_msgq_events), K_FOREVER);
|
|
|
|
if (err != 0) {
|
|
|
|
shell_error(can_shell_rx_msgq_sh, "failed to submit rx msgq polling (err %d)",
|
|
|
|
err);
|
|
|
|
}
|
2019-04-24 20:09:34 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
return err;
|
2019-04-24 20:09:34 +02:00
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
static void can_shell_rx_msgq_triggered_work_handler(struct k_work *work)
|
2019-04-24 20:09:34 +02:00
|
|
|
{
|
2022-08-26 12:50:16 +02:00
|
|
|
struct can_frame frame;
|
2019-04-24 20:09:34 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
while (k_msgq_get(&can_shell_rx_msgq, &frame, K_NO_WAIT) == 0) {
|
|
|
|
can_shell_print_frame(can_shell_rx_msgq_sh, &frame);
|
2019-04-24 20:09:34 +02:00
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
(void)can_shell_rx_msgq_poll_submit(can_shell_rx_msgq_sh);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *can_shell_state_to_string(enum can_state state)
|
|
|
|
{
|
|
|
|
switch (state) {
|
|
|
|
case CAN_STATE_ERROR_ACTIVE:
|
|
|
|
return "error-active";
|
|
|
|
case CAN_STATE_ERROR_WARNING:
|
|
|
|
return "error-warning";
|
|
|
|
case CAN_STATE_ERROR_PASSIVE:
|
|
|
|
return "error-passive";
|
|
|
|
case CAN_STATE_BUS_OFF:
|
|
|
|
return "bus-off";
|
2022-08-31 14:28:42 +02:00
|
|
|
case CAN_STATE_STOPPED:
|
|
|
|
return "stopped";
|
2022-08-26 12:50:16 +02:00
|
|
|
default:
|
|
|
|
return "unknown";
|
2019-04-24 20:09:34 +02:00
|
|
|
}
|
2022-08-26 12:50:16 +02:00
|
|
|
}
|
2019-04-24 20:09:34 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
static void can_shell_print_capabilities(const struct shell *sh, can_mode_t cap)
|
|
|
|
{
|
|
|
|
int bit;
|
|
|
|
int i;
|
2019-04-24 20:09:34 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
for (bit = 0; bit < sizeof(cap) * 8; bit++) {
|
|
|
|
/* Skip unset bits */
|
|
|
|
if ((cap & BIT(bit)) == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Lookup symbolic mode name */
|
|
|
|
for (i = 0; i < ARRAY_SIZE(can_shell_mode_map); i++) {
|
|
|
|
if (BIT(bit) == can_shell_mode_map[i].mode) {
|
|
|
|
shell_fprintf(sh, SHELL_NORMAL, "%s ", can_shell_mode_map[i].name);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i == ARRAY_SIZE(can_shell_mode_map)) {
|
|
|
|
/* Symbolic name not found, use raw mode */
|
|
|
|
shell_fprintf(sh, SHELL_NORMAL, "0x%08x ", (can_mode_t)BIT(bit));
|
|
|
|
}
|
|
|
|
}
|
2019-04-24 20:09:34 +02:00
|
|
|
}
|
|
|
|
|
2022-08-31 14:40:55 +02:00
|
|
|
static int cmd_can_start(const struct shell *sh, size_t argc, char **argv)
|
|
|
|
{
|
|
|
|
const struct device *dev = device_get_binding(argv[1]);
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (!device_is_ready(dev)) {
|
|
|
|
shell_error(sh, "device %s not ready", argv[1]);
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
|
|
|
shell_print(sh, "starting %s", argv[1]);
|
|
|
|
|
|
|
|
err = can_start(dev);
|
|
|
|
if (err != 0) {
|
|
|
|
shell_error(sh, "failed to start CAN controller (err %d)", err);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int cmd_can_stop(const struct shell *sh, size_t argc, char **argv)
|
|
|
|
{
|
|
|
|
const struct device *dev = device_get_binding(argv[1]);
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (!device_is_ready(dev)) {
|
|
|
|
shell_error(sh, "device %s not ready", argv[1]);
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
|
|
|
shell_print(sh, "stopping %s", argv[1]);
|
|
|
|
|
|
|
|
err = can_stop(dev);
|
|
|
|
if (err != 0) {
|
|
|
|
shell_error(sh, "failed to stop CAN controller (err %d)", err);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-08-26 12:54:41 +02:00
|
|
|
static int cmd_can_show(const struct shell *sh, size_t argc, char **argv)
|
|
|
|
{
|
|
|
|
const struct device *dev = device_get_binding(argv[1]);
|
2023-03-16 13:56:18 +01:00
|
|
|
const struct can_timing *timing_min;
|
|
|
|
const struct can_timing *timing_max;
|
2022-08-26 12:54:41 +02:00
|
|
|
struct can_bus_err_cnt err_cnt;
|
|
|
|
enum can_state state;
|
|
|
|
uint32_t max_bitrate = 0;
|
|
|
|
int max_std_filters = 0;
|
|
|
|
int max_ext_filters = 0;
|
|
|
|
uint32_t core_clock;
|
|
|
|
can_mode_t cap;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (!device_is_ready(dev)) {
|
|
|
|
shell_error(sh, "device %s not ready", argv[1]);
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = can_get_core_clock(dev, &core_clock);
|
|
|
|
if (err != 0) {
|
|
|
|
shell_error(sh, "failed to get CAN core clock (err %d)", err);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = can_get_max_bitrate(dev, &max_bitrate);
|
|
|
|
if (err != 0 && err != -ENOSYS) {
|
|
|
|
shell_error(sh, "failed to get maximum bitrate (err %d)", err);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
drivers: can: use flags fields for can_frame and can_filter structs
The can_frame and can_filter structs support a number of different flags
(standard/extended CAN ID type, Remote Transmission Request, CAN-FD format,
Bit Rate Switch, ...). Each of these flags is represented as a discrete bit
in the given structure.
This design pattern requires every user of these structs to initialize all
of these flags to either 0 or 1, which does not scale well for future flag
additions.
Some of these flags have associated enumerations to be used for assignment,
some do not. CAN drivers and protocols tend to rely on the logical value of
the flag instead of using the enumeration, leading to a very fragile
API. The enumerations are used inconsistently between the can_frame and
can_filter structures, which further complicates the API.
Instead, convert these flags to bitfields with separate flag definitions
for the can_frame and can_filter structures. This API allows for future
extensions without having to revisit existing users of the two
structures. Furthermore, this allows driver to easily check for unsupported
flags in the respective API calls.
As this change leads to the "id_mask" field of the can_filter to be the
only mask present in that structure, rename it to "mask" for simplicity.
Fixes: #50776
Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
2022-09-30 14:44:16 +02:00
|
|
|
max_std_filters = can_get_max_filters(dev, false);
|
2022-08-26 12:54:41 +02:00
|
|
|
if (max_std_filters < 0 && max_std_filters != -ENOSYS) {
|
|
|
|
shell_error(sh, "failed to get maximum standard (11-bit) filters (err %d)", err);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
drivers: can: use flags fields for can_frame and can_filter structs
The can_frame and can_filter structs support a number of different flags
(standard/extended CAN ID type, Remote Transmission Request, CAN-FD format,
Bit Rate Switch, ...). Each of these flags is represented as a discrete bit
in the given structure.
This design pattern requires every user of these structs to initialize all
of these flags to either 0 or 1, which does not scale well for future flag
additions.
Some of these flags have associated enumerations to be used for assignment,
some do not. CAN drivers and protocols tend to rely on the logical value of
the flag instead of using the enumeration, leading to a very fragile
API. The enumerations are used inconsistently between the can_frame and
can_filter structures, which further complicates the API.
Instead, convert these flags to bitfields with separate flag definitions
for the can_frame and can_filter structures. This API allows for future
extensions without having to revisit existing users of the two
structures. Furthermore, this allows driver to easily check for unsupported
flags in the respective API calls.
As this change leads to the "id_mask" field of the can_filter to be the
only mask present in that structure, rename it to "mask" for simplicity.
Fixes: #50776
Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
2022-09-30 14:44:16 +02:00
|
|
|
max_ext_filters = can_get_max_filters(dev, true);
|
2022-08-26 12:54:41 +02:00
|
|
|
if (max_ext_filters < 0 && max_ext_filters != -ENOSYS) {
|
|
|
|
shell_error(sh, "failed to get maximum extended (29-bit) filters (err %d)", err);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = can_get_capabilities(dev, &cap);
|
|
|
|
if (err != 0) {
|
|
|
|
shell_error(sh, "failed to get CAN controller capabilities (err %d)", err);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = can_get_state(dev, &state, &err_cnt);
|
|
|
|
if (err != 0) {
|
|
|
|
shell_error(sh, "failed to get CAN controller state (%d)", err);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
shell_print(sh, "core clock: %d Hz", core_clock);
|
|
|
|
shell_print(sh, "max bitrate: %d bps", max_bitrate);
|
|
|
|
shell_print(sh, "max std filters: %d", max_std_filters);
|
|
|
|
shell_print(sh, "max ext filters: %d", max_ext_filters);
|
|
|
|
|
|
|
|
shell_fprintf(sh, SHELL_NORMAL, "capabilities: normal ");
|
|
|
|
can_shell_print_capabilities(sh, cap);
|
|
|
|
shell_fprintf(sh, SHELL_NORMAL, "\n");
|
|
|
|
|
|
|
|
shell_print(sh, "state: %s", can_shell_state_to_string(state));
|
|
|
|
shell_print(sh, "rx errors: %d", err_cnt.rx_err_cnt);
|
|
|
|
shell_print(sh, "tx errors: %d", err_cnt.tx_err_cnt);
|
|
|
|
|
2023-03-16 13:56:18 +01:00
|
|
|
timing_min = can_get_timing_min(dev);
|
|
|
|
timing_max = can_get_timing_max(dev);
|
|
|
|
|
|
|
|
shell_print(sh, "timing: sjw %u..%u, prop_seg %u..%u, "
|
|
|
|
"phase_seg1 %u..%u, phase_seg2 %u..%u, prescaler %u..%u",
|
|
|
|
timing_min->sjw, timing_max->sjw,
|
|
|
|
timing_min->prop_seg, timing_max->prop_seg,
|
|
|
|
timing_min->phase_seg1, timing_max->phase_seg1,
|
|
|
|
timing_min->phase_seg2, timing_max->phase_seg2,
|
|
|
|
timing_min->prescaler, timing_max->prescaler);
|
|
|
|
|
|
|
|
if (IS_ENABLED(CONFIG_CAN_FD_MODE) && (cap & CAN_MODE_FD) != 0) {
|
|
|
|
timing_min = can_get_timing_data_min(dev);
|
|
|
|
timing_max = can_get_timing_data_max(dev);
|
|
|
|
|
|
|
|
shell_print(sh, "timing data: sjw %u..%u, prop_seg %u..%u, "
|
|
|
|
"phase_seg1 %u..%u, phase_seg2 %u..%u, prescaler %u..%u",
|
|
|
|
timing_min->sjw, timing_max->sjw,
|
|
|
|
timing_min->prop_seg, timing_max->prop_seg,
|
|
|
|
timing_min->phase_seg1, timing_max->phase_seg1,
|
|
|
|
timing_min->phase_seg2, timing_max->phase_seg2,
|
|
|
|
timing_min->prescaler, timing_max->prescaler);
|
|
|
|
}
|
|
|
|
|
2022-08-26 12:54:41 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
static int cmd_can_bitrate_set(const struct shell *sh, size_t argc, char **argv)
|
2019-04-24 20:09:34 +02:00
|
|
|
{
|
2022-08-26 12:50:16 +02:00
|
|
|
const struct device *dev = device_get_binding(argv[1]);
|
|
|
|
struct can_timing timing;
|
|
|
|
uint16_t sample_pnt;
|
|
|
|
uint32_t bitrate;
|
|
|
|
char *endptr;
|
|
|
|
int err;
|
2019-04-24 20:09:34 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
if (!device_is_ready(dev)) {
|
|
|
|
shell_error(sh, "device %s not ready", argv[1]);
|
|
|
|
return -ENODEV;
|
2019-04-24 20:09:34 +02:00
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
bitrate = (uint32_t)strtoul(argv[2], &endptr, 10);
|
|
|
|
if (*endptr != '\0') {
|
|
|
|
shell_error(sh, "failed to parse bitrate");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
2019-04-24 20:09:34 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
if (argc >= 4) {
|
|
|
|
sample_pnt = (uint32_t)strtoul(argv[3], &endptr, 10);
|
|
|
|
if (*endptr != '\0') {
|
|
|
|
shell_error(sh, "failed to parse sample point");
|
2019-04-24 20:09:34 +02:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2023-03-13 21:46:59 +01:00
|
|
|
if (argc >= 5) {
|
|
|
|
timing.sjw = (uint16_t)strtoul(argv[4], &endptr, 10);
|
|
|
|
if (*endptr != '\0') {
|
|
|
|
shell_error(sh, "failed to parse SJW");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
timing.sjw = CAN_SJW_NO_CHANGE;
|
|
|
|
}
|
2019-04-24 20:09:34 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
err = can_calc_timing(dev, &timing, bitrate, sample_pnt);
|
|
|
|
if (err < 0) {
|
|
|
|
shell_error(sh, "failed to calculate timing for "
|
|
|
|
"bitrate %d bps, sample point %d.%d%% (err %d)",
|
|
|
|
bitrate, sample_pnt / 10, sample_pnt % 10, err);
|
|
|
|
return err;
|
|
|
|
}
|
2019-04-24 20:09:34 +02:00
|
|
|
|
2023-03-13 21:46:59 +01:00
|
|
|
if (timing.sjw == CAN_SJW_NO_CHANGE) {
|
|
|
|
shell_print(sh, "setting bitrate to %d bps, sample point %d.%d%% "
|
|
|
|
"(+/- %d.%d%%)",
|
|
|
|
bitrate, sample_pnt / 10, sample_pnt % 10, err / 10, err % 10);
|
|
|
|
} else {
|
|
|
|
shell_print(sh, "setting bitrate to %d bps, sample point %d.%d%% "
|
|
|
|
"(+/- %d.%d%%), sjw %d",
|
|
|
|
bitrate, sample_pnt / 10, sample_pnt % 10, err / 10, err % 10,
|
|
|
|
timing.sjw);
|
|
|
|
}
|
2019-04-24 20:09:34 +02:00
|
|
|
|
2023-03-16 13:57:55 +01:00
|
|
|
LOG_DBG("sjw %u, prop_seg %u, phase_seg1 %u, phase_seg2 %u, prescaler %u",
|
|
|
|
timing.sjw, timing.prop_seg, timing.phase_seg1, timing.phase_seg2,
|
|
|
|
timing.prescaler);
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
err = can_set_timing(dev, &timing);
|
|
|
|
if (err != 0) {
|
|
|
|
shell_error(sh, "failed to set timing (err %d)", err);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
shell_print(sh, "setting bitrate to %d bps", bitrate);
|
2019-04-24 20:09:34 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
err = can_set_bitrate(dev, bitrate);
|
|
|
|
if (err != 0) {
|
|
|
|
shell_error(sh, "failed to set bitrate (err %d)", err);
|
|
|
|
return err;
|
2019-04-24 20:09:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
return 0;
|
2021-12-16 12:13:33 +01:00
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
static int cmd_can_dbitrate_set(const struct shell *sh, size_t argc, char **argv)
|
2021-12-16 12:13:33 +01:00
|
|
|
{
|
2022-08-26 12:50:16 +02:00
|
|
|
const struct device *dev = device_get_binding(argv[1]);
|
|
|
|
struct can_timing timing;
|
|
|
|
uint16_t sample_pnt;
|
|
|
|
uint32_t bitrate;
|
|
|
|
char *endptr;
|
|
|
|
int err;
|
2021-12-16 12:13:33 +01:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
if (!device_is_ready(dev)) {
|
|
|
|
shell_error(sh, "device %s not ready", argv[1]);
|
|
|
|
return -ENODEV;
|
2021-12-16 12:13:33 +01:00
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
bitrate = (uint32_t)strtoul(argv[2], &endptr, 10);
|
|
|
|
if (*endptr != '\0') {
|
|
|
|
shell_error(sh, "failed to parse data bitrate");
|
|
|
|
return -EINVAL;
|
2021-12-16 12:13:33 +01:00
|
|
|
}
|
2019-04-24 20:09:34 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
if (argc >= 4) {
|
|
|
|
sample_pnt = (uint32_t)strtoul(argv[3], &endptr, 10);
|
|
|
|
if (*endptr != '\0') {
|
|
|
|
shell_error(sh, "failed to parse sample point");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
2020-04-21 12:06:28 +02:00
|
|
|
|
2023-03-13 21:46:59 +01:00
|
|
|
if (argc >= 5) {
|
|
|
|
timing.sjw = (uint16_t)strtoul(argv[4], &endptr, 10);
|
|
|
|
if (*endptr != '\0') {
|
|
|
|
shell_error(sh, "failed to parse SJW");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
timing.sjw = CAN_SJW_NO_CHANGE;
|
|
|
|
}
|
2020-04-21 12:06:28 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
err = can_calc_timing_data(dev, &timing, bitrate, sample_pnt);
|
|
|
|
if (err < 0) {
|
|
|
|
shell_error(sh, "failed to calculate timing for "
|
|
|
|
"data bitrate %d bps, sample point %d.%d%% (err %d)",
|
|
|
|
bitrate, sample_pnt / 10, sample_pnt % 10, err);
|
|
|
|
return err;
|
|
|
|
}
|
2020-04-21 12:06:28 +02:00
|
|
|
|
2023-03-13 21:46:59 +01:00
|
|
|
if (timing.sjw == CAN_SJW_NO_CHANGE) {
|
|
|
|
shell_print(sh, "setting data bitrate to %d bps, sample point %d.%d%% "
|
|
|
|
"(+/- %d.%d%%)",
|
|
|
|
bitrate, sample_pnt / 10, sample_pnt % 10, err / 10, err % 10);
|
|
|
|
} else {
|
|
|
|
shell_print(sh, "setting data bitrate to %d bps, sample point %d.%d%% "
|
|
|
|
"(+/- %d.%d%%), sjw %d",
|
|
|
|
bitrate, sample_pnt / 10, sample_pnt % 10, err / 10, err % 10,
|
|
|
|
timing.sjw);
|
|
|
|
}
|
2020-04-21 12:06:28 +02:00
|
|
|
|
2023-03-16 13:57:55 +01:00
|
|
|
LOG_DBG("sjw %u, prop_seg %u, phase_seg1 %u, phase_seg2 %u, prescaler %u",
|
|
|
|
timing.sjw, timing.prop_seg, timing.phase_seg1, timing.phase_seg2,
|
|
|
|
timing.prescaler);
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
err = can_set_timing_data(dev, &timing);
|
|
|
|
if (err != 0) {
|
|
|
|
shell_error(sh, "failed to set data timing (err %d)", err);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
shell_print(sh, "setting data bitrate to %d bps", bitrate);
|
2022-05-05 11:28:30 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
err = can_set_bitrate_data(dev, bitrate);
|
|
|
|
if (err != 0) {
|
|
|
|
shell_error(sh, "failed to set data bitrate (err %d)", err);
|
|
|
|
return err;
|
|
|
|
}
|
2020-04-21 12:06:28 +02:00
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
return 0;
|
|
|
|
}
|
2022-07-12 22:23:05 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
static int cmd_can_mode_set(const struct shell *sh, size_t argc, char **argv)
|
|
|
|
{
|
|
|
|
const struct device *dev = device_get_binding(argv[1]);
|
|
|
|
can_mode_t mode = CAN_MODE_NORMAL;
|
|
|
|
can_mode_t raw;
|
|
|
|
char *endptr;
|
|
|
|
int err;
|
|
|
|
int i;
|
|
|
|
int j;
|
2022-07-13 15:25:28 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
if (!device_is_ready(dev)) {
|
|
|
|
shell_error(sh, "device %s not ready", argv[1]);
|
|
|
|
return -ENODEV;
|
2020-04-27 18:58:05 +02:00
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
for (i = 2; i < argc; i++) {
|
|
|
|
/* Lookup symbolic mode name */
|
|
|
|
for (j = 0; j < ARRAY_SIZE(can_shell_mode_map); j++) {
|
|
|
|
if (strcmp(argv[i], can_shell_mode_map[j].name) == 0) {
|
|
|
|
mode |= can_shell_mode_map[j].mode;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (j == ARRAY_SIZE(can_shell_mode_map)) {
|
|
|
|
/* Symbolic name not found, use raw mode if hex number */
|
|
|
|
raw = (can_mode_t)strtoul(argv[i], &endptr, 16);
|
|
|
|
if (*endptr == '\0') {
|
|
|
|
mode |= raw;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
shell_error(sh, "failed to parse mode");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
2020-04-21 12:06:28 +02:00
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
shell_print(sh, "setting mode 0x%08x", mode);
|
|
|
|
|
|
|
|
err = can_set_mode(dev, mode);
|
|
|
|
if (err != 0) {
|
|
|
|
shell_error(sh, "failed to set mode 0x%08x (err %d)", mode, err);
|
|
|
|
return err;
|
2020-04-21 12:06:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
static int cmd_can_send(const struct shell *sh, size_t argc, char **argv)
|
2019-04-24 20:09:34 +02:00
|
|
|
{
|
2022-08-26 12:50:16 +02:00
|
|
|
const struct device *dev = device_get_binding(argv[1]);
|
|
|
|
static unsigned int frame_counter;
|
|
|
|
unsigned int frame_no;
|
2022-08-11 15:31:59 +02:00
|
|
|
struct can_frame frame;
|
2022-08-26 12:50:16 +02:00
|
|
|
uint32_t max_id;
|
|
|
|
int argidx = 2;
|
|
|
|
uint32_t val;
|
|
|
|
char *endptr;
|
|
|
|
int nbytes;
|
|
|
|
int err;
|
|
|
|
int i;
|
2019-04-24 20:09:34 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
if (!device_is_ready(dev)) {
|
|
|
|
shell_error(sh, "device %s not ready", argv[1]);
|
|
|
|
return -ENODEV;
|
2019-04-24 20:09:34 +02:00
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
/* Defaults */
|
|
|
|
max_id = CAN_MAX_STD_ID;
|
drivers: can: use flags fields for can_frame and can_filter structs
The can_frame and can_filter structs support a number of different flags
(standard/extended CAN ID type, Remote Transmission Request, CAN-FD format,
Bit Rate Switch, ...). Each of these flags is represented as a discrete bit
in the given structure.
This design pattern requires every user of these structs to initialize all
of these flags to either 0 or 1, which does not scale well for future flag
additions.
Some of these flags have associated enumerations to be used for assignment,
some do not. CAN drivers and protocols tend to rely on the logical value of
the flag instead of using the enumeration, leading to a very fragile
API. The enumerations are used inconsistently between the can_frame and
can_filter structures, which further complicates the API.
Instead, convert these flags to bitfields with separate flag definitions
for the can_frame and can_filter structures. This API allows for future
extensions without having to revisit existing users of the two
structures. Furthermore, this allows driver to easily check for unsupported
flags in the respective API calls.
As this change leads to the "id_mask" field of the can_filter to be the
only mask present in that structure, rename it to "mask" for simplicity.
Fixes: #50776
Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
2022-09-30 14:44:16 +02:00
|
|
|
frame.flags = 0;
|
2022-08-26 12:50:16 +02:00
|
|
|
frame.dlc = 0;
|
2019-04-24 20:09:34 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
/* Parse options */
|
|
|
|
while (argidx < argc && strncmp(argv[argidx], "-", 1) == 0) {
|
|
|
|
if (strcmp(argv[argidx], "--") == 0) {
|
|
|
|
argidx++;
|
|
|
|
break;
|
|
|
|
} else if (strcmp(argv[argidx], "-e") == 0) {
|
drivers: can: use flags fields for can_frame and can_filter structs
The can_frame and can_filter structs support a number of different flags
(standard/extended CAN ID type, Remote Transmission Request, CAN-FD format,
Bit Rate Switch, ...). Each of these flags is represented as a discrete bit
in the given structure.
This design pattern requires every user of these structs to initialize all
of these flags to either 0 or 1, which does not scale well for future flag
additions.
Some of these flags have associated enumerations to be used for assignment,
some do not. CAN drivers and protocols tend to rely on the logical value of
the flag instead of using the enumeration, leading to a very fragile
API. The enumerations are used inconsistently between the can_frame and
can_filter structures, which further complicates the API.
Instead, convert these flags to bitfields with separate flag definitions
for the can_frame and can_filter structures. This API allows for future
extensions without having to revisit existing users of the two
structures. Furthermore, this allows driver to easily check for unsupported
flags in the respective API calls.
As this change leads to the "id_mask" field of the can_filter to be the
only mask present in that structure, rename it to "mask" for simplicity.
Fixes: #50776
Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
2022-09-30 14:44:16 +02:00
|
|
|
frame.flags |= CAN_FRAME_IDE;
|
2022-08-26 12:50:16 +02:00
|
|
|
max_id = CAN_MAX_EXT_ID;
|
|
|
|
argidx++;
|
|
|
|
} else if (strcmp(argv[argidx], "-r") == 0) {
|
drivers: can: use flags fields for can_frame and can_filter structs
The can_frame and can_filter structs support a number of different flags
(standard/extended CAN ID type, Remote Transmission Request, CAN-FD format,
Bit Rate Switch, ...). Each of these flags is represented as a discrete bit
in the given structure.
This design pattern requires every user of these structs to initialize all
of these flags to either 0 or 1, which does not scale well for future flag
additions.
Some of these flags have associated enumerations to be used for assignment,
some do not. CAN drivers and protocols tend to rely on the logical value of
the flag instead of using the enumeration, leading to a very fragile
API. The enumerations are used inconsistently between the can_frame and
can_filter structures, which further complicates the API.
Instead, convert these flags to bitfields with separate flag definitions
for the can_frame and can_filter structures. This API allows for future
extensions without having to revisit existing users of the two
structures. Furthermore, this allows driver to easily check for unsupported
flags in the respective API calls.
As this change leads to the "id_mask" field of the can_filter to be the
only mask present in that structure, rename it to "mask" for simplicity.
Fixes: #50776
Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
2022-09-30 14:44:16 +02:00
|
|
|
frame.flags |= CAN_FRAME_RTR;
|
2022-08-26 12:50:16 +02:00
|
|
|
argidx++;
|
|
|
|
} else if (strcmp(argv[argidx], "-f") == 0) {
|
drivers: can: use flags fields for can_frame and can_filter structs
The can_frame and can_filter structs support a number of different flags
(standard/extended CAN ID type, Remote Transmission Request, CAN-FD format,
Bit Rate Switch, ...). Each of these flags is represented as a discrete bit
in the given structure.
This design pattern requires every user of these structs to initialize all
of these flags to either 0 or 1, which does not scale well for future flag
additions.
Some of these flags have associated enumerations to be used for assignment,
some do not. CAN drivers and protocols tend to rely on the logical value of
the flag instead of using the enumeration, leading to a very fragile
API. The enumerations are used inconsistently between the can_frame and
can_filter structures, which further complicates the API.
Instead, convert these flags to bitfields with separate flag definitions
for the can_frame and can_filter structures. This API allows for future
extensions without having to revisit existing users of the two
structures. Furthermore, this allows driver to easily check for unsupported
flags in the respective API calls.
As this change leads to the "id_mask" field of the can_filter to be the
only mask present in that structure, rename it to "mask" for simplicity.
Fixes: #50776
Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
2022-09-30 14:44:16 +02:00
|
|
|
frame.flags |= CAN_FRAME_FDF;
|
2022-08-26 12:50:16 +02:00
|
|
|
argidx++;
|
|
|
|
} else if (strcmp(argv[argidx], "-b") == 0) {
|
drivers: can: use flags fields for can_frame and can_filter structs
The can_frame and can_filter structs support a number of different flags
(standard/extended CAN ID type, Remote Transmission Request, CAN-FD format,
Bit Rate Switch, ...). Each of these flags is represented as a discrete bit
in the given structure.
This design pattern requires every user of these structs to initialize all
of these flags to either 0 or 1, which does not scale well for future flag
additions.
Some of these flags have associated enumerations to be used for assignment,
some do not. CAN drivers and protocols tend to rely on the logical value of
the flag instead of using the enumeration, leading to a very fragile
API. The enumerations are used inconsistently between the can_frame and
can_filter structures, which further complicates the API.
Instead, convert these flags to bitfields with separate flag definitions
for the can_frame and can_filter structures. This API allows for future
extensions without having to revisit existing users of the two
structures. Furthermore, this allows driver to easily check for unsupported
flags in the respective API calls.
As this change leads to the "id_mask" field of the can_filter to be the
only mask present in that structure, rename it to "mask" for simplicity.
Fixes: #50776
Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
2022-09-30 14:44:16 +02:00
|
|
|
frame.flags |= CAN_FRAME_BRS;
|
2022-08-26 12:50:16 +02:00
|
|
|
argidx++;
|
|
|
|
} else {
|
|
|
|
shell_error(sh, "unsupported option %s", argv[argidx]);
|
|
|
|
shell_help(sh);
|
|
|
|
return SHELL_CMD_HELP_PRINTED;
|
|
|
|
}
|
2019-04-24 20:09:34 +02:00
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
/* Parse CAN ID */
|
|
|
|
if (argidx >= argc) {
|
|
|
|
shell_error(sh, "missing CAN ID parameter");
|
|
|
|
shell_help(sh);
|
|
|
|
return SHELL_CMD_HELP_PRINTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
val = (uint32_t)strtoul(argv[argidx++], &endptr, 16);
|
|
|
|
if (*endptr != '\0') {
|
|
|
|
shell_error(sh, "failed to parse CAN ID");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
2019-04-24 20:09:34 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
if (val > max_id) {
|
|
|
|
shell_error(sh, "CAN ID 0x%0*x out of range",
|
drivers: can: use flags fields for can_frame and can_filter structs
The can_frame and can_filter structs support a number of different flags
(standard/extended CAN ID type, Remote Transmission Request, CAN-FD format,
Bit Rate Switch, ...). Each of these flags is represented as a discrete bit
in the given structure.
This design pattern requires every user of these structs to initialize all
of these flags to either 0 or 1, which does not scale well for future flag
additions.
Some of these flags have associated enumerations to be used for assignment,
some do not. CAN drivers and protocols tend to rely on the logical value of
the flag instead of using the enumeration, leading to a very fragile
API. The enumerations are used inconsistently between the can_frame and
can_filter structures, which further complicates the API.
Instead, convert these flags to bitfields with separate flag definitions
for the can_frame and can_filter structures. This API allows for future
extensions without having to revisit existing users of the two
structures. Furthermore, this allows driver to easily check for unsupported
flags in the respective API calls.
As this change leads to the "id_mask" field of the can_filter to be the
only mask present in that structure, rename it to "mask" for simplicity.
Fixes: #50776
Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
2022-09-30 14:44:16 +02:00
|
|
|
(frame.flags & CAN_FRAME_IDE) != 0 ? 8 : 3,
|
2022-08-26 12:50:16 +02:00
|
|
|
val);
|
2019-04-24 20:09:34 +02:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
frame.id = val;
|
2019-04-24 20:09:34 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
nbytes = argc - argidx;
|
|
|
|
if (nbytes > ARRAY_SIZE(frame.data)) {
|
|
|
|
shell_error(sh, "excessive amount of data (%d bytes)", nbytes);
|
2019-04-24 20:09:34 +02:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
frame.dlc = can_bytes_to_dlc(nbytes);
|
2019-04-24 20:09:34 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
/* Parse data */
|
|
|
|
for (i = 0; i < nbytes; i++) {
|
|
|
|
val = (uint32_t)strtoul(argv[argidx++], &endptr, 16);
|
|
|
|
if (*endptr != '\0') {
|
|
|
|
shell_error(sh, "failed to parse data %s", argv[argidx++]);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (val > 0xff) {
|
|
|
|
shell_error(sh, "data 0x%x out of range", val);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
frame.data[i] = val;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = can_shell_tx_msgq_poll_submit(sh);
|
|
|
|
if (err != 0) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
frame_no = frame_counter++;
|
|
|
|
|
|
|
|
shell_print(sh, "enqueuing CAN frame #%u with %s (%d-bit) CAN ID 0x%0*x, "
|
|
|
|
"RTR %d, CAN-FD %d, BRS %d, DLC %d", frame_no,
|
drivers: can: use flags fields for can_frame and can_filter structs
The can_frame and can_filter structs support a number of different flags
(standard/extended CAN ID type, Remote Transmission Request, CAN-FD format,
Bit Rate Switch, ...). Each of these flags is represented as a discrete bit
in the given structure.
This design pattern requires every user of these structs to initialize all
of these flags to either 0 or 1, which does not scale well for future flag
additions.
Some of these flags have associated enumerations to be used for assignment,
some do not. CAN drivers and protocols tend to rely on the logical value of
the flag instead of using the enumeration, leading to a very fragile
API. The enumerations are used inconsistently between the can_frame and
can_filter structures, which further complicates the API.
Instead, convert these flags to bitfields with separate flag definitions
for the can_frame and can_filter structures. This API allows for future
extensions without having to revisit existing users of the two
structures. Furthermore, this allows driver to easily check for unsupported
flags in the respective API calls.
As this change leads to the "id_mask" field of the can_filter to be the
only mask present in that structure, rename it to "mask" for simplicity.
Fixes: #50776
Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
2022-09-30 14:44:16 +02:00
|
|
|
(frame.flags & CAN_FRAME_IDE) != 0 ? "extended" : "standard",
|
|
|
|
(frame.flags & CAN_FRAME_IDE) != 0 ? 29 : 11,
|
|
|
|
(frame.flags & CAN_FRAME_IDE) != 0 ? 8 : 3, frame.id,
|
|
|
|
(frame.flags & CAN_FRAME_RTR) != 0 ? 1 : 0,
|
|
|
|
(frame.flags & CAN_FRAME_FDF) != 0 ? 1 : 0,
|
|
|
|
(frame.flags & CAN_FRAME_BRS) != 0 ? 1 : 0,
|
|
|
|
can_dlc_to_bytes(frame.dlc));
|
2022-08-26 12:50:16 +02:00
|
|
|
|
|
|
|
err = can_send(dev, &frame, K_NO_WAIT, can_shell_tx_callback, UINT_TO_POINTER(frame_no));
|
|
|
|
if (err != 0) {
|
|
|
|
shell_error(sh, "failed to enqueue CAN frame #%u (err %d)", frame_no, err);
|
|
|
|
return err;
|
2019-04-24 20:09:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
static int cmd_can_filter_add(const struct shell *sh, size_t argc, char **argv)
|
2019-04-24 20:09:34 +02:00
|
|
|
{
|
2022-08-26 12:50:16 +02:00
|
|
|
const struct device *dev = device_get_binding(argv[1]);
|
2022-08-11 15:31:59 +02:00
|
|
|
struct can_filter filter;
|
2022-08-26 12:50:16 +02:00
|
|
|
uint32_t max_id;
|
|
|
|
int argidx = 2;
|
|
|
|
uint32_t val;
|
|
|
|
char *endptr;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (!device_is_ready(dev)) {
|
|
|
|
shell_error(sh, "device %s not ready", argv[1]);
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Defaults */
|
|
|
|
max_id = CAN_MAX_STD_ID;
|
drivers: can: use flags fields for can_frame and can_filter structs
The can_frame and can_filter structs support a number of different flags
(standard/extended CAN ID type, Remote Transmission Request, CAN-FD format,
Bit Rate Switch, ...). Each of these flags is represented as a discrete bit
in the given structure.
This design pattern requires every user of these structs to initialize all
of these flags to either 0 or 1, which does not scale well for future flag
additions.
Some of these flags have associated enumerations to be used for assignment,
some do not. CAN drivers and protocols tend to rely on the logical value of
the flag instead of using the enumeration, leading to a very fragile
API. The enumerations are used inconsistently between the can_frame and
can_filter structures, which further complicates the API.
Instead, convert these flags to bitfields with separate flag definitions
for the can_frame and can_filter structures. This API allows for future
extensions without having to revisit existing users of the two
structures. Furthermore, this allows driver to easily check for unsupported
flags in the respective API calls.
As this change leads to the "id_mask" field of the can_filter to be the
only mask present in that structure, rename it to "mask" for simplicity.
Fixes: #50776
Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
2022-09-30 14:44:16 +02:00
|
|
|
filter.flags = CAN_FILTER_DATA;
|
2022-08-26 12:50:16 +02:00
|
|
|
|
|
|
|
/* Parse options */
|
|
|
|
while (argidx < argc && strncmp(argv[argidx], "-", 1) == 0) {
|
|
|
|
if (strcmp(argv[argidx], "--") == 0) {
|
|
|
|
argidx++;
|
|
|
|
break;
|
|
|
|
} else if (strcmp(argv[argidx], "-e") == 0) {
|
drivers: can: use flags fields for can_frame and can_filter structs
The can_frame and can_filter structs support a number of different flags
(standard/extended CAN ID type, Remote Transmission Request, CAN-FD format,
Bit Rate Switch, ...). Each of these flags is represented as a discrete bit
in the given structure.
This design pattern requires every user of these structs to initialize all
of these flags to either 0 or 1, which does not scale well for future flag
additions.
Some of these flags have associated enumerations to be used for assignment,
some do not. CAN drivers and protocols tend to rely on the logical value of
the flag instead of using the enumeration, leading to a very fragile
API. The enumerations are used inconsistently between the can_frame and
can_filter structures, which further complicates the API.
Instead, convert these flags to bitfields with separate flag definitions
for the can_frame and can_filter structures. This API allows for future
extensions without having to revisit existing users of the two
structures. Furthermore, this allows driver to easily check for unsupported
flags in the respective API calls.
As this change leads to the "id_mask" field of the can_filter to be the
only mask present in that structure, rename it to "mask" for simplicity.
Fixes: #50776
Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
2022-09-30 14:44:16 +02:00
|
|
|
filter.flags |= CAN_FILTER_IDE;
|
2022-08-26 12:50:16 +02:00
|
|
|
max_id = CAN_MAX_EXT_ID;
|
|
|
|
argidx++;
|
2023-03-07 10:53:51 +01:00
|
|
|
} else if (strcmp(argv[argidx], "-f") == 0) {
|
|
|
|
filter.flags |= CAN_FILTER_FDF;
|
|
|
|
argidx++;
|
2022-08-26 12:50:16 +02:00
|
|
|
} else if (strcmp(argv[argidx], "-r") == 0) {
|
drivers: can: use flags fields for can_frame and can_filter structs
The can_frame and can_filter structs support a number of different flags
(standard/extended CAN ID type, Remote Transmission Request, CAN-FD format,
Bit Rate Switch, ...). Each of these flags is represented as a discrete bit
in the given structure.
This design pattern requires every user of these structs to initialize all
of these flags to either 0 or 1, which does not scale well for future flag
additions.
Some of these flags have associated enumerations to be used for assignment,
some do not. CAN drivers and protocols tend to rely on the logical value of
the flag instead of using the enumeration, leading to a very fragile
API. The enumerations are used inconsistently between the can_frame and
can_filter structures, which further complicates the API.
Instead, convert these flags to bitfields with separate flag definitions
for the can_frame and can_filter structures. This API allows for future
extensions without having to revisit existing users of the two
structures. Furthermore, this allows driver to easily check for unsupported
flags in the respective API calls.
As this change leads to the "id_mask" field of the can_filter to be the
only mask present in that structure, rename it to "mask" for simplicity.
Fixes: #50776
Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
2022-09-30 14:44:16 +02:00
|
|
|
filter.flags |= CAN_FILTER_RTR;
|
2022-08-26 12:50:16 +02:00
|
|
|
argidx++;
|
|
|
|
} else if (strcmp(argv[argidx], "-R") == 0) {
|
drivers: can: use flags fields for can_frame and can_filter structs
The can_frame and can_filter structs support a number of different flags
(standard/extended CAN ID type, Remote Transmission Request, CAN-FD format,
Bit Rate Switch, ...). Each of these flags is represented as a discrete bit
in the given structure.
This design pattern requires every user of these structs to initialize all
of these flags to either 0 or 1, which does not scale well for future flag
additions.
Some of these flags have associated enumerations to be used for assignment,
some do not. CAN drivers and protocols tend to rely on the logical value of
the flag instead of using the enumeration, leading to a very fragile
API. The enumerations are used inconsistently between the can_frame and
can_filter structures, which further complicates the API.
Instead, convert these flags to bitfields with separate flag definitions
for the can_frame and can_filter structures. This API allows for future
extensions without having to revisit existing users of the two
structures. Furthermore, this allows driver to easily check for unsupported
flags in the respective API calls.
As this change leads to the "id_mask" field of the can_filter to be the
only mask present in that structure, rename it to "mask" for simplicity.
Fixes: #50776
Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
2022-09-30 14:44:16 +02:00
|
|
|
filter.flags &= ~(CAN_FILTER_DATA);
|
|
|
|
filter.flags |= CAN_FILTER_RTR;
|
2022-08-26 12:50:16 +02:00
|
|
|
argidx++;
|
|
|
|
} else {
|
|
|
|
shell_error(sh, "unsupported argument %s", argv[argidx]);
|
|
|
|
shell_help(sh);
|
|
|
|
return SHELL_CMD_HELP_PRINTED;
|
|
|
|
}
|
2019-04-24 20:09:34 +02:00
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
/* Parse CAN ID */
|
|
|
|
if (argidx >= argc) {
|
|
|
|
shell_error(sh, "missing CAN ID parameter");
|
|
|
|
shell_help(sh);
|
|
|
|
return SHELL_CMD_HELP_PRINTED;
|
|
|
|
}
|
2019-04-24 20:09:34 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
val = (uint32_t)strtoul(argv[argidx++], &endptr, 16);
|
|
|
|
if (*endptr != '\0') {
|
|
|
|
shell_error(sh, "failed to parse CAN ID");
|
2019-04-24 20:09:34 +02:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
if (val > max_id) {
|
|
|
|
shell_error(sh, "CAN ID 0x%0*x out of range",
|
drivers: can: use flags fields for can_frame and can_filter structs
The can_frame and can_filter structs support a number of different flags
(standard/extended CAN ID type, Remote Transmission Request, CAN-FD format,
Bit Rate Switch, ...). Each of these flags is represented as a discrete bit
in the given structure.
This design pattern requires every user of these structs to initialize all
of these flags to either 0 or 1, which does not scale well for future flag
additions.
Some of these flags have associated enumerations to be used for assignment,
some do not. CAN drivers and protocols tend to rely on the logical value of
the flag instead of using the enumeration, leading to a very fragile
API. The enumerations are used inconsistently between the can_frame and
can_filter structures, which further complicates the API.
Instead, convert these flags to bitfields with separate flag definitions
for the can_frame and can_filter structures. This API allows for future
extensions without having to revisit existing users of the two
structures. Furthermore, this allows driver to easily check for unsupported
flags in the respective API calls.
As this change leads to the "id_mask" field of the can_filter to be the
only mask present in that structure, rename it to "mask" for simplicity.
Fixes: #50776
Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
2022-09-30 14:44:16 +02:00
|
|
|
(filter.flags & CAN_FILTER_IDE) != 0 ? 8 : 3,
|
2022-08-26 12:50:16 +02:00
|
|
|
val);
|
2019-04-24 20:09:34 +02:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
filter.id = val;
|
2019-04-24 20:09:34 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
if (argidx < argc) {
|
|
|
|
/* Parse CAN ID mask */
|
|
|
|
val = (uint32_t)strtoul(argv[argidx++], &endptr, 16);
|
|
|
|
if (*endptr != '\0') {
|
|
|
|
shell_error(sh, "failed to parse CAN ID mask");
|
2019-04-24 20:09:34 +02:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
if (val > max_id) {
|
|
|
|
shell_error(sh, "CAN ID mask 0x%0*x out of range",
|
drivers: can: use flags fields for can_frame and can_filter structs
The can_frame and can_filter structs support a number of different flags
(standard/extended CAN ID type, Remote Transmission Request, CAN-FD format,
Bit Rate Switch, ...). Each of these flags is represented as a discrete bit
in the given structure.
This design pattern requires every user of these structs to initialize all
of these flags to either 0 or 1, which does not scale well for future flag
additions.
Some of these flags have associated enumerations to be used for assignment,
some do not. CAN drivers and protocols tend to rely on the logical value of
the flag instead of using the enumeration, leading to a very fragile
API. The enumerations are used inconsistently between the can_frame and
can_filter structures, which further complicates the API.
Instead, convert these flags to bitfields with separate flag definitions
for the can_frame and can_filter structures. This API allows for future
extensions without having to revisit existing users of the two
structures. Furthermore, this allows driver to easily check for unsupported
flags in the respective API calls.
As this change leads to the "id_mask" field of the can_filter to be the
only mask present in that structure, rename it to "mask" for simplicity.
Fixes: #50776
Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
2022-09-30 14:44:16 +02:00
|
|
|
(filter.flags & CAN_FILTER_IDE) != 0 ? 8 : 3,
|
2022-08-26 12:50:16 +02:00
|
|
|
val);
|
2019-04-24 20:09:34 +02:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
2022-08-26 12:50:16 +02:00
|
|
|
|
|
|
|
} else {
|
|
|
|
val = max_id;
|
2019-04-24 20:09:34 +02:00
|
|
|
}
|
|
|
|
|
drivers: can: use flags fields for can_frame and can_filter structs
The can_frame and can_filter structs support a number of different flags
(standard/extended CAN ID type, Remote Transmission Request, CAN-FD format,
Bit Rate Switch, ...). Each of these flags is represented as a discrete bit
in the given structure.
This design pattern requires every user of these structs to initialize all
of these flags to either 0 or 1, which does not scale well for future flag
additions.
Some of these flags have associated enumerations to be used for assignment,
some do not. CAN drivers and protocols tend to rely on the logical value of
the flag instead of using the enumeration, leading to a very fragile
API. The enumerations are used inconsistently between the can_frame and
can_filter structures, which further complicates the API.
Instead, convert these flags to bitfields with separate flag definitions
for the can_frame and can_filter structures. This API allows for future
extensions without having to revisit existing users of the two
structures. Furthermore, this allows driver to easily check for unsupported
flags in the respective API calls.
As this change leads to the "id_mask" field of the can_filter to be the
only mask present in that structure, rename it to "mask" for simplicity.
Fixes: #50776
Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
2022-09-30 14:44:16 +02:00
|
|
|
filter.mask = val;
|
2019-04-24 20:09:34 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
err = can_shell_rx_msgq_poll_submit(sh);
|
|
|
|
if (err != 0) {
|
|
|
|
return err;
|
|
|
|
}
|
2019-04-24 20:09:34 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
shell_print(sh, "adding filter with %s (%d-bit) CAN ID 0x%0*x, "
|
2023-03-07 10:53:51 +01:00
|
|
|
"CAN ID mask 0x%0*x, data frames %d, RTR frames %d, CAN-FD frames %d",
|
drivers: can: use flags fields for can_frame and can_filter structs
The can_frame and can_filter structs support a number of different flags
(standard/extended CAN ID type, Remote Transmission Request, CAN-FD format,
Bit Rate Switch, ...). Each of these flags is represented as a discrete bit
in the given structure.
This design pattern requires every user of these structs to initialize all
of these flags to either 0 or 1, which does not scale well for future flag
additions.
Some of these flags have associated enumerations to be used for assignment,
some do not. CAN drivers and protocols tend to rely on the logical value of
the flag instead of using the enumeration, leading to a very fragile
API. The enumerations are used inconsistently between the can_frame and
can_filter structures, which further complicates the API.
Instead, convert these flags to bitfields with separate flag definitions
for the can_frame and can_filter structures. This API allows for future
extensions without having to revisit existing users of the two
structures. Furthermore, this allows driver to easily check for unsupported
flags in the respective API calls.
As this change leads to the "id_mask" field of the can_filter to be the
only mask present in that structure, rename it to "mask" for simplicity.
Fixes: #50776
Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
2022-09-30 14:44:16 +02:00
|
|
|
(filter.flags & CAN_FILTER_IDE) != 0 ? "extended" : "standard",
|
|
|
|
(filter.flags & CAN_FILTER_IDE) != 0 ? 29 : 11,
|
|
|
|
(filter.flags & CAN_FILTER_IDE) != 0 ? 8 : 3, filter.id,
|
|
|
|
(filter.flags & CAN_FILTER_IDE) != 0 ? 8 : 3, filter.mask,
|
|
|
|
(filter.flags & CAN_FILTER_DATA) != 0 ? 1 : 0,
|
2023-03-07 10:53:51 +01:00
|
|
|
(filter.flags & CAN_FILTER_RTR) != 0 ? 1 : 0,
|
|
|
|
(filter.flags & CAN_FILTER_FDF) != 0 ? 1 : 0);
|
2019-04-24 20:09:34 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
err = can_add_rx_filter_msgq(dev, &can_shell_rx_msgq, &filter);
|
|
|
|
if (err < 0) {
|
|
|
|
shell_error(sh, "failed to add filter (err %d)", err);
|
|
|
|
return err;
|
2019-04-24 20:09:34 +02:00
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
shell_print(sh, "filter ID: %d", err);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int cmd_can_filter_remove(const struct shell *sh, size_t argc, char **argv)
|
|
|
|
{
|
|
|
|
const struct device *dev = device_get_binding(argv[1]);
|
|
|
|
int filter_id;
|
|
|
|
char *endptr;
|
2019-04-24 20:09:34 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
if (!device_is_ready(dev)) {
|
|
|
|
shell_error(sh, "device %s not ready", argv[1]);
|
|
|
|
return -ENODEV;
|
2021-12-16 12:13:33 +01:00
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
/* Parse filter ID */
|
|
|
|
filter_id = (int)strtol(argv[2], &endptr, 10);
|
|
|
|
if (*endptr != '\0') {
|
|
|
|
shell_error(sh, "failed to parse filter ID");
|
|
|
|
return -EINVAL;
|
2021-12-16 12:13:33 +01:00
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
shell_print(sh, "removing filter with ID %d", filter_id);
|
|
|
|
can_remove_rx_filter(dev, filter_id);
|
|
|
|
|
2019-04-24 20:09:34 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
static int cmd_can_recover(const struct shell *sh, size_t argc, char **argv)
|
2019-04-24 20:09:34 +02:00
|
|
|
{
|
2022-08-26 12:50:16 +02:00
|
|
|
const struct device *dev = device_get_binding(argv[1]);
|
|
|
|
k_timeout_t timeout = K_FOREVER;
|
|
|
|
int millisec;
|
|
|
|
char *endptr;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (!device_is_ready(dev)) {
|
|
|
|
shell_error(sh, "device %s not ready", argv[1]);
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (argc >= 3) {
|
|
|
|
/* Parse timeout */
|
|
|
|
millisec = (int)strtol(argv[2], &endptr, 10);
|
|
|
|
if (*endptr != '\0') {
|
|
|
|
shell_error(sh, "failed to parse timeout");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
timeout = K_MSEC(millisec);
|
|
|
|
shell_print(sh, "recovering, timeout %d ms", millisec);
|
|
|
|
} else {
|
|
|
|
shell_print(sh, "recovering, no timeout");
|
2019-04-24 20:09:34 +02:00
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
err = can_recover(dev, timeout);
|
|
|
|
if (err != 0) {
|
|
|
|
shell_error(sh, "failed to recover CAN controller from bus-off (err %d)", err);
|
|
|
|
return err;
|
2019-04-24 20:09:34 +02:00
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void cmd_can_device_name(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_can_device_name, cmd_can_device_name);
|
|
|
|
|
|
|
|
static void cmd_can_mode(size_t idx, struct shell_static_entry *entry);
|
|
|
|
|
|
|
|
SHELL_DYNAMIC_CMD_CREATE(dsub_can_mode, cmd_can_mode);
|
|
|
|
|
|
|
|
static void cmd_can_mode(size_t idx, struct shell_static_entry *entry)
|
|
|
|
{
|
|
|
|
if (idx < ARRAY_SIZE(can_shell_mode_map)) {
|
|
|
|
entry->syntax = can_shell_mode_map[idx].name;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
entry->syntax = NULL;
|
2019-04-24 20:09:34 +02:00
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
entry->handler = NULL;
|
|
|
|
entry->help = NULL;
|
|
|
|
entry->subcmd = &dsub_can_mode;
|
|
|
|
}
|
2019-04-24 20:09:34 +02:00
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
static void cmd_can_device_name_mode(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 = &dsub_can_mode;
|
2019-04-24 20:09:34 +02:00
|
|
|
}
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
SHELL_DYNAMIC_CMD_CREATE(dsub_can_device_name_mode, cmd_can_device_name_mode);
|
|
|
|
|
|
|
|
SHELL_STATIC_SUBCMD_SET_CREATE(sub_can_filter_cmds,
|
|
|
|
SHELL_CMD_ARG(add, &dsub_can_device_name,
|
|
|
|
"Add rx filter\n"
|
2023-03-07 10:53:51 +01:00
|
|
|
"Usage: can filter add <device> [-e] [-f] [-r] [-R] <CAN ID> [CAN ID mask]\n"
|
2022-08-26 12:50:16 +02:00
|
|
|
"-e use extended (29-bit) CAN ID/CAN ID mask\n"
|
2023-03-07 10:53:51 +01:00
|
|
|
"-f match CAN-FD format frames\n"
|
drivers: can: use flags fields for can_frame and can_filter structs
The can_frame and can_filter structs support a number of different flags
(standard/extended CAN ID type, Remote Transmission Request, CAN-FD format,
Bit Rate Switch, ...). Each of these flags is represented as a discrete bit
in the given structure.
This design pattern requires every user of these structs to initialize all
of these flags to either 0 or 1, which does not scale well for future flag
additions.
Some of these flags have associated enumerations to be used for assignment,
some do not. CAN drivers and protocols tend to rely on the logical value of
the flag instead of using the enumeration, leading to a very fragile
API. The enumerations are used inconsistently between the can_frame and
can_filter structures, which further complicates the API.
Instead, convert these flags to bitfields with separate flag definitions
for the can_frame and can_filter structures. This API allows for future
extensions without having to revisit existing users of the two
structures. Furthermore, this allows driver to easily check for unsupported
flags in the respective API calls.
As this change leads to the "id_mask" field of the can_filter to be the
only mask present in that structure, rename it to "mask" for simplicity.
Fixes: #50776
Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
2022-09-30 14:44:16 +02:00
|
|
|
"-r also match Remote Transmission Request (RTR) frames\n"
|
|
|
|
"-R only match Remote Transmission Request (RTR) frames",
|
2023-03-07 10:53:51 +01:00
|
|
|
cmd_can_filter_add, 3, 5),
|
2022-08-26 12:50:16 +02:00
|
|
|
SHELL_CMD_ARG(remove, &dsub_can_device_name,
|
|
|
|
"Remove rx filter\n"
|
|
|
|
"Usage: can filter remove <device> <filter_id>",
|
|
|
|
cmd_can_filter_remove, 3, 0),
|
|
|
|
SHELL_SUBCMD_SET_END
|
|
|
|
);
|
|
|
|
|
|
|
|
SHELL_STATIC_SUBCMD_SET_CREATE(sub_can_cmds,
|
2022-08-31 14:40:55 +02:00
|
|
|
SHELL_CMD_ARG(start, &dsub_can_device_name,
|
|
|
|
"Start CAN controller\n"
|
|
|
|
"Usage: can start <device>",
|
|
|
|
cmd_can_start, 2, 0),
|
|
|
|
SHELL_CMD_ARG(stop, &dsub_can_device_name,
|
|
|
|
"Stop CAN controller\n"
|
|
|
|
"Usage: can stop <device>",
|
|
|
|
cmd_can_stop, 2, 0),
|
2022-08-26 12:54:41 +02:00
|
|
|
SHELL_CMD_ARG(show, &dsub_can_device_name,
|
|
|
|
"Show CAN controller information\n"
|
|
|
|
"Usage: can show <device>",
|
|
|
|
cmd_can_show, 2, 0),
|
2022-08-26 12:50:16 +02:00
|
|
|
SHELL_CMD_ARG(bitrate, &dsub_can_device_name,
|
2023-03-13 21:46:59 +01:00
|
|
|
"Set CAN controller bitrate (sample point and SJW optional)\n"
|
|
|
|
"Usage: can bitrate <device> <bitrate> [sample point] [sjw]",
|
|
|
|
cmd_can_bitrate_set, 3, 2),
|
2022-08-26 12:50:16 +02:00
|
|
|
SHELL_COND_CMD_ARG(CONFIG_CAN_FD_MODE,
|
|
|
|
dbitrate, &dsub_can_device_name,
|
2023-03-13 21:46:59 +01:00
|
|
|
"Set CAN controller data phase bitrate (sample point and SJW optional)\n"
|
|
|
|
"Usage: can dbitrate <device> <data phase bitrate> [sample point] [sjw]",
|
|
|
|
cmd_can_dbitrate_set, 3, 2),
|
2022-08-26 12:50:16 +02:00
|
|
|
SHELL_CMD_ARG(mode, &dsub_can_device_name_mode,
|
|
|
|
"Set CAN controller mode\n"
|
|
|
|
"Usage: can mode <device> <mode> [mode] [mode] [...]",
|
|
|
|
cmd_can_mode_set, 3, SHELL_OPT_ARG_CHECK_SKIP),
|
|
|
|
SHELL_CMD_ARG(send, &dsub_can_device_name,
|
|
|
|
"Enqueue a CAN frame for sending\n"
|
|
|
|
"Usage: can send <device> [-e] [-r] [-f] [-b] <CAN ID> [data] [...]\n"
|
|
|
|
"-e use extended (29-bit) CAN ID\n"
|
|
|
|
"-r send Remote Transmission Request (RTR) frame\n"
|
|
|
|
"-f use CAN-FD frame format\n"
|
|
|
|
"-b use CAN-FD Bit Rate Switching (BRS)",
|
|
|
|
cmd_can_send, 3, SHELL_OPT_ARG_CHECK_SKIP),
|
|
|
|
SHELL_CMD(filter, &sub_can_filter_cmds,
|
|
|
|
"CAN rx filter commands\n"
|
|
|
|
"Usage: can filter <add|remove> <device> ...",
|
|
|
|
NULL),
|
|
|
|
SHELL_EXPR_CMD_ARG(!IS_ENABLED(CONFIG_CAN_AUTO_BUS_OFF_RECOVERY),
|
|
|
|
recover, &dsub_can_device_name,
|
|
|
|
"Recover CAN controller from bus-off state\n"
|
|
|
|
"Usage: can recover <device> [timeout ms]",
|
|
|
|
cmd_can_recover, 2, 1),
|
|
|
|
SHELL_SUBCMD_SET_END
|
2019-04-24 20:09:34 +02:00
|
|
|
);
|
|
|
|
|
2022-08-26 12:50:16 +02:00
|
|
|
SHELL_CMD_REGISTER(can, &sub_can_cmds, "CAN controller commands", NULL);
|