]> rtime.felk.cvut.cz Git - socketcan-devel.git/commitdiff
Network device (e.g. can0) is created when the device has been attached.
authorJiri Vanek <vanekjir@fel.cvut.cz>
Fri, 9 Mar 2012 15:53:50 +0000 (16:53 +0100)
committerJiri Vanek <vanekjir@fel.cvut.cz>
Fri, 9 Mar 2012 15:53:50 +0000 (16:53 +0100)
kernel/2.6/drivers/net/can/usb/ctu_usbcan.c

index 78f672e0897bdbec1ca4fda024ce8ecd13f9a8a2..42bb6984c29f5ba0ebdad1d6039391b313227475 100644 (file)
@@ -7,11 +7,17 @@
 #include <linux/uaccess.h>
 #include <linux/usb.h>
 #include <linux/mutex.h>
+#include <linux/netdevice.h>
+#include <linux/version.h>
 
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include <linux/can/error.h>
 
 #define CTU_USBCAN_VENDOR_ID   0x1669
 #define CTU_USBCAN_PRODUCT_ID  0x1011
 
+MODULE_LICENSE("GPL");
 
 /* table of devices that work with this driver */
 static struct usb_device_id ctu_usbcan_table [] = {
@@ -23,21 +29,91 @@ MODULE_DEVICE_TABLE(usb, ctu_usbcan_table);
 
 static struct usb_driver ctu_usbcan_driver;
 
+/* Structure to hold all of our device specific stuff */
+struct ctu_usbcan_usb {
+
+       struct can_priv can; /* must be the first member */
+
+       struct usb_device *udev;                        /* the usb device for this device */
+       struct net_device *netdev;
+};
+
+static int ctu_usbcan_open(struct net_device *netdev)
+{
+       return 0;
+}
+
+static int ctu_usbcan_close(struct net_device *netdev)
+{
+       return 0;
+}
+
+static const struct net_device_ops ctu_usbcan_netdev_ops = {
+       .ndo_open = ctu_usbcan_open,
+       .ndo_stop = ctu_usbcan_close,
+};
 
-static int ctu_usbcan_probe(struct usb_interface *interface, const struct usb_device_id *id)
+static int ctu_usbcan_probe(struct usb_interface *intf,
+                                                       const struct usb_device_id *id)
 {
+       struct net_device *netdev;
+       struct ctu_usbcan_usb *dev;
+       int err = -ENOMEM;
 
        printk(KERN_INFO "CTU USBCAN device now attached\n");
 
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,32)
+       netdev = alloc_candev(sizeof(struct ctu_usbcan_usb), MAX_TX_URBS);
+#else
+       netdev = alloc_candev(sizeof(struct ctu_usbcan_usb));
+#endif
+
+       if (!netdev) {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,32)
+               dev_err(&intf->dev, "ems_usb: Couldn't alloc candev\n");
+#else
+               dev_err(netdev->dev.parent, "Couldn't alloc candev\n");
+#endif
+               return -ENOMEM;
+       }
+
+       dev = netdev_priv(netdev);
+
+       dev->udev = interface_to_usbdev(intf);
+       dev->netdev = netdev;
+
+
+       netdev->netdev_ops = &ctu_usbcan_netdev_ops;
+       netdev->flags |= IFF_ECHO;
+
+       usb_set_intfdata(intf, dev);
+       SET_NETDEV_DEV(netdev, &intf->dev);
+
+
+       err = register_candev(netdev);
+       if (err) {
+               dev_err(netdev->dev.parent,
+                       "couldn't register CAN device: %d\n", err);
+       }
+
        return 0;
 }
 
 /* called by the usb core when the device is removed from the system */
-static void ctu_usbcan_disconnect(struct usb_interface *interface)
+static void ctu_usbcan_disconnect(struct usb_interface *intf)
 {
 
+       struct ctu_usbcan_usb *dev = usb_get_intfdata(intf);
+
        printk(KERN_INFO "CTU USBCAN device now disconnected\n");
 
+       usb_set_intfdata(intf, NULL);
+
+       if (dev) {
+               unregister_netdev(dev->netdev);
+               free_candev(dev->netdev);
+       }
+
 }
 
 /* usb specific object needed to register this driver with the usb subsystem */
@@ -73,4 +149,3 @@ static void __exit ctu_usbcan_exit(void)
 module_init(ctu_usbcan_init);
 module_exit(ctu_usbcan_exit);
 
-MODULE_LICENSE("GPL");