14 #include <linux/kernel.h>
15 #include <linux/errno.h>
16 #include <linux/slab.h>
17 #include <linux/module.h>
20 #include <linux/bitops.h>
21 #include <linux/poll.h>
24 #include <asm/byteorder.h>
25 #include <asm/unaligned.h>
31 #define DRIVER_VERSION "v0.03"
32 #define DRIVER_AUTHOR "Oliver Neukum"
33 #define DRIVER_DESC "USB Abstract Control Model driver for USB WCM Device Management"
47 #define WDM_MINOR_BASE 176
51 #define WDM_DISCONNECTING 2
54 #define WDM_INT_STALL 5
55 #define WDM_POLL_RUNNING 6
56 #define WDM_RESPONDING 7
57 #define WDM_SUSPENDING 8
58 #define WDM_RESETTING 9
63 #define WDM_DEFAULT_BUFSIZE 256
107 static struct usb_driver wdm_driver;
114 spin_lock(&wdm_device_list_lock);
116 if (desc->intf == intf)
120 spin_unlock(&wdm_device_list_lock);
129 spin_lock(&wdm_device_list_lock);
131 if (desc->intf->minor == minor)
135 spin_unlock(&wdm_device_list_lock);
146 desc->
werr = urb->status;
147 spin_unlock(&desc->
iuspin);
154 static void wdm_in_callback(
struct urb *
urb)
166 "nonzero urb status received: -ENOENT");
170 "nonzero urb status received: -ECONNRESET");
174 "nonzero urb status received: -ESHUTDOWN");
178 "nonzero urb status received: -EPIPE\n");
182 "Unexpected error %d\n", status);
195 spin_unlock(&desc->
iuspin);
198 static void wdm_int_callback(
struct urb *urb)
201 int status = urb->status;
216 dev_err(&desc->
intf->dev,
"Stall on int endpoint\n");
220 "nonzero urb status received: %d\n", status);
226 dev_err(&desc->
intf->dev,
"wdm_int_callback - %d bytes\n",
234 "NOTIFY_RESPONSE_AVAILABLE received: index %d len %d",
241 "NOTIFY_NETWORK_CONNECTION %s network",
242 dr->
wValue ?
"connected to" :
"disconnected from");
247 "unknown notification %d received: index %d len %d\n",
261 spin_unlock(&desc->
iuspin);
271 "Cannot schedule work\n");
278 "%s - usb_submit_urb failed with result %d\n",
283 static void kill_urbs(
struct wdm_device *desc)
291 static void free_urbs(
struct wdm_device *desc)
320 spin_lock_irq(&desc->
iuspin);
323 spin_unlock_irq(&desc->
iuspin);
354 r = usb_autopm_get_interface(desc->
intf);
357 rv = usb_translate_errors(r);
378 usb_fill_control_urb(
380 interface_to_usbdev(desc->
intf),
382 usb_sndctrlpipe(interface_to_usbdev(desc->
intf), 0),
383 (
unsigned char *)req,
404 dev_err(&desc->
intf->dev,
"Tx URB error: %d\n", rv);
405 rv = usb_translate_errors(rv);
407 dev_dbg(&desc->
intf->dev,
"Tx URB has been submitted index=%d",
411 usb_autopm_put_interface(desc->
intf);
415 return rv < 0 ? rv :
count;
419 (
struct file *file,
char __user *buffer,
size_t count, loff_t *ppos)
441 rv = cntr ? cntr : -
EAGAIN;
459 usb_mark_last_busy(interface_to_usbdev(desc->
intf));
465 spin_lock_irq(&desc->
iuspin);
469 spin_unlock_irq(&desc->
iuspin);
478 spin_unlock_irq(&desc->
iuspin);
482 dev_dbg(&desc->
intf->dev,
"%s: zero length - clearing WDM_READ\n", __func__);
484 spin_unlock_irq(&desc->
iuspin);
488 spin_unlock_irq(&desc->
iuspin);
499 spin_lock_irq(&desc->
iuspin);
501 for (i = 0; i < desc->
length - cntr; i++)
502 desc->
ubuf[i] = desc->
ubuf[i + cntr];
509 spin_unlock_irq(&desc->
iuspin);
518 static int wdm_flush(
struct file *file,
fl_owner_t id)
526 dev_err(&desc->
intf->dev,
"Error in flush path: %d\n",
529 return usb_translate_errors(desc->
werr);
536 unsigned int mask = 0;
541 spin_unlock_irqrestore(&desc->
iuspin, flags);
550 spin_unlock_irqrestore(&desc->
iuspin, flags);
552 poll_wait(file, &desc->
wait, wait);
558 static int wdm_open(
struct inode *
inode,
struct file *file)
560 int minor = iminor(inode);
566 desc = wdm_find_device_by_minor(minor);
575 rv = usb_autopm_get_interface(desc->
intf);
577 dev_err(&desc->
intf->dev,
"Error autopm - %d\n", rv);
583 if (!desc->
count++) {
590 "Error submitting int urb - %d\n", rv);
591 rv = usb_translate_errors(rv);
597 if (desc->
count == 1)
599 usb_autopm_put_interface(desc->
intf);
605 static int wdm_release(
struct inode *inode,
struct file *file)
623 pr_debug(KBUILD_MODNAME
" %s: device gone - cleaning up\n", __func__);
637 .release = wdm_release,
642 static struct usb_class_driver wdm_class = {
657 spin_unlock_irqrestore(&desc->
iuspin, flags);
659 spin_unlock_irqrestore(&desc->
iuspin, flags);
661 if (rv < 0 && rv != -
EPERM) {
665 spin_unlock_irqrestore(&desc->
iuspin, flags);
693 if (!usb_endpoint_is_int_in(ep))
731 interface_to_usbdev(intf),
742 desc->
irq->wValue = 0;
743 desc->
irq->wIndex = desc->
inum;
746 usb_fill_control_urb(
748 interface_to_usbdev(intf),
750 usb_rcvctrlpipe(interface_to_usbdev(desc->
intf), 0),
751 (
unsigned char *)desc->
irq,
760 spin_lock(&wdm_device_list_lock);
762 spin_unlock(&wdm_device_list_lock);
768 dev_info(&intf->dev,
"%s: USB WDM device\n", dev_name(intf->usb_dev));
772 spin_lock(&wdm_device_list_lock);
774 spin_unlock(&wdm_device_list_lock);
779 static int wdm_manage_power(
struct usb_interface *intf,
int on)
782 int rv = usb_autopm_get_interface(intf);
786 intf->needs_remote_wakeup = on;
787 usb_autopm_put_interface(intf);
795 struct usb_host_interface *iface;
798 u8 *buffer = intf->altsetting->extra;
799 int buflen = intf->altsetting->extralen;
806 dev_err(&intf->dev,
"skipping garbage\n");
817 "Finding maximum buffer length: %d", maxcom);
821 "Ignoring extra header, type %d, length %d\n",
822 buffer[2], buffer[0]);
830 iface = intf->cur_altsetting;
831 if (iface->desc.bNumEndpoints != 1)
833 ep = &iface->endpoint[0].desc;
835 rv = wdm_create(intf, ep, maxcom, &wdm_manage_power);
867 rv = wdm_create(intf, ep, bufsize, manage_power);
883 desc = wdm_find_device(intf);
892 spin_unlock_irqrestore(&desc->
iuspin, flags);
902 spin_lock(&wdm_device_list_lock);
904 spin_unlock(&wdm_device_list_lock);
909 dev_dbg(&intf->dev,
"%s: %d open files - postponing cleanup\n", __func__, desc->
count);
916 struct wdm_device *desc = wdm_find_device(intf);
919 dev_dbg(&desc->
intf->dev,
"wdm%d_suspend\n", intf->minor);
926 spin_lock_irq(&desc->
iuspin);
931 spin_unlock_irq(&desc->
iuspin);
936 spin_unlock_irq(&desc->
iuspin);
950 static int recover_from_urb_loss(
struct wdm_device *desc)
958 "Error resume submitting int urb - %d\n", rv);
966 struct wdm_device *desc = wdm_find_device(intf);
969 dev_dbg(&desc->
intf->dev,
"wdm%d_resume\n", intf->minor);
972 rv = recover_from_urb_loss(desc);
980 struct wdm_device *desc = wdm_find_device(intf);
988 spin_lock_irq(&desc->
iuspin);
993 spin_unlock_irq(&desc->
iuspin);
1004 struct wdm_device *desc = wdm_find_device(intf);
1008 rv = recover_from_urb_loss(desc);
1014 static struct usb_driver wdm_driver = {
1017 .disconnect = wdm_disconnect,
1019 .suspend = wdm_suspend,
1020 .resume = wdm_resume,
1021 .reset_resume = wdm_resume,
1023 .pre_reset = wdm_pre_reset,
1024 .post_reset = wdm_post_reset,
1025 .id_table = wdm_ids,
1026 .supports_autosuspend = 1,
1027 .disable_hub_initiated_lpm = 1,