aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/misc/vstusb.c
diff options
context:
space:
mode:
authorStephen Ware <stephen.ware@eqware.net>2008-09-30 14:39:38 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2008-10-17 17:41:01 -0400
commitcbc30118d7a376dab4113f299c0c8f035737a5c3 (patch)
treec81723cea0775df91588079ae31bc2596cc35d89 /drivers/usb/misc/vstusb.c
parent29bac7b7661bbbdbbd32bc1e6cedca22f260da7f (diff)
usb: vstusb.c : new driver for spectrometers used by Vernier Software & Technology, Inc.
This patch adds the vstusb driver to the drivers/usb/misc directory. This driver provides support for Vernier Software & Technology spectrometers, all made by Ocean Optics. The driver provides both IOCTL and read()/write() methods for sending raw data to spectrometers across the bulk channel. Each method allows for a configured timeout. From: Stephen Ware <stephen.ware@eqware.net> Signed-off-by: Dennis O'Brien <dennis.obrien@eqware.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/misc/vstusb.c')
-rw-r--r--drivers/usb/misc/vstusb.c768
1 files changed, 768 insertions, 0 deletions
diff --git a/drivers/usb/misc/vstusb.c b/drivers/usb/misc/vstusb.c
new file mode 100644
index 000000000000..5ad75e4a0323
--- /dev/null
+++ b/drivers/usb/misc/vstusb.c
@@ -0,0 +1,768 @@
1/*****************************************************************************
2 * File: drivers/usb/misc/vstusb.c
3 *
4 * Purpose: Support for the bulk USB Vernier Spectrophotometers
5 *
6 * Author: Johnnie Peters
7 * Axian Consulting
8 * Beaverton, OR, USA 97005
9 *
10 * Modified by: EQware Engineering, Inc.
11 * Oregon City, OR, USA 97045
12 *
13 * Copyright: 2007, 2008
14 * Vernier Software & Technology
15 * Beaverton, OR, USA 97005
16 *
17 * Web: www.vernier.com
18 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License version 2 as
21 * published by the Free Software Foundation.
22 *
23 *****************************************************************************/
24#include <linux/kernel.h>
25#include <linux/errno.h>
26#include <linux/init.h>
27#include <linux/slab.h>
28#include <linux/module.h>
29#include <linux/mutex.h>
30#include <linux/uaccess.h>
31#include <linux/usb.h>
32
33#include <linux/usb/vstusb.h>
34
35#define DRIVER_VERSION "VST USB Driver Version 1.5"
36#define DRIVER_DESC "Vernier Software Technology Bulk USB Driver"
37
38#ifdef CONFIG_USB_DYNAMIC_MINORS
39 #define VSTUSB_MINOR_BASE 0
40#else
41 #define VSTUSB_MINOR_BASE 199
42#endif
43
44#define USB_VENDOR_OCEANOPTICS 0x2457
45#define USB_VENDOR_VERNIER 0x08F7 /* Vernier Software & Technology */
46
47#define USB_PRODUCT_USB2000 0x1002
48#define USB_PRODUCT_ADC1000_FW 0x1003 /* firmware download (renumerates) */
49#define USB_PRODUCT_ADC1000 0x1004
50#define USB_PRODUCT_HR2000_FW 0x1009 /* firmware download (renumerates) */
51#define USB_PRODUCT_HR2000 0x100A
52#define USB_PRODUCT_HR4000_FW 0x1011 /* firmware download (renumerates) */
53#define USB_PRODUCT_HR4000 0x1012
54#define USB_PRODUCT_USB650 0x1014 /* "Red Tide" */
55#define USB_PRODUCT_QE65000 0x1018
56#define USB_PRODUCT_USB4000 0x1022
57#define USB_PRODUCT_USB325 0x1024 /* "Vernier Spectrometer" */
58
59#define USB_PRODUCT_LABPRO 0x0001
60#define USB_PRODUCT_LABQUEST 0x0005
61
62static struct usb_device_id id_table[] = {
63 { USB_DEVICE(USB_VENDOR_OCEANOPTICS, USB_PRODUCT_USB2000)},
64 { USB_DEVICE(USB_VENDOR_OCEANOPTICS, USB_PRODUCT_HR4000)},
65 { USB_DEVICE(USB_VENDOR_OCEANOPTICS, USB_PRODUCT_USB650)},
66 { USB_DEVICE(USB_VENDOR_OCEANOPTICS, USB_PRODUCT_USB4000)},
67 { USB_DEVICE(USB_VENDOR_OCEANOPTICS, USB_PRODUCT_USB325)},
68 { USB_DEVICE(USB_VENDOR_VERNIER, USB_PRODUCT_LABQUEST)},
69 { USB_DEVICE(USB_VENDOR_VERNIER, USB_PRODUCT_LABPRO)},
70 {},
71};
72
73MODULE_DEVICE_TABLE(usb, id_table);
74
75struct vstusb_device {
76 struct mutex lock;
77 struct usb_device *usb_dev;
78 char present;
79 char isopen;
80 struct usb_anchor submitted;
81 int rd_pipe;
82 int rd_timeout_ms;
83 int wr_pipe;
84 int wr_timeout_ms;
85};
86
87static struct usb_driver vstusb_driver;
88
89static int vstusb_open(struct inode *inode, struct file *file)
90{
91 struct vstusb_device *vstdev;
92 struct usb_interface *interface;
93
94 interface = usb_find_interface(&vstusb_driver, iminor(inode));
95
96 if (!interface) {
97 printk(KERN_ERR KBUILD_MODNAME
98 ": %s - error, can't find device for minor %d\n",
99 __func__, iminor(inode));
100 return -ENODEV;
101 }
102
103 vstdev = usb_get_intfdata(interface);
104
105 if (!vstdev)
106 return -ENODEV;
107
108 /* lock this device */
109 mutex_lock(&vstdev->lock);
110
111 /* can only open one time */
112 if ((!vstdev->present) || (vstdev->isopen)) {
113 mutex_unlock(&vstdev->lock);
114 return -EBUSY;
115 }
116
117 vstdev->isopen = 1;
118
119 /* save device in the file's private structure */
120 file->private_data = vstdev;
121
122 dev_dbg(&vstdev->usb_dev->dev, "%s: opened\n", __func__);
123
124 mutex_unlock(&vstdev->lock);
125
126 return 0;
127}
128
129static int vstusb_close(struct inode *inode, struct file *file)
130{
131 struct vstusb_device *vstdev;
132
133 vstdev = file->private_data;
134
135 if (vstdev == NULL)
136 return -ENODEV;
137
138 mutex_lock(&vstdev->lock);
139
140 vstdev->isopen = 0;
141 file->private_data = NULL;
142
143 /* if device is no longer present */
144 if (!vstdev->present) {
145 mutex_unlock(&vstdev->lock);
146 kfree(vstdev);
147 } else
148 mutex_unlock(&vstdev->lock);
149
150 return 0;
151}
152
153static void usb_api_blocking_completion(struct urb *urb)
154{
155 struct completion *completeit = urb->context;
156
157 complete(completeit);
158}
159
160static int vstusb_fill_and_send_urb(struct urb *urb,
161 struct usb_device *usb_dev,
162 unsigned int pipe, void *data,
163 unsigned int len, struct completion *done)
164{
165 struct usb_host_endpoint *ep;
166 struct usb_host_endpoint **hostep;
167 unsigned int pipend;
168
169 int status;
170
171 hostep = usb_pipein(pipe) ? usb_dev->ep_in : usb_dev->ep_out;
172 pipend = usb_pipeendpoint(pipe);
173 ep = hostep[pipend];
174
175 if (!ep || (len == 0))
176 return -EINVAL;
177
178 if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
179 == USB_ENDPOINT_XFER_INT) {
180 pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30);
181 usb_fill_int_urb(urb, usb_dev, pipe, data, len,
182 (usb_complete_t)usb_api_blocking_completion,
183 NULL, ep->desc.bInterval);
184 } else
185 usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
186 (usb_complete_t)usb_api_blocking_completion,
187 NULL);
188
189 init_completion(done);
190 urb->context = done;
191 urb->actual_length = 0;
192 status = usb_submit_urb(urb, GFP_KERNEL);
193
194 return status;
195}
196
197static int vstusb_complete_urb(struct urb *urb, struct completion *done,
198 int timeout, int *actual_length)
199{
200 unsigned long expire;
201 int status;
202
203 expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT;
204 if (!wait_for_completion_interruptible_timeout(done, expire)) {
205 usb_kill_urb(urb);
206 status = urb->status == -ENOENT ? -ETIMEDOUT : urb->status;
207
208 dev_dbg(&urb->dev->dev,
209 "%s timed out on ep%d%s len=%d/%d, urb status = %d\n",
210 current->comm,
211 usb_pipeendpoint(urb->pipe),
212 usb_pipein(urb->pipe) ? "in" : "out",
213 urb->actual_length,
214 urb->transfer_buffer_length,
215 urb->status);
216
217 } else {
218 if (signal_pending(current)) {
219 /* if really an error */
220 if (urb->status && !((urb->status == -ENOENT) ||
221 (urb->status == -ECONNRESET) ||
222 (urb->status == -ESHUTDOWN))) {
223 status = -EINTR;
224 usb_kill_urb(urb);
225 } else {
226 status = 0;
227 }
228
229 dev_dbg(&urb->dev->dev,
230 "%s: signal pending on ep%d%s len=%d/%d,"
231 "urb status = %d\n",
232 current->comm,
233 usb_pipeendpoint(urb->pipe),
234 usb_pipein(urb->pipe) ? "in" : "out",
235 urb->actual_length,
236 urb->transfer_buffer_length,
237 urb->status);
238
239 } else {
240 status = urb->status;
241 }
242 }
243
244 if (actual_length)
245 *actual_length = urb->actual_length;
246
247 return status;
248}
249
250static ssize_t vstusb_read(struct file *file, char __user *buffer,
251 size_t count, loff_t *ppos)
252{
253 struct vstusb_device *vstdev;
254 int cnt = -1;
255 void *buf;
256 int retval = 0;
257
258 struct urb *urb;
259 struct usb_device *dev;
260 unsigned int pipe;
261 int timeout;
262
263 DECLARE_COMPLETION_ONSTACK(done);
264
265 vstdev = file->private_data;
266
267 if (vstdev == NULL)
268 return -ENODEV;
269
270 /* verify that we actually want to read some data */
271 if (count == 0)
272 return -EINVAL;
273
274 /* lock this object */
275 if (mutex_lock_interruptible(&vstdev->lock))
276 return -ERESTARTSYS;
277
278 /* anyone home */
279 if (!vstdev->present) {
280 mutex_unlock(&vstdev->lock);
281 printk(KERN_ERR KBUILD_MODNAME
282 ": %s: device not present\n", __func__);
283 return -ENODEV;
284 }
285
286 /* pull out the necessary data */
287 dev = vstdev->usb_dev;
288 pipe = usb_rcvbulkpipe(dev, vstdev->rd_pipe);
289 timeout = vstdev->rd_timeout_ms;
290
291 buf = kmalloc(count, GFP_KERNEL);
292 if (buf == NULL) {
293 mutex_unlock(&vstdev->lock);
294 return -ENOMEM;
295 }
296
297 urb = usb_alloc_urb(0, GFP_KERNEL);
298 if (!urb) {
299 kfree(buf);
300 mutex_unlock(&vstdev->lock);
301 return -ENOMEM;
302 }
303
304 usb_anchor_urb(urb, &vstdev->submitted);
305 retval = vstusb_fill_and_send_urb(urb, dev, pipe, buf, count, &done);
306 mutex_unlock(&vstdev->lock);
307 if (retval) {
308 usb_unanchor_urb(urb);
309 dev_err(&dev->dev, "%s: error %d filling and sending urb %d\n",
310 __func__, retval, pipe);
311 goto exit;
312 }
313
314 retval = vstusb_complete_urb(urb, &done, timeout, &cnt);
315 if (retval) {
316 dev_err(&dev->dev, "%s: error %d completing urb %d\n",
317 __func__, retval, pipe);
318 goto exit;
319 }
320
321 if (copy_to_user(buffer, buf, cnt)) {
322 dev_err(&dev->dev, "%s: can't copy_to_user\n", __func__);
323 retval = -EFAULT;
324 } else {
325 retval = cnt;
326 dev_dbg(&dev->dev, "%s: read %d bytes from pipe %d\n",
327 __func__, cnt, pipe);
328 }
329
330exit:
331 usb_free_urb(urb);
332 kfree(buf);
333 return retval;
334}
335
336static ssize_t vstusb_write(struct file *file, const char __user *buffer,
337 size_t count, loff_t *ppos)
338{
339 struct vstusb_device *vstdev;
340 int cnt = -1;
341 void *buf;
342 int retval = 0;
343
344 struct urb *urb;
345 struct usb_device *dev;
346 unsigned int pipe;
347 int timeout;
348
349 DECLARE_COMPLETION_ONSTACK(done);
350
351 vstdev = file->private_data;
352
353 if (vstdev == NULL)
354 return -ENODEV;
355
356 /* verify that we actually have some data to write */
357 if (count == 0)
358 return retval;
359
360 /* lock this object */
361 if (mutex_lock_interruptible(&vstdev->lock))
362 return -ERESTARTSYS;
363
364 /* anyone home */
365 if (!vstdev->present) {
366 mutex_unlock(&vstdev->lock);
367 printk(KERN_ERR KBUILD_MODNAME
368 ": %s: device not present\n", __func__);
369 return -ENODEV;
370 }
371
372 /* pull out the necessary data */
373 dev = vstdev->usb_dev;
374 pipe = usb_sndbulkpipe(dev, vstdev->wr_pipe);
375 timeout = vstdev->wr_timeout_ms;
376
377 buf = kmalloc(count, GFP_KERNEL);
378 if (buf == NULL) {
379 mutex_unlock(&vstdev->lock);
380 return -ENOMEM;
381 }
382
383 urb = usb_alloc_urb(0, GFP_KERNEL);
384 if (!urb) {
385 kfree(buf);
386 mutex_unlock(&vstdev->lock);
387 return -ENOMEM;
388 }
389
390 if (copy_from_user(buf, buffer, count)) {
391 dev_err(&dev->dev, "%s: can't copy_from_user\n", __func__);
392 retval = -EFAULT;
393 goto exit;
394 }
395
396 usb_anchor_urb(urb, &vstdev->submitted);
397 retval = vstusb_fill_and_send_urb(urb, dev, pipe, buf, count, &done);
398 mutex_unlock(&vstdev->lock);
399 if (retval) {
400 usb_unanchor_urb(urb);
401 dev_err(&dev->dev, "%s: error %d filling and sending urb %d\n",
402 __func__, retval, pipe);
403 goto exit;
404 }
405
406 retval = vstusb_complete_urb(urb, &done, timeout, &cnt);
407 if (retval) {
408 dev_err(&dev->dev, "%s: error %d completing urb %d\n",
409 __func__, retval, pipe);
410 goto exit;
411 } else {
412 retval = cnt;
413 dev_dbg(&dev->dev, "%s: sent %d bytes to pipe %d\n",
414 __func__, cnt, pipe);
415 }
416
417exit:
418 usb_free_urb(urb);
419 kfree(buf);
420 return retval;
421}
422
423static long vstusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
424{
425 int retval = 0;
426 int cnt = -1;
427 void __user *data = (void __user *)arg;
428 struct vstusb_args usb_data;
429
430 struct vstusb_device *vstdev;
431 void *buffer = NULL; /* must be initialized. buffer is
432 * referenced on exit but not all
433 * ioctls allocate it */
434
435 struct urb *urb = NULL; /* must be initialized. urb is
436 * referenced on exit but not all
437 * ioctls allocate it */
438 struct usb_device *dev;
439 unsigned int pipe;
440 int timeout;
441
442 DECLARE_COMPLETION_ONSTACK(done);
443
444 vstdev = file->private_data;
445
446 if (_IOC_TYPE(cmd) != VST_IOC_MAGIC) {
447 dev_warn(&vstdev->usb_dev->dev,
448 "%s: ioctl command %x, bad ioctl magic %x, "
449 "expected %x\n", __func__, cmd,
450 _IOC_TYPE(cmd), VST_IOC_MAGIC);
451 return -EINVAL;
452 }
453
454 if (vstdev == NULL)
455 return -ENODEV;
456
457 if (copy_from_user(&usb_data, data, sizeof(struct vstusb_args))) {
458 dev_err(&vstdev->usb_dev->dev, "%s: can't copy_from_user\n",
459 __func__);
460 return -EFAULT;
461 }
462
463 /* lock this object */
464 if (mutex_lock_interruptible(&vstdev->lock)) {
465 retval = -ERESTARTSYS;
466 goto exit;
467 }
468
469 /* anyone home */
470 if (!vstdev->present) {
471 mutex_unlock(&vstdev->lock);
472 dev_err(&vstdev->usb_dev->dev, "%s: device not present\n",
473 __func__);
474 retval = -ENODEV;
475 goto exit;
476 }
477
478 /* pull out the necessary data */
479 dev = vstdev->usb_dev;
480
481 switch (cmd) {
482
483 case IOCTL_VSTUSB_CONFIG_RW:
484
485 vstdev->rd_pipe = usb_data.rd_pipe;
486 vstdev->rd_timeout_ms = usb_data.rd_timeout_ms;
487 vstdev->wr_pipe = usb_data.wr_pipe;
488 vstdev->wr_timeout_ms = usb_data.wr_timeout_ms;
489
490 mutex_unlock(&vstdev->lock);
491
492 dev_dbg(&dev->dev, "%s: setting pipes/timeouts, "
493 "rdpipe = %d, rdtimeout = %d, "
494 "wrpipe = %d, wrtimeout = %d\n", __func__,
495 vstdev->rd_pipe, vstdev->rd_timeout_ms,
496 vstdev->wr_pipe, vstdev->wr_timeout_ms);
497 break;
498
499 case IOCTL_VSTUSB_SEND_PIPE:
500
501 if (usb_data.count == 0) {
502 mutex_unlock(&vstdev->lock);
503 retval = -EINVAL;
504 goto exit;
505 }
506
507 buffer = kmalloc(usb_data.count, GFP_KERNEL);
508 if (buffer == NULL) {
509 mutex_unlock(&vstdev->lock);
510 retval = -ENOMEM;
511 goto exit;
512 }
513
514 urb = usb_alloc_urb(0, GFP_KERNEL);
515 if (!urb) {
516 mutex_unlock(&vstdev->lock);
517 retval = -ENOMEM;
518 goto exit;
519 }
520
521 timeout = usb_data.timeout_ms;
522
523 pipe = usb_sndbulkpipe(dev, usb_data.pipe);
524
525 if (copy_from_user(buffer, usb_data.buffer, usb_data.count)) {
526 dev_err(&dev->dev, "%s: can't copy_from_user\n",
527 __func__);
528 mutex_unlock(&vstdev->lock);
529 retval = -EFAULT;
530 goto exit;
531 }
532
533 usb_anchor_urb(urb, &vstdev->submitted);
534 retval = vstusb_fill_and_send_urb(urb, dev, pipe, buffer,
535 usb_data.count, &done);
536 mutex_unlock(&vstdev->lock);
537 if (retval) {
538 usb_unanchor_urb(urb);
539 dev_err(&dev->dev,
540 "%s: error %d filling and sending urb %d\n",
541 __func__, retval, pipe);
542 goto exit;
543 }
544
545 retval = vstusb_complete_urb(urb, &done, timeout, &cnt);
546 if (retval) {
547 dev_err(&dev->dev, "%s: error %d completing urb %d\n",
548 __func__, retval, pipe);
549 }
550
551 break;
552 case IOCTL_VSTUSB_RECV_PIPE:
553
554 if (usb_data.count == 0) {
555 mutex_unlock(&vstdev->lock);
556 retval = -EINVAL;
557 goto exit;
558 }
559
560 buffer = kmalloc(usb_data.count, GFP_KERNEL);
561 if (buffer == NULL) {
562 mutex_unlock(&vstdev->lock);
563 retval = -ENOMEM;
564 goto exit;
565 }
566
567 urb = usb_alloc_urb(0, GFP_KERNEL);
568 if (!urb) {
569 mutex_unlock(&vstdev->lock);
570 retval = -ENOMEM;
571 goto exit;
572 }
573
574 timeout = usb_data.timeout_ms;
575
576 pipe = usb_rcvbulkpipe(dev, usb_data.pipe);
577
578 usb_anchor_urb(urb, &vstdev->submitted);
579 retval = vstusb_fill_and_send_urb(urb, dev, pipe, buffer,
580 usb_data.count, &done);
581 mutex_unlock(&vstdev->lock);
582 if (retval) {
583 usb_unanchor_urb(urb);
584 dev_err(&dev->dev,
585 "%s: error %d filling and sending urb %d\n",
586 __func__, retval, pipe);
587 goto exit;
588 }
589
590 retval = vstusb_complete_urb(urb, &done, timeout, &cnt);
591 if (retval) {
592 dev_err(&dev->dev, "%s: error %d completing urb %d\n",
593 __func__, retval, pipe);
594 goto exit;
595 }
596
597 if (copy_to_user(usb_data.buffer, buffer, cnt)) {
598 dev_err(&dev->dev, "%s: can't copy_to_user\n",
599 __func__);
600 retval = -EFAULT;
601 goto exit;
602 }
603
604 usb_data.count = cnt;
605 if (copy_to_user(data, &usb_data, sizeof(struct vstusb_args))) {
606 dev_err(&dev->dev, "%s: can't copy_to_user\n",
607 __func__);
608 retval = -EFAULT;
609 } else {
610 dev_dbg(&dev->dev, "%s: recv %d bytes from pipe %d\n",
611 __func__, usb_data.count, usb_data.pipe);
612 }
613
614 break;
615
616 default:
617 mutex_unlock(&vstdev->lock);
618 dev_warn(&dev->dev, "ioctl_vstusb: invalid ioctl cmd %x\n",
619 cmd);
620 return -EINVAL;
621 break;
622 }
623exit:
624 usb_free_urb(urb);
625 kfree(buffer);
626 return retval;
627}
628
629static const struct file_operations vstusb_fops = {
630 .owner = THIS_MODULE,
631 .read = vstusb_read,
632 .write = vstusb_write,
633 .unlocked_ioctl = vstusb_ioctl,
634 .compat_ioctl = vstusb_ioctl,
635 .open = vstusb_open,
636 .release = vstusb_close,
637};
638
639static struct usb_class_driver usb_vstusb_class = {
640 .name = "usb/vstusb%d",
641 .fops = &vstusb_fops,
642 .minor_base = VSTUSB_MINOR_BASE,
643};
644
645static int vstusb_probe(struct usb_interface *intf,
646 const struct usb_device_id *id)
647{
648 struct usb_device *dev = interface_to_usbdev(intf);
649 struct vstusb_device *vstdev;
650 int i;
651 int retval = 0;
652
653 /* allocate memory for our device state and intialize it */
654
655 vstdev = kzalloc(sizeof(*vstdev), GFP_KERNEL);
656 if (vstdev == NULL)
657 return -ENOMEM;
658
659 mutex_init(&vstdev->lock);
660
661 i = dev->descriptor.bcdDevice;
662
663 dev_dbg(&intf->dev, "Version %1d%1d.%1d%1d found at address %d\n",
664 (i & 0xF000) >> 12, (i & 0xF00) >> 8,
665 (i & 0xF0) >> 4, (i & 0xF), dev->devnum);
666
667 vstdev->present = 1;
668 vstdev->isopen = 0;
669 vstdev->usb_dev = dev;
670 init_usb_anchor(&vstdev->submitted);
671
672 usb_set_intfdata(intf, vstdev);
673 retval = usb_register_dev(intf, &usb_vstusb_class);
674 if (retval) {
675 dev_err(&intf->dev,
676 "%s: Not able to get a minor for this device.\n",
677 __func__);
678 usb_set_intfdata(intf, NULL);
679 kfree(vstdev);
680 return retval;
681 }
682
683 /* let the user know what node this device is now attached to */
684 dev_info(&intf->dev,
685 "VST USB Device #%d now attached to major %d minor %d\n",
686 (intf->minor - VSTUSB_MINOR_BASE), USB_MAJOR, intf->minor);
687
688 dev_info(&intf->dev, "%s, %s\n", DRIVER_DESC, DRIVER_VERSION);
689
690 return retval;
691}
692
693static void vstusb_disconnect(struct usb_interface *intf)
694{
695 struct vstusb_device *vstdev = usb_get_intfdata(intf);
696
697 usb_deregister_dev(intf, &usb_vstusb_class);
698 usb_set_intfdata(intf, NULL);
699
700 if (vstdev) {
701
702 mutex_lock(&vstdev->lock);
703 vstdev->present = 0;
704
705 usb_kill_anchored_urbs(&vstdev->submitted);
706
707 /* if the device is not opened, then we clean up right now */
708 if (!vstdev->isopen) {
709 mutex_unlock(&vstdev->lock);
710 kfree(vstdev);
711 } else
712 mutex_unlock(&vstdev->lock);
713
714 }
715}
716
717static int vstusb_suspend(struct usb_interface *intf, pm_message_t message)
718{
719 struct vstusb_device *vstdev = usb_get_intfdata(intf);
720 int time;
721 if (!vstdev)
722 return 0;
723
724 mutex_lock(&vstdev->lock);
725 time = usb_wait_anchor_empty_timeout(&vstdev->submitted, 1000);
726 if (!time)
727 usb_kill_anchored_urbs(&vstdev->submitted);
728 mutex_unlock(&vstdev->lock);
729
730 return 0;
731}
732
733static int vstusb_resume(struct usb_interface *intf)
734{
735 return 0;
736}
737
738static struct usb_driver vstusb_driver = {
739 .name = "vstusb",
740 .probe = vstusb_probe,
741 .disconnect = vstusb_disconnect,
742 .suspend = vstusb_suspend,
743 .resume = vstusb_resume,
744 .id_table = id_table,
745};
746
747static int __init vstusb_init(void)
748{
749 int rc;
750
751 rc = usb_register(&vstusb_driver);
752 if (rc)
753 printk(KERN_ERR "%s: failed to register (%d)", __func__, rc);
754
755 return rc;
756}
757
758static void __exit vstusb_exit(void)
759{
760 usb_deregister(&vstusb_driver);
761}
762
763module_init(vstusb_init);
764module_exit(vstusb_exit);
765
766MODULE_AUTHOR("Dennis O'Brien/Stephen Ware");
767MODULE_DESCRIPTION(DRIVER_VERSION);
768MODULE_LICENSE("GPL");