diff options
Diffstat (limited to 'drivers/usb/misc/usblcd.c')
-rw-r--r-- | drivers/usb/misc/usblcd.c | 129 |
1 files changed, 72 insertions, 57 deletions
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c index 51648154bb44..1871cdf10da3 100644 --- a/drivers/usb/misc/usblcd.c +++ b/drivers/usb/misc/usblcd.c | |||
@@ -18,7 +18,7 @@ | |||
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/errno.h> | 19 | #include <linux/errno.h> |
20 | #include <linux/mutex.h> | 20 | #include <linux/mutex.h> |
21 | #include <asm/uaccess.h> | 21 | #include <linux/uaccess.h> |
22 | #include <linux/usb.h> | 22 | #include <linux/usb.h> |
23 | 23 | ||
24 | #define DRIVER_VERSION "USBLCD Driver Version 1.05" | 24 | #define DRIVER_VERSION "USBLCD Driver Version 1.05" |
@@ -34,22 +34,29 @@ static const struct usb_device_id id_table[] = { | |||
34 | { .idVendor = 0x10D2, .match_flags = USB_DEVICE_ID_MATCH_VENDOR, }, | 34 | { .idVendor = 0x10D2, .match_flags = USB_DEVICE_ID_MATCH_VENDOR, }, |
35 | { }, | 35 | { }, |
36 | }; | 36 | }; |
37 | MODULE_DEVICE_TABLE (usb, id_table); | 37 | MODULE_DEVICE_TABLE(usb, id_table); |
38 | 38 | ||
39 | static DEFINE_MUTEX(open_disc_mutex); | 39 | static DEFINE_MUTEX(open_disc_mutex); |
40 | 40 | ||
41 | 41 | ||
42 | struct usb_lcd { | 42 | struct usb_lcd { |
43 | struct usb_device * udev; /* init: probe_lcd */ | 43 | struct usb_device *udev; /* init: probe_lcd */ |
44 | struct usb_interface * interface; /* the interface for this device */ | 44 | struct usb_interface *interface; /* the interface for |
45 | unsigned char * bulk_in_buffer; /* the buffer to receive data */ | 45 | this device */ |
46 | size_t bulk_in_size; /* the size of the receive buffer */ | 46 | unsigned char *bulk_in_buffer; /* the buffer to receive |
47 | __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */ | 47 | data */ |
48 | __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */ | 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 */ | ||
49 | struct kref kref; | 54 | struct kref kref; |
50 | struct semaphore limit_sem; /* to stop writes at full throttle from | 55 | struct semaphore limit_sem; /* to stop writes at |
51 | * using up all RAM */ | 56 | full throttle from |
52 | struct usb_anchor submitted; /* URBs to wait for before suspend */ | 57 | using up all RAM */ |
58 | struct usb_anchor submitted; /* URBs to wait for | ||
59 | before suspend */ | ||
53 | }; | 60 | }; |
54 | #define to_lcd_dev(d) container_of(d, struct usb_lcd, kref) | 61 | #define to_lcd_dev(d) container_of(d, struct usb_lcd, kref) |
55 | 62 | ||
@@ -63,8 +70,8 @@ static void lcd_delete(struct kref *kref) | |||
63 | struct usb_lcd *dev = to_lcd_dev(kref); | 70 | struct usb_lcd *dev = to_lcd_dev(kref); |
64 | 71 | ||
65 | usb_put_dev(dev->udev); | 72 | usb_put_dev(dev->udev); |
66 | kfree (dev->bulk_in_buffer); | 73 | kfree(dev->bulk_in_buffer); |
67 | kfree (dev); | 74 | kfree(dev); |
68 | } | 75 | } |
69 | 76 | ||
70 | 77 | ||
@@ -80,7 +87,7 @@ static int lcd_open(struct inode *inode, struct file *file) | |||
80 | interface = usb_find_interface(&lcd_driver, subminor); | 87 | interface = usb_find_interface(&lcd_driver, subminor); |
81 | if (!interface) { | 88 | if (!interface) { |
82 | mutex_unlock(&lcd_mutex); | 89 | mutex_unlock(&lcd_mutex); |
83 | err ("USBLCD: %s - error, can't find device for minor %d", | 90 | err("USBLCD: %s - error, can't find device for minor %d", |
84 | __func__, subminor); | 91 | __func__, subminor); |
85 | return -ENODEV; | 92 | return -ENODEV; |
86 | } | 93 | } |
@@ -126,7 +133,8 @@ static int lcd_release(struct inode *inode, struct file *file) | |||
126 | return 0; | 133 | return 0; |
127 | } | 134 | } |
128 | 135 | ||
129 | static ssize_t lcd_read(struct file *file, char __user * buffer, size_t count, loff_t *ppos) | 136 | static ssize_t lcd_read(struct file *file, char __user * buffer, |
137 | size_t count, loff_t *ppos) | ||
130 | { | 138 | { |
131 | struct usb_lcd *dev; | 139 | struct usb_lcd *dev; |
132 | int retval = 0; | 140 | int retval = 0; |
@@ -135,8 +143,9 @@ static ssize_t lcd_read(struct file *file, char __user * buffer, size_t count, l | |||
135 | dev = file->private_data; | 143 | dev = file->private_data; |
136 | 144 | ||
137 | /* do a blocking bulk read to get data from the device */ | 145 | /* do a blocking bulk read to get data from the device */ |
138 | retval = usb_bulk_msg(dev->udev, | 146 | retval = usb_bulk_msg(dev->udev, |
139 | usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr), | 147 | usb_rcvbulkpipe(dev->udev, |
148 | dev->bulk_in_endpointAddr), | ||
140 | dev->bulk_in_buffer, | 149 | dev->bulk_in_buffer, |
141 | min(dev->bulk_in_size, count), | 150 | min(dev->bulk_in_size, count), |
142 | &bytes_read, 10000); | 151 | &bytes_read, 10000); |
@@ -161,23 +170,23 @@ static long lcd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
161 | dev = file->private_data; | 170 | dev = file->private_data; |
162 | if (dev == NULL) | 171 | if (dev == NULL) |
163 | return -ENODEV; | 172 | return -ENODEV; |
164 | 173 | ||
165 | switch (cmd) { | 174 | switch (cmd) { |
166 | case IOCTL_GET_HARD_VERSION: | 175 | case IOCTL_GET_HARD_VERSION: |
167 | mutex_lock(&lcd_mutex); | 176 | mutex_lock(&lcd_mutex); |
168 | bcdDevice = le16_to_cpu((dev->udev)->descriptor.bcdDevice); | 177 | bcdDevice = le16_to_cpu((dev->udev)->descriptor.bcdDevice); |
169 | sprintf(buf,"%1d%1d.%1d%1d", | 178 | sprintf(buf, "%1d%1d.%1d%1d", |
170 | (bcdDevice & 0xF000)>>12, | 179 | (bcdDevice & 0xF000)>>12, |
171 | (bcdDevice & 0xF00)>>8, | 180 | (bcdDevice & 0xF00)>>8, |
172 | (bcdDevice & 0xF0)>>4, | 181 | (bcdDevice & 0xF0)>>4, |
173 | (bcdDevice & 0xF)); | 182 | (bcdDevice & 0xF)); |
174 | mutex_unlock(&lcd_mutex); | 183 | mutex_unlock(&lcd_mutex); |
175 | if (copy_to_user((void __user *)arg,buf,strlen(buf))!=0) | 184 | if (copy_to_user((void __user *)arg, buf, strlen(buf)) != 0) |
176 | return -EFAULT; | 185 | return -EFAULT; |
177 | break; | 186 | break; |
178 | case IOCTL_GET_DRV_VERSION: | 187 | case IOCTL_GET_DRV_VERSION: |
179 | sprintf(buf,DRIVER_VERSION); | 188 | sprintf(buf, DRIVER_VERSION); |
180 | if (copy_to_user((void __user *)arg,buf,strlen(buf))!=0) | 189 | if (copy_to_user((void __user *)arg, buf, strlen(buf)) != 0) |
181 | return -EFAULT; | 190 | return -EFAULT; |
182 | break; | 191 | break; |
183 | default: | 192 | default: |
@@ -199,7 +208,7 @@ static void lcd_write_bulk_callback(struct urb *urb) | |||
199 | if (status && | 208 | if (status && |
200 | !(status == -ENOENT || | 209 | !(status == -ENOENT || |
201 | status == -ECONNRESET || | 210 | status == -ECONNRESET || |
202 | status == -ESHUTDOWN)) { | 211 | status == -ESHUTDOWN)) { |
203 | dbg("USBLCD: %s - nonzero write bulk status received: %d", | 212 | dbg("USBLCD: %s - nonzero write bulk status received: %d", |
204 | __func__, status); | 213 | __func__, status); |
205 | } | 214 | } |
@@ -210,15 +219,16 @@ static void lcd_write_bulk_callback(struct urb *urb) | |||
210 | up(&dev->limit_sem); | 219 | up(&dev->limit_sem); |
211 | } | 220 | } |
212 | 221 | ||
213 | static ssize_t lcd_write(struct file *file, const char __user * user_buffer, size_t count, loff_t *ppos) | 222 | static ssize_t lcd_write(struct file *file, const char __user * user_buffer, |
223 | size_t count, loff_t *ppos) | ||
214 | { | 224 | { |
215 | struct usb_lcd *dev; | 225 | struct usb_lcd *dev; |
216 | int retval = 0, r; | 226 | int retval = 0, r; |
217 | struct urb *urb = NULL; | 227 | struct urb *urb = NULL; |
218 | char *buf = NULL; | 228 | char *buf = NULL; |
219 | 229 | ||
220 | dev = file->private_data; | 230 | dev = file->private_data; |
221 | 231 | ||
222 | /* verify that we actually have some data to write */ | 232 | /* verify that we actually have some data to write */ |
223 | if (count == 0) | 233 | if (count == 0) |
224 | goto exit; | 234 | goto exit; |
@@ -233,34 +243,38 @@ static ssize_t lcd_write(struct file *file, const char __user * user_buffer, siz | |||
233 | retval = -ENOMEM; | 243 | retval = -ENOMEM; |
234 | goto err_no_buf; | 244 | goto err_no_buf; |
235 | } | 245 | } |
236 | 246 | ||
237 | buf = usb_alloc_coherent(dev->udev, count, GFP_KERNEL, &urb->transfer_dma); | 247 | buf = usb_alloc_coherent(dev->udev, count, GFP_KERNEL, |
248 | &urb->transfer_dma); | ||
238 | if (!buf) { | 249 | if (!buf) { |
239 | retval = -ENOMEM; | 250 | retval = -ENOMEM; |
240 | goto error; | 251 | goto error; |
241 | } | 252 | } |
242 | 253 | ||
243 | if (copy_from_user(buf, user_buffer, count)) { | 254 | if (copy_from_user(buf, user_buffer, count)) { |
244 | retval = -EFAULT; | 255 | retval = -EFAULT; |
245 | goto error; | 256 | goto error; |
246 | } | 257 | } |
247 | 258 | ||
248 | /* initialize the urb properly */ | 259 | /* initialize the urb properly */ |
249 | usb_fill_bulk_urb(urb, dev->udev, | 260 | usb_fill_bulk_urb(urb, dev->udev, |
250 | usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr), | 261 | usb_sndbulkpipe(dev->udev, |
262 | dev->bulk_out_endpointAddr), | ||
251 | buf, count, lcd_write_bulk_callback, dev); | 263 | buf, count, lcd_write_bulk_callback, dev); |
252 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 264 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
253 | 265 | ||
254 | usb_anchor_urb(urb, &dev->submitted); | 266 | usb_anchor_urb(urb, &dev->submitted); |
255 | 267 | ||
256 | /* send the data out the bulk port */ | 268 | /* send the data out the bulk port */ |
257 | retval = usb_submit_urb(urb, GFP_KERNEL); | 269 | retval = usb_submit_urb(urb, GFP_KERNEL); |
258 | if (retval) { | 270 | if (retval) { |
259 | err("USBLCD: %s - failed submitting write urb, error %d", __func__, retval); | 271 | err("USBLCD: %s - failed submitting write urb, error %d", |
272 | __func__, retval); | ||
260 | goto error_unanchor; | 273 | goto error_unanchor; |
261 | } | 274 | } |
262 | 275 | ||
263 | /* release our reference to this urb, the USB core will eventually free it entirely */ | 276 | /* release our reference to this urb, |
277 | the USB core will eventually free it entirely */ | ||
264 | usb_free_urb(urb); | 278 | usb_free_urb(urb); |
265 | 279 | ||
266 | exit: | 280 | exit: |
@@ -276,13 +290,13 @@ err_no_buf: | |||
276 | } | 290 | } |
277 | 291 | ||
278 | static const struct file_operations lcd_fops = { | 292 | static const struct file_operations lcd_fops = { |
279 | .owner = THIS_MODULE, | 293 | .owner = THIS_MODULE, |
280 | .read = lcd_read, | 294 | .read = lcd_read, |
281 | .write = lcd_write, | 295 | .write = lcd_write, |
282 | .open = lcd_open, | 296 | .open = lcd_open, |
283 | .unlocked_ioctl = lcd_ioctl, | 297 | .unlocked_ioctl = lcd_ioctl, |
284 | .release = lcd_release, | 298 | .release = lcd_release, |
285 | .llseek = noop_llseek, | 299 | .llseek = noop_llseek, |
286 | }; | 300 | }; |
287 | 301 | ||
288 | /* | 302 | /* |
@@ -290,12 +304,13 @@ static const struct file_operations lcd_fops = { | |||
290 | * and to have the device registered with the driver core | 304 | * and to have the device registered with the driver core |
291 | */ | 305 | */ |
292 | static struct usb_class_driver lcd_class = { | 306 | static struct usb_class_driver lcd_class = { |
293 | .name = "lcd%d", | 307 | .name = "lcd%d", |
294 | .fops = &lcd_fops, | 308 | .fops = &lcd_fops, |
295 | .minor_base = USBLCD_MINOR, | 309 | .minor_base = USBLCD_MINOR, |
296 | }; | 310 | }; |
297 | 311 | ||
298 | static int lcd_probe(struct usb_interface *interface, const struct usb_device_id *id) | 312 | static int lcd_probe(struct usb_interface *interface, |
313 | const struct usb_device_id *id) | ||
299 | { | 314 | { |
300 | struct usb_lcd *dev = NULL; | 315 | struct usb_lcd *dev = NULL; |
301 | struct usb_host_interface *iface_desc; | 316 | struct usb_host_interface *iface_desc; |
@@ -322,7 +337,7 @@ static int lcd_probe(struct usb_interface *interface, const struct usb_device_id | |||
322 | retval = -ENODEV; | 337 | retval = -ENODEV; |
323 | goto error; | 338 | goto error; |
324 | } | 339 | } |
325 | 340 | ||
326 | /* set up the endpoint information */ | 341 | /* set up the endpoint information */ |
327 | /* use only the first bulk-in and bulk-out endpoints */ | 342 | /* use only the first bulk-in and bulk-out endpoints */ |
328 | iface_desc = interface->cur_altsetting; | 343 | iface_desc = interface->cur_altsetting; |
@@ -332,7 +347,7 @@ static int lcd_probe(struct usb_interface *interface, const struct usb_device_id | |||
332 | if (!dev->bulk_in_endpointAddr && | 347 | if (!dev->bulk_in_endpointAddr && |
333 | usb_endpoint_is_bulk_in(endpoint)) { | 348 | usb_endpoint_is_bulk_in(endpoint)) { |
334 | /* we found a bulk in endpoint */ | 349 | /* we found a bulk in endpoint */ |
335 | buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); | 350 | buffer_size = usb_endpoint_maxp(endpoint); |
336 | dev->bulk_in_size = buffer_size; | 351 | dev->bulk_in_size = buffer_size; |
337 | dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; | 352 | dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; |
338 | dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); | 353 | dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); |
@@ -369,7 +384,7 @@ static int lcd_probe(struct usb_interface *interface, const struct usb_device_id | |||
369 | 384 | ||
370 | dev_info(&interface->dev, "USBLCD Version %1d%1d.%1d%1d found " | 385 | dev_info(&interface->dev, "USBLCD Version %1d%1d.%1d%1d found " |
371 | "at address %d\n", (i & 0xF000)>>12, (i & 0xF00)>>8, | 386 | "at address %d\n", (i & 0xF000)>>12, (i & 0xF00)>>8, |
372 | (i & 0xF0)>>4,(i & 0xF), dev->udev->devnum); | 387 | (i & 0xF0)>>4, (i & 0xF), dev->udev->devnum); |
373 | 388 | ||
374 | /* let the user know what node this device is now attached to */ | 389 | /* let the user know what node this device is now attached to */ |
375 | dev_info(&interface->dev, "USB LCD device now attached to USBLCD-%d\n", | 390 | dev_info(&interface->dev, "USB LCD device now attached to USBLCD-%d\n", |
@@ -401,7 +416,7 @@ static int lcd_suspend(struct usb_interface *intf, pm_message_t message) | |||
401 | return 0; | 416 | return 0; |
402 | } | 417 | } |
403 | 418 | ||
404 | static int lcd_resume (struct usb_interface *intf) | 419 | static int lcd_resume(struct usb_interface *intf) |
405 | { | 420 | { |
406 | return 0; | 421 | return 0; |
407 | } | 422 | } |
@@ -409,16 +424,16 @@ static int lcd_resume (struct usb_interface *intf) | |||
409 | static void lcd_disconnect(struct usb_interface *interface) | 424 | static void lcd_disconnect(struct usb_interface *interface) |
410 | { | 425 | { |
411 | struct usb_lcd *dev; | 426 | struct usb_lcd *dev; |
412 | int minor = interface->minor; | 427 | int minor = interface->minor; |
413 | 428 | ||
414 | mutex_lock(&open_disc_mutex); | 429 | mutex_lock(&open_disc_mutex); |
415 | dev = usb_get_intfdata(interface); | 430 | dev = usb_get_intfdata(interface); |
416 | usb_set_intfdata(interface, NULL); | 431 | usb_set_intfdata(interface, NULL); |
417 | mutex_unlock(&open_disc_mutex); | 432 | mutex_unlock(&open_disc_mutex); |
418 | 433 | ||
419 | /* give back our minor */ | 434 | /* give back our minor */ |
420 | usb_deregister_dev(interface, &lcd_class); | 435 | usb_deregister_dev(interface, &lcd_class); |
421 | 436 | ||
422 | /* decrement our usage count */ | 437 | /* decrement our usage count */ |
423 | kref_put(&dev->kref, lcd_delete); | 438 | kref_put(&dev->kref, lcd_delete); |
424 | 439 | ||
@@ -438,7 +453,7 @@ static struct usb_driver lcd_driver = { | |||
438 | static int __init usb_lcd_init(void) | 453 | static int __init usb_lcd_init(void) |
439 | { | 454 | { |
440 | int result; | 455 | int result; |
441 | 456 | ||
442 | result = usb_register(&lcd_driver); | 457 | result = usb_register(&lcd_driver); |
443 | if (result) | 458 | if (result) |
444 | err("usb_register failed. Error number %d", result); | 459 | err("usb_register failed. Error number %d", result); |