aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/usb-skeleton.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/usb-skeleton.c')
-rw-r--r--drivers/usb/usb-skeleton.c252
1 files changed, 218 insertions, 34 deletions
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index 60ba631e99c2..b62f2bc064f6 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -18,7 +18,7 @@
18#include <linux/slab.h> 18#include <linux/slab.h>
19#include <linux/module.h> 19#include <linux/module.h>
20#include <linux/kref.h> 20#include <linux/kref.h>
21#include <asm/uaccess.h> 21#include <linux/uaccess.h>
22#include <linux/usb.h> 22#include <linux/usb.h>
23#include <linux/mutex.h> 23#include <linux/mutex.h>
24 24
@@ -28,7 +28,7 @@
28#define USB_SKEL_PRODUCT_ID 0xfff0 28#define USB_SKEL_PRODUCT_ID 0xfff0
29 29
30/* table of devices that work with this driver */ 30/* table of devices that work with this driver */
31static struct usb_device_id skel_table [] = { 31static struct usb_device_id skel_table[] = {
32 { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) }, 32 { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
33 { } /* Terminating entry */ 33 { } /* Terminating entry */
34}; 34};
@@ -52,15 +52,21 @@ struct usb_skel {
52 struct usb_interface *interface; /* the interface for this device */ 52 struct usb_interface *interface; /* the interface for this device */
53 struct semaphore limit_sem; /* limiting the number of writes in progress */ 53 struct semaphore limit_sem; /* limiting the number of writes in progress */
54 struct usb_anchor submitted; /* in case we need to retract our submissions */ 54 struct usb_anchor submitted; /* in case we need to retract our submissions */
55 struct urb *bulk_in_urb; /* the urb to read data with */
55 unsigned char *bulk_in_buffer; /* the buffer to receive data */ 56 unsigned char *bulk_in_buffer; /* the buffer to receive data */
56 size_t bulk_in_size; /* the size of the receive buffer */ 57 size_t bulk_in_size; /* the size of the receive buffer */
58 size_t bulk_in_filled; /* number of bytes in the buffer */
59 size_t bulk_in_copied; /* already copied to user space */
57 __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */ 60 __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */
58 __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */ 61 __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */
59 int errors; /* the last request tanked */ 62 int errors; /* the last request tanked */
60 int open_count; /* count the number of openers */ 63 int open_count; /* count the number of openers */
64 bool ongoing_read; /* a read is going on */
65 bool processed_urb; /* indicates we haven't processed the urb */
61 spinlock_t err_lock; /* lock for errors */ 66 spinlock_t err_lock; /* lock for errors */
62 struct kref kref; 67 struct kref kref;
63 struct mutex io_mutex; /* synchronize I/O with disconnect */ 68 struct mutex io_mutex; /* synchronize I/O with disconnect */
69 struct completion bulk_in_completion; /* to wait for an ongoing read */
64}; 70};
65#define to_skel_dev(d) container_of(d, struct usb_skel, kref) 71#define to_skel_dev(d) container_of(d, struct usb_skel, kref)
66 72
@@ -71,6 +77,7 @@ static void skel_delete(struct kref *kref)
71{ 77{
72 struct usb_skel *dev = to_skel_dev(kref); 78 struct usb_skel *dev = to_skel_dev(kref);
73 79
80 usb_free_urb(dev->bulk_in_urb);
74 usb_put_dev(dev->udev); 81 usb_put_dev(dev->udev);
75 kfree(dev->bulk_in_buffer); 82 kfree(dev->bulk_in_buffer);
76 kfree(dev); 83 kfree(dev);
@@ -87,7 +94,7 @@ static int skel_open(struct inode *inode, struct file *file)
87 94
88 interface = usb_find_interface(&skel_driver, subminor); 95 interface = usb_find_interface(&skel_driver, subminor);
89 if (!interface) { 96 if (!interface) {
90 err ("%s - error, can't find device for minor %d", 97 err("%s - error, can't find device for minor %d",
91 __func__, subminor); 98 __func__, subminor);
92 retval = -ENODEV; 99 retval = -ENODEV;
93 goto exit; 100 goto exit;
@@ -174,38 +181,190 @@ static int skel_flush(struct file *file, fl_owner_t id)
174 return res; 181 return res;
175} 182}
176 183
177static ssize_t skel_read(struct file *file, char *buffer, size_t count, loff_t *ppos) 184static void skel_read_bulk_callback(struct urb *urb)
178{ 185{
179 struct usb_skel *dev; 186 struct usb_skel *dev;
180 int retval; 187
181 int bytes_read; 188 dev = urb->context;
189
190 spin_lock(&dev->err_lock);
191 /* sync/async unlink faults aren't errors */
192 if (urb->status) {
193 if (!(urb->status == -ENOENT ||
194 urb->status == -ECONNRESET ||
195 urb->status == -ESHUTDOWN))
196 err("%s - nonzero write bulk status received: %d",
197 __func__, urb->status);
198
199 dev->errors = urb->status;
200 } else {
201 dev->bulk_in_filled = urb->actual_length;
202 }
203 dev->ongoing_read = 0;
204 spin_unlock(&dev->err_lock);
205
206 complete(&dev->bulk_in_completion);
207}
208
209static int skel_do_read_io(struct usb_skel *dev, size_t count)
210{
211 int rv;
212
213 /* prepare a read */
214 usb_fill_bulk_urb(dev->bulk_in_urb,
215 dev->udev,
216 usb_rcvbulkpipe(dev->udev,
217 dev->bulk_in_endpointAddr),
218 dev->bulk_in_buffer,
219 min(dev->bulk_in_size, count),
220 skel_read_bulk_callback,
221 dev);
222 /* tell everybody to leave the URB alone */
223 spin_lock_irq(&dev->err_lock);
224 dev->ongoing_read = 1;
225 spin_unlock_irq(&dev->err_lock);
226
227 /* do it */
228 rv = usb_submit_urb(dev->bulk_in_urb, GFP_KERNEL);
229 if (rv < 0) {
230 err("%s - failed submitting read urb, error %d",
231 __func__, rv);
232 dev->bulk_in_filled = 0;
233 rv = (rv == -ENOMEM) ? rv : -EIO;
234 spin_lock_irq(&dev->err_lock);
235 dev->ongoing_read = 0;
236 spin_unlock_irq(&dev->err_lock);
237 }
238
239 return rv;
240}
241
242static ssize_t skel_read(struct file *file, char *buffer, size_t count,
243 loff_t *ppos)
244{
245 struct usb_skel *dev;
246 int rv;
247 bool ongoing_io;
182 248
183 dev = (struct usb_skel *)file->private_data; 249 dev = (struct usb_skel *)file->private_data;
184 250
185 mutex_lock(&dev->io_mutex); 251 /* if we cannot read at all, return EOF */
252 if (!dev->bulk_in_urb || !count)
253 return 0;
254
255 /* no concurrent readers */
256 rv = mutex_lock_interruptible(&dev->io_mutex);
257 if (rv < 0)
258 return rv;
259
186 if (!dev->interface) { /* disconnect() was called */ 260 if (!dev->interface) { /* disconnect() was called */
187 retval = -ENODEV; 261 rv = -ENODEV;
188 goto exit; 262 goto exit;
189 } 263 }
190 264
191 /* do a blocking bulk read to get data from the device */ 265 /* if IO is under way, we must not touch things */
192 retval = usb_bulk_msg(dev->udev, 266retry:
193 usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr), 267 spin_lock_irq(&dev->err_lock);
194 dev->bulk_in_buffer, 268 ongoing_io = dev->ongoing_read;
195 min(dev->bulk_in_size, count), 269 spin_unlock_irq(&dev->err_lock);
196 &bytes_read, 10000); 270
197 271 if (ongoing_io) {
198 /* if the read was successful, copy the data to userspace */ 272 /* nonblocking IO shall not wait */
199 if (!retval) { 273 if (file->f_flags & O_NONBLOCK) {
200 if (copy_to_user(buffer, dev->bulk_in_buffer, bytes_read)) 274 rv = -EAGAIN;
201 retval = -EFAULT; 275 goto exit;
202 else 276 }
203 retval = bytes_read; 277 /*
278 * IO may take forever
279 * hence wait in an interruptible state
280 */
281 rv = wait_for_completion_interruptible(&dev->bulk_in_completion);
282 if (rv < 0)
283 goto exit;
284 /*
285 * by waiting we also semiprocessed the urb
286 * we must finish now
287 */
288 dev->bulk_in_copied = 0;
289 dev->processed_urb = 1;
290 }
291
292 if (!dev->processed_urb) {
293 /*
294 * the URB hasn't been processed
295 * do it now
296 */
297 wait_for_completion(&dev->bulk_in_completion);
298 dev->bulk_in_copied = 0;
299 dev->processed_urb = 1;
300 }
301
302 /* errors must be reported */
303 rv = dev->errors;
304 if (rv < 0) {
305 /* any error is reported once */
306 dev->errors = 0;
307 /* to preserve notifications about reset */
308 rv = (rv == -EPIPE) ? rv : -EIO;
309 /* no data to deliver */
310 dev->bulk_in_filled = 0;
311 /* report it */
312 goto exit;
204 } 313 }
205 314
315 /*
316 * if the buffer is filled we may satisfy the read
317 * else we need to start IO
318 */
319
320 if (dev->bulk_in_filled) {
321 /* we had read data */
322 size_t available = dev->bulk_in_filled - dev->bulk_in_copied;
323 size_t chunk = min(available, count);
324
325 if (!available) {
326 /*
327 * all data has been used
328 * actual IO needs to be done
329 */
330 rv = skel_do_read_io(dev, count);
331 if (rv < 0)
332 goto exit;
333 else
334 goto retry;
335 }
336 /*
337 * data is available
338 * chunk tells us how much shall be copied
339 */
340
341 if (copy_to_user(buffer,
342 dev->bulk_in_buffer + dev->bulk_in_copied,
343 chunk))
344 rv = -EFAULT;
345 else
346 rv = chunk;
347
348 dev->bulk_in_copied += chunk;
349
350 /*
351 * if we are asked for more than we have,
352 * we start IO but don't wait
353 */
354 if (available < count)
355 skel_do_read_io(dev, count - chunk);
356 } else {
357 /* no data in the buffer */
358 rv = skel_do_read_io(dev, count);
359 if (rv < 0)
360 goto exit;
361 else if (!file->f_flags & O_NONBLOCK)
362 goto retry;
363 rv = -EAGAIN;
364 }
206exit: 365exit:
207 mutex_unlock(&dev->io_mutex); 366 mutex_unlock(&dev->io_mutex);
208 return retval; 367 return rv;
209} 368}
210 369
211static void skel_write_bulk_callback(struct urb *urb) 370static void skel_write_bulk_callback(struct urb *urb)
@@ -216,7 +375,7 @@ static void skel_write_bulk_callback(struct urb *urb)
216 375
217 /* sync/async unlink faults aren't errors */ 376 /* sync/async unlink faults aren't errors */
218 if (urb->status) { 377 if (urb->status) {
219 if(!(urb->status == -ENOENT || 378 if (!(urb->status == -ENOENT ||
220 urb->status == -ECONNRESET || 379 urb->status == -ECONNRESET ||
221 urb->status == -ESHUTDOWN)) 380 urb->status == -ESHUTDOWN))
222 err("%s - nonzero write bulk status received: %d", 381 err("%s - nonzero write bulk status received: %d",
@@ -233,7 +392,8 @@ static void skel_write_bulk_callback(struct urb *urb)
233 up(&dev->limit_sem); 392 up(&dev->limit_sem);
234} 393}
235 394
236static ssize_t skel_write(struct file *file, const char *user_buffer, size_t count, loff_t *ppos) 395static ssize_t skel_write(struct file *file, const char *user_buffer,
396 size_t count, loff_t *ppos)
237{ 397{
238 struct usb_skel *dev; 398 struct usb_skel *dev;
239 int retval = 0; 399 int retval = 0;
@@ -247,14 +407,25 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
247 if (count == 0) 407 if (count == 0)
248 goto exit; 408 goto exit;
249 409
250 /* limit the number of URBs in flight to stop a user from using up all RAM */ 410 /*
251 if (down_interruptible(&dev->limit_sem)) { 411 * limit the number of URBs in flight to stop a user from using up all
252 retval = -ERESTARTSYS; 412 * RAM
253 goto exit; 413 */
414 if (!file->f_flags & O_NONBLOCK) {
415 if (down_interruptible(&dev->limit_sem)) {
416 retval = -ERESTARTSYS;
417 goto exit;
418 }
419 } else {
420 if (down_trylock(&dev->limit_sem)) {
421 retval = -EAGAIN;
422 goto exit;
423 }
254 } 424 }
255 425
256 spin_lock_irq(&dev->err_lock); 426 spin_lock_irq(&dev->err_lock);
257 if ((retval = dev->errors) < 0) { 427 retval = dev->errors;
428 if (retval < 0) {
258 /* any error is reported once */ 429 /* any error is reported once */
259 dev->errors = 0; 430 dev->errors = 0;
260 /* to preserve notifications about reset */ 431 /* to preserve notifications about reset */
@@ -271,7 +442,8 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
271 goto error; 442 goto error;
272 } 443 }
273 444
274 buf = usb_buffer_alloc(dev->udev, writesize, GFP_KERNEL, &urb->transfer_dma); 445 buf = usb_buffer_alloc(dev->udev, writesize, GFP_KERNEL,
446 &urb->transfer_dma);
275 if (!buf) { 447 if (!buf) {
276 retval = -ENOMEM; 448 retval = -ENOMEM;
277 goto error; 449 goto error;
@@ -301,11 +473,15 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
301 retval = usb_submit_urb(urb, GFP_KERNEL); 473 retval = usb_submit_urb(urb, GFP_KERNEL);
302 mutex_unlock(&dev->io_mutex); 474 mutex_unlock(&dev->io_mutex);
303 if (retval) { 475 if (retval) {
304 err("%s - failed submitting write urb, error %d", __func__, retval); 476 err("%s - failed submitting write urb, error %d", __func__,
477 retval);
305 goto error_unanchor; 478 goto error_unanchor;
306 } 479 }
307 480
308 /* release our reference to this urb, the USB core will eventually free it entirely */ 481 /*
482 * release our reference to this urb, the USB core will eventually free
483 * it entirely
484 */
309 usb_free_urb(urb); 485 usb_free_urb(urb);
310 486
311 487
@@ -343,7 +519,8 @@ static struct usb_class_driver skel_class = {
343 .minor_base = USB_SKEL_MINOR_BASE, 519 .minor_base = USB_SKEL_MINOR_BASE,
344}; 520};
345 521
346static int skel_probe(struct usb_interface *interface, const struct usb_device_id *id) 522static int skel_probe(struct usb_interface *interface,
523 const struct usb_device_id *id)
347{ 524{
348 struct usb_skel *dev; 525 struct usb_skel *dev;
349 struct usb_host_interface *iface_desc; 526 struct usb_host_interface *iface_desc;
@@ -363,6 +540,7 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
363 mutex_init(&dev->io_mutex); 540 mutex_init(&dev->io_mutex);
364 spin_lock_init(&dev->err_lock); 541 spin_lock_init(&dev->err_lock);
365 init_usb_anchor(&dev->submitted); 542 init_usb_anchor(&dev->submitted);
543 init_completion(&dev->bulk_in_completion);
366 544
367 dev->udev = usb_get_dev(interface_to_usbdev(interface)); 545 dev->udev = usb_get_dev(interface_to_usbdev(interface));
368 dev->interface = interface; 546 dev->interface = interface;
@@ -384,6 +562,11 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
384 err("Could not allocate bulk_in_buffer"); 562 err("Could not allocate bulk_in_buffer");
385 goto error; 563 goto error;
386 } 564 }
565 dev->bulk_in_urb = usb_alloc_urb(0, GFP_KERNEL);
566 if (!dev->bulk_in_urb) {
567 err("Could not allocate bulk_in_urb");
568 goto error;
569 }
387 } 570 }
388 571
389 if (!dev->bulk_out_endpointAddr && 572 if (!dev->bulk_out_endpointAddr &&
@@ -453,6 +636,7 @@ static void skel_draw_down(struct usb_skel *dev)
453 time = usb_wait_anchor_empty_timeout(&dev->submitted, 1000); 636 time = usb_wait_anchor_empty_timeout(&dev->submitted, 1000);
454 if (!time) 637 if (!time)
455 usb_kill_anchored_urbs(&dev->submitted); 638 usb_kill_anchored_urbs(&dev->submitted);
639 usb_kill_urb(dev->bulk_in_urb);
456} 640}
457 641
458static int skel_suspend(struct usb_interface *intf, pm_message_t message) 642static int skel_suspend(struct usb_interface *intf, pm_message_t message)
@@ -465,7 +649,7 @@ static int skel_suspend(struct usb_interface *intf, pm_message_t message)
465 return 0; 649 return 0;
466} 650}
467 651
468static int skel_resume (struct usb_interface *intf) 652static int skel_resume(struct usb_interface *intf)
469{ 653{
470 return 0; 654 return 0;
471} 655}