]> rtime.felk.cvut.cz Git - socketcan-devel.git/blob - kernel/2.6/drivers/net/can/usb/ctu_usbcan.c
7142b199c9e158be0ab34646d5509009e37e8a38
[socketcan-devel.git] / kernel / 2.6 / drivers / net / can / usb / ctu_usbcan.c
1 #include <linux/kernel.h>
2 #include <linux/errno.h>
3 #include <linux/init.h>
4 #include <linux/slab.h>
5 #include <linux/module.h>
6 #include <linux/kref.h>
7 #include <linux/uaccess.h>
8 #include <linux/usb.h>
9 #include <linux/mutex.h>
10 #include <linux/netdevice.h>
11 #include <linux/version.h>
12
13 #include <linux/can.h>
14 #include <linux/can/dev.h>
15 #include <linux/can/error.h>
16
17 #define CTU_USBCAN_VENDOR_ID    0x1669
18 #define CTU_USBCAN_PRODUCT_ID   0x1011
19
20 #define USBCAN_TOT_RX_URBS 8
21 #define USBCAN_TOT_TX_URBS 8
22
23 #define USBCAN_TRANSFER_SIZE 16
24
25
26 #define CAN_MSG_LENGTH 8
27 /* Definitions to use for canmsg_t and canfilt_t flags */
28 #define MSG_RTR   (1<<0)
29 #define MSG_OVR   (1<<1)
30 #define MSG_EXT   (1<<2)
31 #define MSG_LOCAL (1<<3)
32
33 MODULE_LICENSE("GPL");
34
35 /* table of devices that work with this driver */
36 static struct usb_device_id ctu_usbcan_table [] = {
37         { USB_DEVICE(CTU_USBCAN_VENDOR_ID, CTU_USBCAN_PRODUCT_ID) },
38         { }                                     /* Terminating entry */
39 };
40 MODULE_DEVICE_TABLE(usb, ctu_usbcan_table);
41
42
43 static struct usb_driver ctu_usbcan_driver;
44 struct ctu_usbcan_usb;
45
46
47 struct usbcan_message {
48         struct urb      *u;
49         struct ctu_usbcan_usb *dev;
50         u8      msg[USBCAN_TRANSFER_SIZE];
51         u8      dlc;
52 };
53 /*
54 Structure of byte array msg in struct usbcan_message that represens CAN message (little endian):
55         msg[0] - reserved (1 byte)
56         msg[1] - length (1 byte)
57         msg[2:3] - flags (2 bytes)
58         msg[4:7] - id (4 bytes)
59         msg[8:15] - data (8 bytes)
60
61 */
62
63
64 /* Structure to hold all of our device specific stuff */
65 struct ctu_usbcan_usb {
66
67         struct can_priv can; /* must be the first member */
68
69         struct usb_device *udev;                        /* the usb device for this device */
70         struct net_device *netdev;
71
72         u8 bulk_in_endpointAddr;        /* the address of the bulk in endpoint */
73         u8 bulk_out_endpointAddr;       /* the address of the bulk out endpoint */
74 };
75
76
77
78 static void ctu_usbcan_tx_callback(struct urb *urb){
79
80         struct usbcan_message *m = urb->context;
81         struct net_device_stats *stats = &m->dev->netdev->stats;
82
83         if (!netif_device_present(m->dev->netdev))
84                 return;
85
86         printk("TX callback: URB successfully transmitted\n");
87
88         stats->tx_packets++;
89         stats->tx_bytes += m->dlc;
90
91
92 }
93
94 static void ctu_usbcan_rx_callback(struct urb *urb)
95 {
96         struct can_frame *cf;
97         struct sk_buff *skb;
98         struct usbcan_message *m = urb->context;
99         u8 *ptr;
100         int i, len;
101         u16 flags = 0;
102         struct net_device_stats *stats = &m->dev->netdev->stats;
103
104         if (!netif_device_present(m->dev->netdev))
105                 return;
106
107
108 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,32)
109         skb = alloc_can_skb(m->dev->netdev, &cf);
110 #else
111         skb = netdev_alloc_skb(m->dev->netdev, sizeof(struct can_frame)); 
112         skb->protocol = htons(ETH_P_CAN);
113         cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
114 #endif
115
116         if (skb == NULL){
117                 err("RX callback: error alloc skb\n");
118                 return;
119         }
120
121         if(urb->status != 0){
122                 err("RX callback: error");
123                 return;
124         }
125
126         /* success */
127         
128         printk("RX callback: URB successfully received\n");
129
130         len=*(u8 *)(m->msg+1);
131         if(len > CAN_MSG_LENGTH) len = CAN_MSG_LENGTH;
132
133         flags = le16_to_cpu(*(u16 *)(m->msg+2));
134         cf->can_id = le32_to_cpu((*(u32 *)(m->msg+4)));
135
136         if (flags & MSG_RTR)
137                 cf->can_id |= CAN_RTR_FLAG;
138
139         if (flags & MSG_EXT)
140                 cf->can_id |= CAN_EFF_FLAG;
141
142         cf->can_dlc = len;
143
144         for(ptr=m->msg+8,i=0; i < len; ptr++,i++) {
145                 cf->data[i]=*ptr;
146         }
147
148
149         netif_rx(skb);
150
151         stats->rx_packets++;
152         stats->rx_bytes += cf->can_dlc;
153
154 }
155
156 static netdev_tx_t ctu_usbcan_start_xmit(struct sk_buff *skb, struct net_device *netdev)
157 {
158         struct ctu_usbcan_usb *dev = netdev_priv(netdev);
159         struct can_frame *cf = (struct can_frame *)skb->data;
160         int i, retval, len;
161         u8 *ptr;
162         u16 flags = 0;
163         
164         /* Prepare transmit urb  */
165         struct usbcan_message *m;
166         struct urb *u = usb_alloc_urb(0, GFP_ATOMIC);
167
168         if (!u){
169                 err("Error allocating usb transmit urb");
170                 goto exit;
171         }
172
173         m = kzalloc(sizeof(struct usbcan_message), GFP_ATOMIC);
174         if(!m) {
175                 usb_free_urb(u);
176                 err("Error allocating transmit usbcan_message");
177                 goto exit;
178         }
179         m->u = u;
180         u->dev = dev->udev;
181         m->dev = dev;
182
183         /* naplneni     */
184
185         len = cf->can_dlc;
186         if(len > CAN_MSG_LENGTH)
187                 len = CAN_MSG_LENGTH;
188
189         if (cf->can_id & CAN_RTR_FLAG)
190                 flags |= MSG_RTR;
191
192         if (cf->can_id & CAN_EFF_FLAG)
193                 flags |= MSG_EXT;
194
195         *(u8 *)(m->msg)=0;
196         *(u8 *)(m->msg+1)=len & 0xFF;
197         *(u16 *)(m->msg+2)=cpu_to_le16(flags);
198         *(u32 *)(m->msg+4)=cpu_to_le32(cf->can_id & CAN_ERR_MASK);
199
200         for(ptr=m->msg+8, i=0; i < len; ptr++,i++)
201                 *ptr= cf->data[i] & 0xFF;
202                 
203         for(; i < 8; ptr++,i++)
204                 *ptr=0;
205
206
207         m->dlc = (u8) len;
208
209         /* odeslani */
210
211         usb_fill_bulk_urb(u, dev->udev,
212                 usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
213                 m->msg, USBCAN_TRANSFER_SIZE, ctu_usbcan_tx_callback, m);
214
215
216         retval = usb_submit_urb(m->u, GFP_ATOMIC);
217         if (retval){
218                 err("Error submitting URB: %d", retval);
219                 goto exit;
220         }
221         
222
223 exit:
224
225         usb_free_urb(u);
226
227         return NETDEV_TX_OK;
228
229 }
230
231 static int ctu_usbcan_open(struct net_device *netdev)
232 {
233
234         struct ctu_usbcan_usb *dev = netdev_priv(netdev);
235         int retval;
236
237
238         /* Prepare receive urb  */
239         struct usbcan_message *m;
240         struct urb *u;
241
242         printk("CTU USBCAN: opening device\n");
243
244         u = usb_alloc_urb(0, GFP_KERNEL);
245         if (!u){
246                 err("Error allocating usb receive urb");
247                 goto exit;
248         }
249
250         m = kzalloc(sizeof(struct usbcan_message), GFP_KERNEL);
251         if(!m) {
252                 usb_free_urb(u);
253                 err("Error allocating receive usbcan_message");
254                 goto exit;
255         }
256         m->u = u;
257         u->dev = dev->udev;
258         m->dev = dev;
259         usb_fill_bulk_urb(u, dev->udev,
260                 usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr),
261                 m->msg, USBCAN_TRANSFER_SIZE, ctu_usbcan_rx_callback, m);
262
263
264         retval=usb_submit_urb(m->u, GFP_KERNEL);
265         if (retval){
266                 err("Error submitting URB: %d", retval);
267                 goto exit;
268         }
269
270 exit:
271         usb_free_urb(u);
272
273         return 0;
274 }
275
276 static int ctu_usbcan_close(struct net_device *netdev)
277 {
278         
279         return 0;
280 }
281
282 static const struct net_device_ops ctu_usbcan_netdev_ops = {
283         .ndo_open = ctu_usbcan_open,
284         .ndo_stop = ctu_usbcan_close,
285         .ndo_start_xmit = ctu_usbcan_start_xmit,
286 };
287
288 static int ctu_usbcan_probe(struct usb_interface *intf,
289                                                         const struct usb_device_id *id)
290 {
291         struct net_device *netdev;
292         struct ctu_usbcan_usb *dev;
293         struct usb_host_interface *iface_desc;
294         struct usb_endpoint_descriptor *endpoint;
295         int i;
296         int err = -ENOMEM;
297
298         printk(KERN_INFO "CTU USBCAN device now attached\n");
299
300 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,32)
301         netdev = alloc_candev(sizeof(struct ctu_usbcan_usb), USBCAN_TOT_TX_URBS);
302 #else
303         netdev = alloc_candev(sizeof(struct ctu_usbcan_usb));
304 #endif
305
306         if (!netdev) {
307 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,33)
308                 dev_err(&intf->dev, "Couldn't alloc candev\n");
309 #else
310                 dev_err(netdev->dev.parent, "Couldn't alloc candev\n");
311 #endif
312                 return -ENOMEM;
313         }
314
315         dev = netdev_priv(netdev);
316
317         dev->udev = interface_to_usbdev(intf);
318         dev->netdev = netdev;
319
320         netdev->netdev_ops = &ctu_usbcan_netdev_ops;
321         netdev->flags |= IFF_ECHO;
322
323         /* set up the endpoint information */
324         /* use only the first bulk-in and bulk-out endpoints */
325         iface_desc = intf->cur_altsetting;
326         for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
327                 endpoint = &iface_desc->endpoint[i].desc;
328
329                 if (!dev->bulk_in_endpointAddr &&
330                     usb_endpoint_is_bulk_in(endpoint)) {
331                         /* we found a bulk in endpoint */
332                         dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
333                 }
334
335                 if (!dev->bulk_out_endpointAddr &&
336                     usb_endpoint_is_bulk_out(endpoint)) {
337                         /* we found a bulk out endpoint */
338                         dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;
339                 }
340         }
341         if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) {
342                 err("Could not find both bulk-in and bulk-out endpoints");
343                 goto exit;
344         }
345
346
347         usb_set_intfdata(intf, dev);
348         SET_NETDEV_DEV(netdev, &intf->dev);
349
350
351         err = register_candev(netdev);
352         if (err) {
353                 dev_err(netdev->dev.parent,
354                         "couldn't register CAN device: %d\n", err);
355         }
356
357 exit:
358
359         return 0;
360 }
361
362 /* called by the usb core when the device is removed from the system */
363 static void ctu_usbcan_disconnect(struct usb_interface *intf)
364 {
365
366         struct ctu_usbcan_usb *dev = usb_get_intfdata(intf);
367
368         printk(KERN_INFO "CTU USBCAN device now disconnected\n");
369
370         usb_set_intfdata(intf, NULL);
371
372         if (dev) {
373                 unregister_netdev(dev->netdev);
374                 free_candev(dev->netdev);
375         }
376
377 }
378
379 /* usb specific object needed to register this driver with the usb subsystem */
380 static struct usb_driver ctu_usbcan_driver = {
381         .name = "ctu_usbcan",
382         .id_table =     ctu_usbcan_table,
383         .probe =        ctu_usbcan_probe,
384         .disconnect =   ctu_usbcan_disconnect,
385 };
386
387 static int __init ctu_usbcan_init(void)
388 {
389         int result;
390
391         printk(KERN_INFO "CTU USBCAN kernel driver loaded\n");
392
393         /* register this driver with the USB subsystem */
394         result = usb_register(&ctu_usbcan_driver);
395         if (result)
396                 err("usb_register failed. Error number %d", result);
397
398         return result;
399 }
400
401 static void __exit ctu_usbcan_exit(void)
402 {
403         printk(KERN_INFO "CTU USBCAN kernel driver unloaded\n");
404
405         /* deregister this driver with the USB subsystem */
406         usb_deregister(&ctu_usbcan_driver);
407 }
408
409 module_init(ctu_usbcan_init);
410 module_exit(ctu_usbcan_exit);
411