[PATCH 14/17] can: ems_usb: Added code to handle CAN FD frames in ems_usb_start_xmit

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Signed-off-by: Gerhard Uttenthaler <uttenthaler@xxxxxxxxxxxxxxxx>
---
 drivers/net/can/usb/ems_usb.c | 61 ++++++++++++++++++++++++++++++++---
 1 file changed, 57 insertions(+), 4 deletions(-)

diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c
index c3159ffaa4fa..c36f02eeec85 100644
--- a/drivers/net/can/usb/ems_usb.c
+++ b/drivers/net/can/usb/ems_usb.c
@@ -73,8 +73,9 @@ MODULE_LICENSE("GPL v2");
 #define CPC_OVR_HW 0x80
 
 /* Size of the "struct ems_cpc_msg" without the union */
-#define CPC_MSG_HEADER_LEN   11
-#define CPC_CAN_MSG_MIN_SIZE 5
+#define CPC_MSG_HEADER_LEN     11
+#define CPC_CAN_MSG_MIN_SIZE    5
+#define CPC_CANFD_MSG_MIN_SIZE  6
 
 /* Define these values to match your devices */
 #define USB_CPCUSB_VENDOR_ID 0x12D6
@@ -909,8 +910,60 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne
 	size_t buf_len = CPC_HEADER_SIZE + CPC_MSG_HEADER_LEN;
 
 	if (can_is_canfd_skb(skb)) {
-		// Placeholder for next patch
-		return NETDEV_TX_OK;
+		struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
+		struct cpc_canfd_msg *fd_msg;
+
+		if (can_dropped_invalid_skb(netdev, skb))
+			return NETDEV_TX_OK;
+
+		buf_size = CPC_HEADER_SIZE +
+			   CPC_MSG_HEADER_LEN +
+			   sizeof(struct cpc_canfd_msg);
+
+		/* Create an URB and a buffer big enough for
+		 * all message lengths, copy the data to the URB
+		 */
+		urb = usb_alloc_urb(0, GFP_ATOMIC);
+		if (!urb)
+			goto nomem;
+
+		buf = usb_alloc_coherent(dev->udev,
+					 buf_size,
+					 GFP_ATOMIC,
+					 &urb->transfer_dma);
+		if (!buf) {
+			netdev_err(netdev, "No memory left for USB buffer\n");
+			usb_free_urb(urb);
+			goto nomem;
+		}
+		// Clear first 4 bytes
+		*(u32 *)buf = 0;
+
+		msg = (struct ems_cpc_msg *)&buf[CPC_HEADER_SIZE];
+		fd_msg = &msg->msg.canfd_msg;
+
+		msg->type = CPC_CMD_TYPE_CANFD_FRAME;
+
+		fd_msg->id = cpu_to_le32(cfd->can_id & CAN_ERR_MASK);
+		dlc = cfd->len;
+		fd_msg->length = dlc;
+		fd_msg->flags = 0;
+
+		if (cfd->can_id & CAN_EFF_FLAG)
+			fd_msg->flags |= CPC_FDFLAG_XTD;
+
+		if (cfd->flags & CANFD_BRS)
+			fd_msg->flags |= CPC_FDFLAG_BRS;
+
+		if (cfd->flags & CANFD_ESI)
+			fd_msg->flags |= CPC_FDFLAG_ESI;
+
+		for (i = 0; i < cfd->len; i++)
+			fd_msg->msg[i] = cfd->data[i];
+
+		msg->length = CPC_CANFD_MSG_MIN_SIZE + cfd->len;
+		// Send only significant bytes of buffer
+		buf_len += msg->length;
 	} else {
 		struct can_frame *cf = (struct can_frame *)skb->data;
 
-- 
2.26.2

-- 
EMS Dr. Thomas Wuensche e.K.
Sonnenhang 3
85304 Ilmmuenster
HR Ingolstadt, HRA 170106

Phone: +49-8441-490260
Fax  : +49-8441-81860
http://www.ems-wuensche.com



[Index of Archives]     [Automotive Discussions]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]     [CAN Bus]

  Powered by Linux