#include #include #include #include #include #include #define USB_CAN_VENDOR 0xffff #define USB_CAN_PRODUCT 0xffff struct usb_can_priv { struct can_priv can; struct usb_device *udev; struct usb_interface *intf; struct net_device *netdev; u8 ep_in; u8 ep_out; struct urb *rx_urb; u8 *rx_buf; }; static void usb_can_rx_callback(struct urb *urb) { struct usb_can_priv *priv = urb->context; struct net_device *netdev = priv->netdev; struct sk_buff *skb; struct can_frame *cf; if (urb->status) return; skb = alloc_can_skb(netdev, &cf); if (!skb) goto resubmit; memcpy(cf, urb->transfer_buffer, sizeof(struct can_frame)); netif_rx(skb); resubmit: usb_submit_urb(urb, GFP_ATOMIC); } static int usb_can_open(struct net_device *netdev) { struct usb_can_priv *priv = netdev_priv(netdev); priv->rx_urb = usb_alloc_urb(0, GFP_KERNEL); priv->rx_buf = kmalloc(64, GFP_KERNEL); usb_fill_bulk_urb(priv->rx_urb, priv->udev, usb_rcvbulkpipe(priv->udev, priv->ep_in), priv->rx_buf, 64, usb_can_rx_callback, priv); usb_submit_urb(priv->rx_urb, GFP_KERNEL); netif_start_queue(netdev); return 0; } static int usb_can_stop(struct net_device *netdev) { struct usb_can_priv *priv = netdev_priv(netdev); netif_stop_queue(netdev); usb_kill_urb(priv->rx_urb); usb_free_urb(priv->rx_urb); kfree(priv->rx_buf); return 0; } static netdev_tx_t usb_can_start_xmit(struct sk_buff *skb, struct net_device *netdev) { struct usb_can_priv *priv = netdev_priv(netdev); struct can_frame *cf = (struct can_frame *)skb->data; int actual_length; usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, priv->ep_out), cf, sizeof(struct can_frame), &actual_length, 1000); dev_kfree_skb(skb); return NETDEV_TX_OK; } static const struct net_device_ops usb_can_netdev_ops = { .ndo_open = usb_can_open, .ndo_stop = usb_can_stop, .ndo_start_xmit = usb_can_start_xmit, }; static int usb_can_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct net_device *netdev; struct usb_can_priv *priv; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *ep; int i; iface_desc = intf->cur_altsetting; /* 只绑定 data interface */ if (iface_desc->desc.bInterfaceNumber != 1) return -ENODEV; netdev = alloc_candev(sizeof(struct usb_can_priv), 1); if (!netdev) return -ENOMEM; priv = netdev_priv(netdev); priv->udev = usb_get_dev(interface_to_usbdev(intf)); priv->intf = intf; priv->netdev = netdev; for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { ep = &iface_desc->endpoint[i].desc; if (usb_endpoint_is_bulk_in(ep)) priv->ep_in = ep->bEndpointAddress; if (usb_endpoint_is_bulk_out(ep)) priv->ep_out = ep->bEndpointAddress; } netdev->netdev_ops = &usb_can_netdev_ops; priv->can.clock.freq = 48000000; SET_NETDEV_DEV(netdev, &intf->dev); register_candev(netdev); usb_set_intfdata(intf, priv); printk("usb_can_simple: device connected\n"); return 0; } static void usb_can_disconnect(struct usb_interface *intf) { struct usb_can_priv *priv = usb_get_intfdata(intf); unregister_candev(priv->netdev); free_candev(priv->netdev); printk("usb_can_simple: device disconnected\n"); } static struct usb_device_id usb_can_id_table[] = { { USB_DEVICE(USB_CAN_VENDOR, USB_CAN_PRODUCT) }, { } }; MODULE_DEVICE_TABLE(usb, usb_can_id_table); static struct usb_driver usb_can_driver = { .name = "usb_can_simple", .probe = usb_can_probe, .disconnect = usb_can_disconnect, .id_table = usb_can_id_table, }; module_usb_driver(usb_can_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("demo"); MODULE_DESCRIPTION("Simple USB CAN driver");