diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-25 06:23:15 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-25 06:23:15 -0400 |
| commit | 1be025d3cb40cd295123af2c394f7229ef9b30ca (patch) | |
| tree | 5dc14e1ea412cc7fdc3e563ad23187059fe8bfb5 /drivers/usb/misc/usblcd.c | |
| parent | 2d03423b2319cc854adeb28a03f65de5b5e0ab63 (diff) | |
| parent | a2c76b83fdd763c826f38a55127ccf25708099ce (diff) | |
Merge branch 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
* 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (260 commits)
usb: renesas_usbhs: fixup inconsistent return from usbhs_pkt_push()
usb/isp1760: Allow to optionally trigger low-level chip reset via GPIOLIB.
USB: gadget: midi: memory leak in f_midi_bind_config()
USB: gadget: midi: fix range check in f_midi_out_open()
QE/FHCI: fixed the CONTROL bug
usb: renesas_usbhs: tidyup for smatch warnings
USB: Fix USB Kconfig dependency problem on 85xx/QoirQ platforms
EHCI: workaround for MosChip controller bug
usb: gadget: file_storage: fix race on unloading
USB: ftdi_sio.c: Use ftdi async_icount structure for TIOCMIWAIT, as in other drivers
USB: ftdi_sio.c:Fill MSR fields of the ftdi async_icount structure
USB: ftdi_sio.c: Fill LSR fields of the ftdi async_icount structure
USB: ftdi_sio.c:Fill TX field of the ftdi async_icount structure
USB: ftdi_sio.c: Fill the RX field of the ftdi async_icount structure
USB: ftdi_sio.c: Basic icount infrastructure for ftdi_sio
usb/isp1760: Let OF bindings depend on general CONFIG_OF instead of PPC_OF .
USB: ftdi_sio: Support TI/Luminary Micro Stellaris BD-ICDI Board
USB: Fix runtime wakeup on OHCI
xHCI/USB: Make xHCI driver have a BOS descriptor.
usb: gadget: add new usb gadget for ACM and mass storage
...
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); |
