This is an automated email from the ASF dual-hosted git repository.
acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 6cdd3eaf46e drivers/can: Use 8 data bytes for classic messages with
DLC 9..15.
6cdd3eaf46e is described below
commit 6cdd3eaf46e79484770fe30bb3c181fed1943968
Author: raiden00pl <[email protected]>
AuthorDate: Fri Oct 23 09:18:18 2026 +0200
drivers/can: Use 8 data bytes for classic messages with DLC 9..15.
The character driver took the data length of every message from
can_dlc2bytes(), which with CONFIG_CAN_FD gives 12..64 bytes for DLC
9..15, also for classic frames. write() of such a classic message with
its 8 data bytes then returned 0 without sending it, and can_receive()
copied up to 64 bytes from the 8-byte data of a classic lower half.
Use the CAN FD length only when ch_edl is set and 8 bytes otherwise;
the DLC itself is kept. ctucanfd_pci, kvaser_pci and sim_canchar copy
8 bytes for these frames too.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: raiden00pl <[email protected]>
---
arch/sim/src/sim/sim_canchar.c | 5 ++++-
drivers/can/can.c | 41 ++++++++++++++++++++++++++++-------------
drivers/can/ctucanfd_pci.c | 15 ++++++++++++++-
drivers/can/kvaser_pci.c | 22 ++++++++++++++--------
4 files changed, 60 insertions(+), 23 deletions(-)
diff --git a/arch/sim/src/sim/sim_canchar.c b/arch/sim/src/sim/sim_canchar.c
index 49c574c7ecd..a3c50552750 100644
--- a/arch/sim/src/sim/sim_canchar.c
+++ b/arch/sim/src/sim/sim_canchar.c
@@ -26,6 +26,7 @@
#include <nuttx/debug.h>
#include <stdio.h>
+#include <sys/param.h>
#include <time.h>
#include <nuttx/clock.h>
@@ -226,8 +227,10 @@ static int sim_can_send(struct can_dev_s *dev, struct
can_msg_s *msg)
{
struct can_frame frame;
+ /* DLC 9..15 of a classic frame means 8 data bytes */
+
frame.can_id = msg->cm_hdr.ch_id;
- frame.can_dlc = msg->cm_hdr.ch_dlc;
+ frame.can_dlc = MIN(msg->cm_hdr.ch_dlc, CAN_MAX_DLEN);
if (msg->cm_hdr.ch_rtr)
{
diff --git a/drivers/can/can.c b/drivers/can/can.c
index d01647dcac0..887318bd440 100644
--- a/drivers/can/can.c
+++ b/drivers/can/can.c
@@ -44,6 +44,7 @@
#include <nuttx/clock.h>
#include <nuttx/signal.h>
#include <nuttx/fs/fs.h>
+#include <nuttx/can.h>
#include <nuttx/can/can.h>
#include <nuttx/can/can_sender.h>
#include <nuttx/kmalloc.h>
@@ -120,6 +121,7 @@ static int can_ioctl(FAR struct file *filep, int
cmd,
static int can_poll(FAR struct file *filep,
FAR struct pollfd *fds,
bool setup);
+static int can_datalen(FAR const struct can_hdr_s *hdr);
/****************************************************************************
* Private Data
@@ -142,6 +144,27 @@ static const struct file_operations g_canops =
* Private Functions
****************************************************************************/
+/****************************************************************************
+ * Name: can_datalen
+ *
+ * Description:
+ * Return the number of data bytes of a CAN message. The DLC codes 9..15
+ * mean 12..64 bytes in a CAN FD frame but 8 bytes in a classic frame.
+ *
+ ****************************************************************************/
+
+static int can_datalen(FAR const struct can_hdr_s *hdr)
+{
+#ifdef CONFIG_CAN_FD
+ if (hdr->ch_edl)
+ {
+ return can_dlc2bytes(hdr->ch_dlc);
+ }
+#endif
+
+ return MIN(hdr->ch_dlc, CAN_MAX_DLEN);
+}
+
/****************************************************************************
* Name: can_txready_work
*
@@ -513,7 +536,7 @@ static ssize_t can_read(FAR struct file *filep, FAR char
*buffer,
/* Will the next message in the FIFO fit into the user buffer? */
FAR struct can_msg_s *msg = &fifo->rx_buffer[fifo->rx_head];
- int nbytes = can_dlc2bytes(msg->cm_hdr.ch_dlc);
+ int nbytes = can_datalen(&msg->cm_hdr);
int msglen = CAN_MSGLEN(nbytes);
if (ret + msglen > buflen)
@@ -806,7 +829,7 @@ static ssize_t can_write(FAR struct file *filep, FAR const
char *buffer,
}
else
{
- nbytes = can_dlc2bytes(msg->cm_hdr.ch_dlc);
+ nbytes = can_datalen(&msg->cm_hdr);
}
msglen = CAN_MSGLEN(nbytes);
@@ -1379,7 +1402,7 @@ int can_receive(FAR struct can_dev_s *dev, FAR struct
can_hdr_s *hdr,
memcpy(&waitmsg->cm_hdr, hdr, sizeof(struct can_hdr_s));
- nbytes = can_dlc2bytes(hdr->ch_dlc);
+ nbytes = can_datalen(hdr);
if (nbytes)
{
memcpy(waitmsg->cm_data, data, nbytes);
@@ -1413,20 +1436,12 @@ int can_receive(FAR struct can_dev_s *dev, FAR struct
can_hdr_s *hdr,
{
int nbytes;
- /* Add the new, decoded CAN message at the tail of the FIFO.
- *
- * REVISIT: In the CAN FD format, the coding of the DLC differs
- * from the standard CAN format. The DLC codes 0 to 8 have the
- * same coding as in standard CAN, the codes 9 to 15, which in
- * standard CAN all code a data field of 8 bytes, are encoded:
- *
- * 9->12, 10->16, 11->20, 12->24, 13->32, 14->48, 15->64
- */
+ /* Add the new, decoded CAN message at the tail of the FIFO */
memcpy(&fifo->rx_buffer[fifo->rx_tail].cm_hdr, hdr,
sizeof(struct can_hdr_s));
- nbytes = can_dlc2bytes(hdr->ch_dlc);
+ nbytes = can_datalen(hdr);
if (nbytes)
{
memcpy(fifo->rx_buffer[fifo->rx_tail].cm_data, data, nbytes);
diff --git a/drivers/can/ctucanfd_pci.c b/drivers/can/ctucanfd_pci.c
index a8b92c8fe3d..af4ab1004f5 100644
--- a/drivers/can/ctucanfd_pci.c
+++ b/drivers/can/ctucanfd_pci.c
@@ -37,6 +37,7 @@
#include <nuttx/pci/pci.h>
#ifdef CONFIG_CAN_CTUCANFD_CHARDEV
+# include <nuttx/can.h>
# include <nuttx/can/can.h>
#endif
@@ -636,7 +637,19 @@ static int ctucanfd_chrdev_send(FAR struct can_dev_s *dev,
ctucanfd_putreg(priv, offset + CTUCANFD_TXBUF_TSL, 0);
ctucanfd_putreg(priv, offset + CTUCANFD_TXBUF_TSU, 0);
- bytes = can_dlc2bytes(msg->cm_hdr.ch_dlc);
+ /* DLC 9..15 of a classic frame carry 8 data bytes */
+
+#ifdef CONFIG_CAN_FD
+ if (msg->cm_hdr.ch_edl)
+ {
+ bytes = can_dlc2bytes(msg->cm_hdr.ch_dlc);
+ }
+ else
+#endif
+ {
+ bytes = MIN(msg->cm_hdr.ch_dlc, CAN_MAX_DLEN);
+ }
+
for (i = 0; i < bytes; i++)
{
ctucanfd_putreg(priv, offset + CTUCANFD_TXBUF_DATA + i,
diff --git a/drivers/can/kvaser_pci.c b/drivers/can/kvaser_pci.c
index 7e2760f54f8..1b7118ccf04 100644
--- a/drivers/can/kvaser_pci.c
+++ b/drivers/can/kvaser_pci.c
@@ -30,12 +30,14 @@
#include <nuttx/debug.h>
#include <errno.h>
#include <stdio.h>
+#include <sys/param.h>
#include <nuttx/arch.h>
#include <nuttx/kmalloc.h>
#include <nuttx/pci/pci.h>
#ifdef CONFIG_CAN_KVASER_CHARDEV
+# include <nuttx/can.h>
# include <nuttx/can/can.h>
#endif
@@ -660,21 +662,20 @@ static int kvaser_chrdev_send(FAR struct can_dev_s *dev,
return -EBUSY;
}
- /* Get data bytes for this frame */
-
- bytes = can_dlc2bytes(msg->cm_hdr.ch_dlc);
-
#ifdef CONFIG_CAN_FD
/* Drop CAN FD frames */
- if (bytes > 8 || msg->cm_hdr.ch_edl ||
- msg->cm_hdr.ch_brs || msg->cm_hdr.ch_esi)
+ if (msg->cm_hdr.ch_edl || msg->cm_hdr.ch_brs || msg->cm_hdr.ch_esi)
{
canerr("ERROR: CAN FD frames not supported\n");
return -ENOTSUP;
}
#endif
+ /* Get data bytes for this frame, DLC 9..15 means 8 bytes */
+
+ bytes = MIN(msg->cm_hdr.ch_dlc, CAN_MAX_DLEN);
+
/* Set up the DLC */
fi = msg->cm_hdr.ch_dlc;
@@ -852,12 +853,17 @@ static void kvaser_chardev_receive(FAR struct
kvaser_sja_s *priv)
#ifdef CONFIG_CAN_ERRORS
hdr.ch_error = 0;
+#endif
+#ifdef CONFIG_CAN_FD
+ hdr.ch_edl = 0;
+ hdr.ch_brs = 0;
+ hdr.ch_esi = 0;
#endif
hdr.ch_tcf = 0;
- /* Get data */
+ /* Get data, DLC 9..15 means 8 bytes */
- for (i = 0; i < can_dlc2bytes(hdr.ch_dlc); i++)
+ for (i = 0; i < MIN(hdr.ch_dlc, CAN_MAX_DLEN); i++)
{
data[i] = kvaser_getreg_sja(priv, dreg + i);
}