recipes-kernel: update driver recipes
[AGL/meta-agl-demo.git] / recipes-kernel / mocca-usb / _files / mocca_usb.c
1 /*
2  * USB Skeleton driver - 2.2
3  *
4  * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
5  *
6  *      This program is free software; you can redistribute it and/or
7  *      modify it under the terms of the GNU General Public License as
8  *      published by the Free Software Foundation, version 2.
9  *
10  * This driver is based on the 2.6.3 version of drivers/usb/usb-skeleton.c 
11  * but has been rewritten to be easier to read and use.
12  *
13  */
14
15 #include <linux/kernel.h>
16 #include <linux/errno.h>
17 #include <linux/init.h>
18 #include <linux/slab.h>
19 #include <linux/module.h>
20 #include <linux/kref.h>
21 #include <linux/uaccess.h>
22 #include <linux/usb.h>
23 #include <linux/mutex.h>
24 #include <linux/spinlock.h>
25
26
27 /* Define these values to match your devices */
28 #define USB_MOCCA_VENDOR_ID     0x184f
29 #define USB_MOCCA_PRODUCT_ID_1  0x0007
30 #define USB_MOCCA_PRODUCT_ID_2  0x0008
31 #define USB_MOCCA_PRODUCT_ID_3  0x0009
32 #define USB_MOCCA_PRODUCT_ID_4  0x0010
33 #define USB_MOCCA_PRODUCT_ID_5  0x0011
34 #define USB_MOCCA_PRODUCT_ID_6  0x0012
35
36 /* table of devices that work with this driver */
37 static const struct usb_device_id mocca_table[] = {
38         { USB_DEVICE(USB_MOCCA_VENDOR_ID, USB_MOCCA_PRODUCT_ID_1) },
39         { USB_DEVICE(USB_MOCCA_VENDOR_ID, USB_MOCCA_PRODUCT_ID_2) },
40         { USB_DEVICE(USB_MOCCA_VENDOR_ID, USB_MOCCA_PRODUCT_ID_3) },
41         { USB_DEVICE(USB_MOCCA_VENDOR_ID, USB_MOCCA_PRODUCT_ID_4) },
42         { USB_DEVICE(USB_MOCCA_VENDOR_ID, USB_MOCCA_PRODUCT_ID_5) },
43         { USB_DEVICE(USB_MOCCA_VENDOR_ID, USB_MOCCA_PRODUCT_ID_6) },
44         { }                                     /* Terminating entry */
45 };
46 MODULE_DEVICE_TABLE (usb, mocca_table);
47
48
49 /* Get a minor range for your devices from the usb maintainer */
50 #define USB_MOCCA_MINOR_BASE    221 /*TODO: change this minor number */
51
52 /* our private defines. if this grows any larger, use your own .h file */
53 #define MAX_TRANSFER            ( PAGE_SIZE - 512 )
54 #define WRITES_IN_FLIGHT        8
55
56 /* Structure to hold all of our device specific stuff */
57 struct mocca_skel {
58         struct usb_device *     udev;                   /* the usb device for this device */
59         struct usb_interface *  interface;              /* the interface for this device */
60         struct semaphore        limit_sem;              /* limiting the number of writes in progress */
61         unsigned char *         bulk_in_buffer;         /* the buffer to receive data */
62         size_t                  bulk_in_size;           /* the size of the receive buffer */
63         __u8                    bulk_in_endpointAddr;   /* the address of the bulk in endpoint */
64         __u8                    bulk_out_endpointAddr;  /* the address of the bulk out endpoint */
65         struct kref             kref;
66 };
67 #define to_mocca_dev(d) container_of(d, struct mocca_skel, kref)
68
69 static struct usb_driver mocca_driver;
70 static spinlock_t spinLock;
71
72 static void mocca_delete(struct kref *kref)
73 {       
74         struct mocca_skel *dev = to_mocca_dev(kref);
75
76         usb_put_dev(dev->udev);
77         kfree (dev->bulk_in_buffer);
78         kfree (dev);
79 }
80
81 static int mocca_open(struct inode *inode, struct file *file)
82 {
83         struct mocca_skel *dev;
84         struct usb_interface *interface;
85         int subminor;
86         int retval = 0;
87
88         subminor = iminor(inode);
89
90         interface = usb_find_interface(&mocca_driver, subminor);
91         if (!interface) {
92                 printk(KERN_ERR "%s - error, can't find device for minor %d",
93                      __FUNCTION__, subminor);
94                 retval = -ENODEV;
95                 goto exit;
96         }
97
98         dev = usb_get_intfdata(interface);
99         if (!dev) {
100                 retval = -ENODEV;
101                 goto exit;
102         }
103
104         /* increment our usage count for the device */
105         kref_get(&dev->kref);
106
107         /* save our object in the file's private structure */
108         file->private_data = dev;
109
110 exit:
111         return retval;
112 }
113
114 static int mocca_release(struct inode *inode, struct file *file)
115 {
116         struct mocca_skel *dev;
117
118         dev = (struct mocca_skel *)file->private_data;
119         if (dev == NULL)
120                 return -ENODEV;
121
122         /* decrement the count on our device */
123         kref_put(&dev->kref, mocca_delete);
124         return 0;
125 }
126
127 static ssize_t mocca_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
128 {
129         struct mocca_skel *dev;
130         int retval = 0;
131         int bytes_read;
132
133         dev = (struct mocca_skel *)file->private_data;
134         
135         /* do a blocking bulk read to get data from the device */
136         retval = usb_bulk_msg(dev->udev,
137                               usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr),
138                               dev->bulk_in_buffer,
139                               min(dev->bulk_in_size, count),
140                               &bytes_read, 10000);
141
142         /* if the read was successful, copy the data to userspace */
143         if (!retval) {
144                 if (copy_to_user(buffer, dev->bulk_in_buffer, bytes_read))
145                         retval = -EFAULT;
146                 else
147                         retval = bytes_read;
148         }
149
150         return retval;
151 }
152
153 static void mocca_write_bulk_callback(struct urb *urb)
154 {
155         struct mocca_skel *dev;
156
157         dev = (struct mocca_skel *)urb->context;
158
159         /* sync/async unlink faults aren't errors */
160         if (urb->status && 
161             !(urb->status == -ENOENT || 
162               urb->status == -ECONNRESET ||
163               urb->status == -ESHUTDOWN)) {
164                 printk(KERN_ERR "%s - nonzero write bulk status received: %d",
165                     __FUNCTION__, urb->status);
166         }
167
168         /* free up our allocated buffer */
169         usb_free_coherent(urb->dev, urb->transfer_buffer_length, 
170                         urb->transfer_buffer, urb->transfer_dma);
171         up(&dev->limit_sem);
172 }
173
174 static ssize_t mocca_write(struct file *file, const char *user_buffer, size_t count, loff_t *ppos)
175 {
176         struct mocca_skel *dev;
177         int retval = 0;
178         struct urb *urb = NULL;
179         char *buf = NULL;
180         size_t writesize = min(count, (size_t)MAX_TRANSFER);
181
182         dev = (struct mocca_skel *)file->private_data;
183
184         /* verify that we actually have some data to write */
185         if (count == 0)
186                 goto exit;
187
188         /* limit the number of URBs in flight to stop a user from using up all RAM */
189         if (down_interruptible(&dev->limit_sem)) {
190                 retval = -ERESTARTSYS;
191                 goto exit;
192         }
193
194         /* create a urb, and a buffer for it, and copy the data to the urb */
195         urb = usb_alloc_urb(0, GFP_KERNEL);
196         if (!urb) {
197                 retval = -ENOMEM;
198                 goto error;
199         }
200
201         buf = usb_alloc_coherent(dev->udev, writesize, GFP_KERNEL, &urb->transfer_dma);
202         if (!buf) {
203                 retval = -ENOMEM;
204                 goto error;
205         }
206
207         if (copy_from_user(buf, user_buffer, writesize)) {
208                 retval = -EFAULT;
209                 goto error;
210         }
211
212         /* initialize the urb properly */
213         usb_fill_bulk_urb(urb, dev->udev,
214                           usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
215                           buf, writesize, mocca_write_bulk_callback, dev);
216         urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
217
218         /* send the data out the bulk port */
219         retval = usb_submit_urb(urb, GFP_KERNEL);
220         if (retval) {
221                 printk(KERN_ERR "%s - failed submitting write urb, error %d", __FUNCTION__, retval);
222                 goto error;
223         }
224
225         /* release our reference to this urb, the USB core will eventually free it entirely */
226         usb_free_urb(urb);
227
228 exit:
229         return writesize;
230
231 error:
232         usb_free_coherent(dev->udev, writesize, buf, urb->transfer_dma);
233         usb_free_urb(urb);
234         up(&dev->limit_sem);
235         return retval;
236 }
237
238 static struct file_operations mocca_fops = {
239         .owner =        THIS_MODULE,
240         .read =         mocca_read,
241         .write =        mocca_write,
242         .open =         mocca_open,
243         .release =      mocca_release,
244 };
245
246 /* 
247  * usb class driver info in order to get a minor number from the usb core,
248  * and to have the device registered with the driver core
249  */
250 static struct usb_class_driver mocca_class = {
251         .name =         "mocca%d",
252         .fops =         &mocca_fops,
253         .minor_base =   USB_MOCCA_MINOR_BASE,
254 };
255
256 static int mocca_probe(struct usb_interface *interface, const struct usb_device_id *id)
257 {
258         struct mocca_skel *dev = NULL;
259         struct usb_host_interface *iface_desc;
260         struct usb_endpoint_descriptor *endpoint;
261         size_t buffer_size;
262         int i;
263         int retval = -ENOMEM;
264
265         spin_lock_init(&spinLock);
266         
267         /* allocate memory for our device state and initialize it */
268         dev = kzalloc(sizeof(*dev), GFP_KERNEL);
269         if (dev == NULL) {
270                 printk(KERN_ERR "Out of memory");
271                 goto error;
272         }
273         kref_init(&dev->kref);
274         sema_init(&dev->limit_sem, WRITES_IN_FLIGHT);
275
276         dev->udev = usb_get_dev(interface_to_usbdev(interface));
277         dev->interface = interface;
278
279         /* set up the endpoint information */
280         /* use only the first bulk-in and bulk-out endpoints */
281         iface_desc = interface->cur_altsetting;
282         for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
283                 endpoint = &iface_desc->endpoint[i].desc;
284
285                 if (!dev->bulk_in_endpointAddr &&
286                     ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
287                                         == USB_DIR_IN) &&
288                     ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
289                                         == USB_ENDPOINT_XFER_BULK)) {
290                         /* we found a bulk in endpoint */
291                         buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
292                         dev->bulk_in_size = buffer_size;
293                         dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
294                         dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
295                         if (!dev->bulk_in_buffer) {
296                                 printk(KERN_ERR "Could not allocate bulk_in_buffer");
297                                 goto error;
298                         }
299                         printk(KERN_INFO "Found bulk-in pipe, adress: %x, max packet size: %d", endpoint->bEndpointAddress, endpoint->wMaxPacketSize);
300                 }
301
302                 if (!dev->bulk_out_endpointAddr &&
303                     ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
304                                         == USB_DIR_OUT) &&
305                     ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
306                                         == USB_ENDPOINT_XFER_BULK)) {
307                         /* we found a bulk out endpoint */
308                         dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;
309                     printk(KERN_INFO "Found bulk-out pipe, adress: %x, max packet size: %d", endpoint->bEndpointAddress, endpoint->wMaxPacketSize);
310                 }
311         }
312         if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) {
313                 printk(KERN_ERR "Could not find both bulk-in and bulk-out endpoints");
314                 goto error;
315         }
316
317         /* save our data pointer in this interface device */
318         usb_set_intfdata(interface, dev);
319
320         /* we can register the device now, as it is ready */
321         retval = usb_register_dev(interface, &mocca_class);
322         if (retval) {
323                 /* something prevented us from registering this driver */
324                 printk(KERN_ERR "Not able to get a minor for this device.");
325                 usb_set_intfdata(interface, NULL);
326                 goto error;
327         }
328
329         /* let the user know what node this device is now attached to */
330         dev_info(&interface->dev,
331                  "K2L MOCCA device now attached to mocca%d",
332                  interface->minor);
333         return 0;
334
335 error:
336         if (dev)
337                 kref_put(&dev->kref, mocca_delete);
338         return retval;
339 }
340
341 static void mocca_disconnect(struct usb_interface *interface)
342 {
343         struct mocca_skel *dev;
344         int minor = interface->minor;
345
346         /* prevent mocca_open() from racing mocca_disconnect() */
347         spin_lock(&spinLock);
348
349         dev = usb_get_intfdata(interface);
350         usb_set_intfdata(interface, NULL);
351
352         /* give back our minor */
353         usb_deregister_dev(interface, &mocca_class);
354
355         spin_unlock(&spinLock);
356
357         /* decrement our usage count */
358         kref_put(&dev->kref, mocca_delete);
359
360         dev_info(&interface->dev, "K2L MOCCA device #%d now disconnected", minor);
361 }
362
363 static struct usb_driver mocca_driver = {
364         .name =         "k2l-mocca",
365         .probe =        mocca_probe,
366         .disconnect =   mocca_disconnect,
367         .id_table =     mocca_table,
368 };
369
370 static int __init usb_mocca_init(void)
371 {
372         int result;
373
374         /* register this driver with the USB subsystem */
375         result = usb_register(&mocca_driver);
376         if (result)
377                 printk(KERN_ERR "usb_register failed. Error number %d", result);
378
379         return result;
380 }
381
382 static void __exit usb_mocca_exit(void)
383 {
384         /* deregister this driver with the USB subsystem */
385         usb_deregister(&mocca_driver);
386 }
387
388 module_init (usb_mocca_init);
389 module_exit (usb_mocca_exit);
390
391 MODULE_LICENSE("GPL");