Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
usblcd.c
Go to the documentation of this file.
1 /*****************************************************************************
2  * USBLCD Kernel Driver *
3  * Version 1.05 *
4  * (C) 2005 Georges Toth <[email protected]> *
5  * *
6  * This file is licensed under the GPL. See COPYING in the package. *
7  * Based on usb-skeleton.c 2.0 by Greg Kroah-Hartman ([email protected]) *
8  * *
9  * *
10  * 28.02.05 Complete rewrite of the original usblcd.c driver, *
11  * based on usb_skeleton.c. *
12  * This new driver allows more than one USB-LCD to be connected *
13  * and controlled, at once *
14  *****************************************************************************/
15 #include <linux/module.h>
16 #include <linux/kernel.h>
17 #include <linux/init.h>
18 #include <linux/slab.h>
19 #include <linux/errno.h>
20 #include <linux/mutex.h>
21 #include <linux/uaccess.h>
22 #include <linux/usb.h>
23 
24 #define DRIVER_VERSION "USBLCD Driver Version 1.05"
25 
26 #define USBLCD_MINOR 144
27 
28 #define IOCTL_GET_HARD_VERSION 1
29 #define IOCTL_GET_DRV_VERSION 2
30 
31 
32 static DEFINE_MUTEX(lcd_mutex);
33 static const struct usb_device_id id_table[] = {
34  { .idVendor = 0x10D2, .match_flags = USB_DEVICE_ID_MATCH_VENDOR, },
35  { },
36 };
37 MODULE_DEVICE_TABLE(usb, id_table);
38 
39 static DEFINE_MUTEX(open_disc_mutex);
40 
41 
42 struct usb_lcd {
43  struct usb_device *udev; /* init: probe_lcd */
44  struct usb_interface *interface; /* the interface for
45  this device */
46  unsigned char *bulk_in_buffer; /* the buffer to receive
47  data */
48  size_t bulk_in_size; /* the size of the
49  receive buffer */
50  __u8 bulk_in_endpointAddr; /* the address of the
51  bulk in endpoint */
52  __u8 bulk_out_endpointAddr; /* the address of the
53  bulk out endpoint */
54  struct kref kref;
55  struct semaphore limit_sem; /* to stop writes at
56  full throttle from
57  using up all RAM */
58  struct usb_anchor submitted; /* URBs to wait for
59  before suspend */
60 };
61 #define to_lcd_dev(d) container_of(d, struct usb_lcd, kref)
62 
63 #define USB_LCD_CONCURRENT_WRITES 5
64 
65 static struct usb_driver lcd_driver;
66 
67 
68 static void lcd_delete(struct kref *kref)
69 {
70  struct usb_lcd *dev = to_lcd_dev(kref);
71 
72  usb_put_dev(dev->udev);
73  kfree(dev->bulk_in_buffer);
74  kfree(dev);
75 }
76 
77 
78 static int lcd_open(struct inode *inode, struct file *file)
79 {
80  struct usb_lcd *dev;
81  struct usb_interface *interface;
82  int subminor, r;
83 
84  mutex_lock(&lcd_mutex);
85  subminor = iminor(inode);
86 
87  interface = usb_find_interface(&lcd_driver, subminor);
88  if (!interface) {
89  mutex_unlock(&lcd_mutex);
90  printk(KERN_ERR "USBLCD: %s - error, can't find device for minor %d\n",
91  __func__, subminor);
92  return -ENODEV;
93  }
94 
95  mutex_lock(&open_disc_mutex);
96  dev = usb_get_intfdata(interface);
97  if (!dev) {
98  mutex_unlock(&open_disc_mutex);
99  mutex_unlock(&lcd_mutex);
100  return -ENODEV;
101  }
102 
103  /* increment our usage count for the device */
104  kref_get(&dev->kref);
105  mutex_unlock(&open_disc_mutex);
106 
107  /* grab a power reference */
108  r = usb_autopm_get_interface(interface);
109  if (r < 0) {
110  kref_put(&dev->kref, lcd_delete);
111  mutex_unlock(&lcd_mutex);
112  return r;
113  }
114 
115  /* save our object in the file's private structure */
116  file->private_data = dev;
117  mutex_unlock(&lcd_mutex);
118 
119  return 0;
120 }
121 
122 static int lcd_release(struct inode *inode, struct file *file)
123 {
124  struct usb_lcd *dev;
125 
126  dev = file->private_data;
127  if (dev == NULL)
128  return -ENODEV;
129 
130  /* decrement the count on our device */
131  usb_autopm_put_interface(dev->interface);
132  kref_put(&dev->kref, lcd_delete);
133  return 0;
134 }
135 
136 static ssize_t lcd_read(struct file *file, char __user * buffer,
137  size_t count, loff_t *ppos)
138 {
139  struct usb_lcd *dev;
140  int retval = 0;
141  int bytes_read;
142 
143  dev = file->private_data;
144 
145  /* do a blocking bulk read to get data from the device */
146  retval = usb_bulk_msg(dev->udev,
147  usb_rcvbulkpipe(dev->udev,
148  dev->bulk_in_endpointAddr),
149  dev->bulk_in_buffer,
150  min(dev->bulk_in_size, count),
151  &bytes_read, 10000);
152 
153  /* if the read was successful, copy the data to userspace */
154  if (!retval) {
155  if (copy_to_user(buffer, dev->bulk_in_buffer, bytes_read))
156  retval = -EFAULT;
157  else
158  retval = bytes_read;
159  }
160 
161  return retval;
162 }
163 
164 static long lcd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
165 {
166  struct usb_lcd *dev;
167  u16 bcdDevice;
168  char buf[30];
169 
170  dev = file->private_data;
171  if (dev == NULL)
172  return -ENODEV;
173 
174  switch (cmd) {
176  mutex_lock(&lcd_mutex);
177  bcdDevice = le16_to_cpu((dev->udev)->descriptor.bcdDevice);
178  sprintf(buf, "%1d%1d.%1d%1d",
179  (bcdDevice & 0xF000)>>12,
180  (bcdDevice & 0xF00)>>8,
181  (bcdDevice & 0xF0)>>4,
182  (bcdDevice & 0xF));
183  mutex_unlock(&lcd_mutex);
184  if (copy_to_user((void __user *)arg, buf, strlen(buf)) != 0)
185  return -EFAULT;
186  break;
188  sprintf(buf, DRIVER_VERSION);
189  if (copy_to_user((void __user *)arg, buf, strlen(buf)) != 0)
190  return -EFAULT;
191  break;
192  default:
193  return -ENOTTY;
194  break;
195  }
196 
197  return 0;
198 }
199 
200 static void lcd_write_bulk_callback(struct urb *urb)
201 {
202  struct usb_lcd *dev;
203  int status = urb->status;
204 
205  dev = urb->context;
206 
207  /* sync/async unlink faults aren't errors */
208  if (status &&
209  !(status == -ENOENT ||
210  status == -ECONNRESET ||
211  status == -ESHUTDOWN)) {
212  dev_dbg(&dev->interface->dev,
213  "nonzero write bulk status received: %d\n", status);
214  }
215 
216  /* free up our allocated buffer */
217  usb_free_coherent(urb->dev, urb->transfer_buffer_length,
218  urb->transfer_buffer, urb->transfer_dma);
219  up(&dev->limit_sem);
220 }
221 
222 static ssize_t lcd_write(struct file *file, const char __user * user_buffer,
223  size_t count, loff_t *ppos)
224 {
225  struct usb_lcd *dev;
226  int retval = 0, r;
227  struct urb *urb = NULL;
228  char *buf = NULL;
229 
230  dev = file->private_data;
231 
232  /* verify that we actually have some data to write */
233  if (count == 0)
234  goto exit;
235 
236  r = down_interruptible(&dev->limit_sem);
237  if (r < 0)
238  return -EINTR;
239 
240  /* create a urb, and a buffer for it, and copy the data to the urb */
241  urb = usb_alloc_urb(0, GFP_KERNEL);
242  if (!urb) {
243  retval = -ENOMEM;
244  goto err_no_buf;
245  }
246 
247  buf = usb_alloc_coherent(dev->udev, count, GFP_KERNEL,
248  &urb->transfer_dma);
249  if (!buf) {
250  retval = -ENOMEM;
251  goto error;
252  }
253 
254  if (copy_from_user(buf, user_buffer, count)) {
255  retval = -EFAULT;
256  goto error;
257  }
258 
259  /* initialize the urb properly */
260  usb_fill_bulk_urb(urb, dev->udev,
261  usb_sndbulkpipe(dev->udev,
262  dev->bulk_out_endpointAddr),
263  buf, count, lcd_write_bulk_callback, dev);
264  urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
265 
266  usb_anchor_urb(urb, &dev->submitted);
267 
268  /* send the data out the bulk port */
269  retval = usb_submit_urb(urb, GFP_KERNEL);
270  if (retval) {
271  dev_err(&dev->udev->dev,
272  "%s - failed submitting write urb, error %d\n",
273  __func__, retval);
274  goto error_unanchor;
275  }
276 
277  /* release our reference to this urb,
278  the USB core will eventually free it entirely */
279  usb_free_urb(urb);
280 
281 exit:
282  return count;
283 error_unanchor:
284  usb_unanchor_urb(urb);
285 error:
286  usb_free_coherent(dev->udev, count, buf, urb->transfer_dma);
287  usb_free_urb(urb);
288 err_no_buf:
289  up(&dev->limit_sem);
290  return retval;
291 }
292 
293 static const struct file_operations lcd_fops = {
294  .owner = THIS_MODULE,
295  .read = lcd_read,
296  .write = lcd_write,
297  .open = lcd_open,
298  .unlocked_ioctl = lcd_ioctl,
299  .release = lcd_release,
300  .llseek = noop_llseek,
301 };
302 
303 /*
304  * usb class driver info in order to get a minor number from the usb core,
305  * and to have the device registered with the driver core
306  */
307 static struct usb_class_driver lcd_class = {
308  .name = "lcd%d",
309  .fops = &lcd_fops,
310  .minor_base = USBLCD_MINOR,
311 };
312 
313 static int lcd_probe(struct usb_interface *interface,
314  const struct usb_device_id *id)
315 {
316  struct usb_lcd *dev = NULL;
317  struct usb_host_interface *iface_desc;
319  size_t buffer_size;
320  int i;
321  int retval = -ENOMEM;
322 
323  /* allocate memory for our device state and initialize it */
324  dev = kzalloc(sizeof(*dev), GFP_KERNEL);
325  if (dev == NULL) {
326  dev_err(&interface->dev, "Out of memory\n");
327  goto error;
328  }
329  kref_init(&dev->kref);
330  sema_init(&dev->limit_sem, USB_LCD_CONCURRENT_WRITES);
331  init_usb_anchor(&dev->submitted);
332 
333  dev->udev = usb_get_dev(interface_to_usbdev(interface));
334  dev->interface = interface;
335 
336  if (le16_to_cpu(dev->udev->descriptor.idProduct) != 0x0001) {
337  dev_warn(&interface->dev, "USBLCD model not supported.\n");
338  retval = -ENODEV;
339  goto error;
340  }
341 
342  /* set up the endpoint information */
343  /* use only the first bulk-in and bulk-out endpoints */
344  iface_desc = interface->cur_altsetting;
345  for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
346  endpoint = &iface_desc->endpoint[i].desc;
347 
348  if (!dev->bulk_in_endpointAddr &&
349  usb_endpoint_is_bulk_in(endpoint)) {
350  /* we found a bulk in endpoint */
351  buffer_size = usb_endpoint_maxp(endpoint);
352  dev->bulk_in_size = buffer_size;
353  dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
354  dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
355  if (!dev->bulk_in_buffer) {
356  dev_err(&interface->dev,
357  "Could not allocate bulk_in_buffer\n");
358  goto error;
359  }
360  }
361 
362  if (!dev->bulk_out_endpointAddr &&
363  usb_endpoint_is_bulk_out(endpoint)) {
364  /* we found a bulk out endpoint */
365  dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;
366  }
367  }
368  if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) {
369  dev_err(&interface->dev,
370  "Could not find both bulk-in and bulk-out endpoints\n");
371  goto error;
372  }
373 
374  /* save our data pointer in this interface device */
375  usb_set_intfdata(interface, dev);
376 
377  /* we can register the device now, as it is ready */
378  retval = usb_register_dev(interface, &lcd_class);
379  if (retval) {
380  /* something prevented us from registering this driver */
381  dev_err(&interface->dev,
382  "Not able to get a minor for this device.\n");
383  usb_set_intfdata(interface, NULL);
384  goto error;
385  }
386 
387  i = le16_to_cpu(dev->udev->descriptor.bcdDevice);
388 
389  dev_info(&interface->dev, "USBLCD Version %1d%1d.%1d%1d found "
390  "at address %d\n", (i & 0xF000)>>12, (i & 0xF00)>>8,
391  (i & 0xF0)>>4, (i & 0xF), dev->udev->devnum);
392 
393  /* let the user know what node this device is now attached to */
394  dev_info(&interface->dev, "USB LCD device now attached to USBLCD-%d\n",
395  interface->minor);
396  return 0;
397 
398 error:
399  if (dev)
400  kref_put(&dev->kref, lcd_delete);
401  return retval;
402 }
403 
404 static void lcd_draw_down(struct usb_lcd *dev)
405 {
406  int time;
407 
408  time = usb_wait_anchor_empty_timeout(&dev->submitted, 1000);
409  if (!time)
411 }
412 
413 static int lcd_suspend(struct usb_interface *intf, pm_message_t message)
414 {
415  struct usb_lcd *dev = usb_get_intfdata(intf);
416 
417  if (!dev)
418  return 0;
419  lcd_draw_down(dev);
420  return 0;
421 }
422 
423 static int lcd_resume(struct usb_interface *intf)
424 {
425  return 0;
426 }
427 
428 static void lcd_disconnect(struct usb_interface *interface)
429 {
430  struct usb_lcd *dev;
431  int minor = interface->minor;
432 
433  mutex_lock(&open_disc_mutex);
434  dev = usb_get_intfdata(interface);
435  usb_set_intfdata(interface, NULL);
436  mutex_unlock(&open_disc_mutex);
437 
438  /* give back our minor */
439  usb_deregister_dev(interface, &lcd_class);
440 
441  /* decrement our usage count */
442  kref_put(&dev->kref, lcd_delete);
443 
444  dev_info(&interface->dev, "USB LCD #%d now disconnected\n", minor);
445 }
446 
447 static struct usb_driver lcd_driver = {
448  .name = "usblcd",
449  .probe = lcd_probe,
450  .disconnect = lcd_disconnect,
451  .suspend = lcd_suspend,
452  .resume = lcd_resume,
453  .id_table = id_table,
454  .supports_autosuspend = 1,
455 };
456 
457 module_usb_driver(lcd_driver);
458 
459 MODULE_AUTHOR("Georges Toth <[email protected]>");
461 MODULE_LICENSE("GPL");