aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/class/cdc-wdm.c
diff options
context:
space:
mode:
authorBjørn Mork <bjorn@mork.no>2012-03-06 11:29:20 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-03-08 16:06:48 -0500
commit0dffb4862a5f109dc9b72e3a4e0ecc85a87ce397 (patch)
treee45b3920a374874225d1c0efe4c44d0167a977d0 /drivers/usb/class/cdc-wdm.c
parentc1cee1d84001815a1b4321c49b995254c0df3100 (diff)
usb: cdc-wdm: split out reusable parts of probe
Preparing for the addition of subdriver registering as an alternative to probe for interface-less usage. This should not change anything apart from minor code reordering. Signed-off-by: Bjørn Mork <bjorn@mork.no> Acked-by: Oliver Neukum <oneukum@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/class/cdc-wdm.c')
-rw-r--r--drivers/usb/class/cdc-wdm.c105
1 files changed, 54 insertions, 51 deletions
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 6037b503153..451793036d3 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -631,47 +631,11 @@ static void wdm_rxwork(struct work_struct *work)
631 631
632/* --- hotplug --- */ 632/* --- hotplug --- */
633 633
634static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id) 634static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor *ep, u16 bufsize)
635{ 635{
636 int rv = -EINVAL; 636 int rv = -ENOMEM;
637 struct wdm_device *desc; 637 struct wdm_device *desc;
638 struct usb_host_interface *iface;
639 struct usb_endpoint_descriptor *ep;
640 struct usb_cdc_dmm_desc *dmhd;
641 u8 *buffer = intf->altsetting->extra;
642 int buflen = intf->altsetting->extralen;
643 u16 maxcom = WDM_DEFAULT_BUFSIZE;
644
645 if (!buffer)
646 goto out;
647
648 while (buflen > 2) {
649 if (buffer [1] != USB_DT_CS_INTERFACE) {
650 dev_err(&intf->dev, "skipping garbage\n");
651 goto next_desc;
652 }
653
654 switch (buffer [2]) {
655 case USB_CDC_HEADER_TYPE:
656 break;
657 case USB_CDC_DMM_TYPE:
658 dmhd = (struct usb_cdc_dmm_desc *)buffer;
659 maxcom = le16_to_cpu(dmhd->wMaxCommand);
660 dev_dbg(&intf->dev,
661 "Finding maximum buffer length: %d", maxcom);
662 break;
663 default:
664 dev_err(&intf->dev,
665 "Ignoring extra header, type %d, length %d\n",
666 buffer[2], buffer[0]);
667 break;
668 }
669next_desc:
670 buflen -= buffer[0];
671 buffer += buffer[0];
672 }
673 638
674 rv = -ENOMEM;
675 desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL); 639 desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL);
676 if (!desc) 640 if (!desc)
677 goto out; 641 goto out;
@@ -679,18 +643,14 @@ next_desc:
679 mutex_init(&desc->wlock); 643 mutex_init(&desc->wlock);
680 spin_lock_init(&desc->iuspin); 644 spin_lock_init(&desc->iuspin);
681 init_waitqueue_head(&desc->wait); 645 init_waitqueue_head(&desc->wait);
682 desc->wMaxCommand = maxcom; 646 desc->wMaxCommand = bufsize;
683 /* this will be expanded and needed in hardware endianness */ 647 /* this will be expanded and needed in hardware endianness */
684 desc->inum = cpu_to_le16((u16)intf->cur_altsetting->desc.bInterfaceNumber); 648 desc->inum = cpu_to_le16((u16)intf->cur_altsetting->desc.bInterfaceNumber);
685 desc->intf = intf; 649 desc->intf = intf;
686 INIT_WORK(&desc->rxwork, wdm_rxwork); 650 INIT_WORK(&desc->rxwork, wdm_rxwork);
687 651
688 rv = -EINVAL; 652 rv = -EINVAL;
689 iface = intf->cur_altsetting; 653 if (!usb_endpoint_is_int_in(ep))
690 if (iface->desc.bNumEndpoints != 1)
691 goto err;
692 ep = &iface->endpoint[0].desc;
693 if (!ep || !usb_endpoint_is_int_in(ep))
694 goto err; 654 goto err;
695 655
696 desc->wMaxPacketSize = usb_endpoint_maxp(ep); 656 desc->wMaxPacketSize = usb_endpoint_maxp(ep);
@@ -766,13 +726,56 @@ out:
766err2: 726err2:
767 usb_set_intfdata(intf, NULL); 727 usb_set_intfdata(intf, NULL);
768err: 728err:
769 free_urbs(desc); 729 cleanup(desc);
770 kfree(desc->inbuf); 730 return rv;
771 kfree(desc->sbuf); 731}
772 kfree(desc->ubuf); 732
773 kfree(desc->orq); 733static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id)
774 kfree(desc->irq); 734{
775 kfree(desc); 735 int rv = -EINVAL;
736 struct usb_host_interface *iface;
737 struct usb_endpoint_descriptor *ep;
738 struct usb_cdc_dmm_desc *dmhd;
739 u8 *buffer = intf->altsetting->extra;
740 int buflen = intf->altsetting->extralen;
741 u16 maxcom = WDM_DEFAULT_BUFSIZE;
742
743 if (!buffer)
744 goto err;
745 while (buflen > 2) {
746 if (buffer[1] != USB_DT_CS_INTERFACE) {
747 dev_err(&intf->dev, "skipping garbage\n");
748 goto next_desc;
749 }
750
751 switch (buffer[2]) {
752 case USB_CDC_HEADER_TYPE:
753 break;
754 case USB_CDC_DMM_TYPE:
755 dmhd = (struct usb_cdc_dmm_desc *)buffer;
756 maxcom = le16_to_cpu(dmhd->wMaxCommand);
757 dev_dbg(&intf->dev,
758 "Finding maximum buffer length: %d", maxcom);
759 break;
760 default:
761 dev_err(&intf->dev,
762 "Ignoring extra header, type %d, length %d\n",
763 buffer[2], buffer[0]);
764 break;
765 }
766next_desc:
767 buflen -= buffer[0];
768 buffer += buffer[0];
769 }
770
771 iface = intf->cur_altsetting;
772 if (iface->desc.bNumEndpoints != 1)
773 goto err;
774 ep = &iface->endpoint[0].desc;
775
776 rv = wdm_create(intf, ep, maxcom);
777
778err:
776 return rv; 779 return rv;
777} 780}
778 781