- struct usb_host_config *cfacm;
- struct usb_interface *data = NULL;
- struct usb_host_interface *ifcom, *ifdata = NULL;
- struct usb_endpoint_descriptor *epctrl = NULL;
- struct usb_endpoint_descriptor *epread = NULL;
- struct usb_endpoint_descriptor *epwrite = NULL;
- int readsize, ctrlsize, minor, j;
- unsigned char *buf;
-
- dev = interface_to_usbdev (intf);
-
- cfacm = dev->actconfig;
-
- /* We know we're probe()d with the control interface. */
- ifcom = intf->cur_altsetting;
-
- /* ACM doesn't guarantee the data interface is
- * adjacent to the control interface, or that if one
- * is there it's not for call management ... so find
- * it
- */
- for (j = 0; j < cfacm->desc.bNumInterfaces; j++) {
- ifdata = cfacm->interface[j]->cur_altsetting;
- data = cfacm->interface[j];
-
- if (ifdata->desc.bInterfaceClass == USB_CLASS_CDC_DATA
- && ifdata->desc.bNumEndpoints == 2) {
-
- epctrl = &ifcom->endpoint[0].desc;
- epread = &ifdata->endpoint[0].desc;
- epwrite = &ifdata->endpoint[1].desc;
-
- if ((epctrl->bEndpointAddress & USB_DIR_IN) != USB_DIR_IN
- || !CHECK_XFERTYPE(epctrl, USB_ENDPOINT_XFER_INT)
- || !CHECK_XFERTYPE(epread, USB_ENDPOINT_XFER_BULK)
- || !CHECK_XFERTYPE(epwrite, USB_ENDPOINT_XFER_BULK)
- || ((epread->bEndpointAddress & USB_DIR_IN)
- ^ (epwrite->bEndpointAddress & USB_DIR_IN)) != USB_DIR_IN) {
- /* not suitable */
- goto next_interface;
- }
-
- if ((epread->bEndpointAddress & USB_DIR_IN) != USB_DIR_IN) {
- /* descriptors are swapped */
- epread = &ifdata->endpoint[1].desc;
- epwrite = &ifdata->endpoint[0].desc;
+ int minor;
+ int ctrlsize,readsize;
+ u8 *buf;
+ u8 ac_management_function = 0;
+ u8 call_management_function = 0;
+ int call_interface_num = -1;
+ int data_interface_num;
+ unsigned long quirks;
+ int num_rx_buf;
+ int i;
+
+ /* normal quirks */
+ quirks = (unsigned long)id->driver_info;
+ num_rx_buf = (quirks == SINGLE_RX_URB) ? 1 : ACM_NR;
+
+ /* handle quirks deadly to normal probing*/
+ if (quirks == NO_UNION_NORMAL) {
+ data_interface = usb_ifnum_to_if(usb_dev, 1);
+ control_interface = usb_ifnum_to_if(usb_dev, 0);
+ goto skip_normal_probe;
+ }
+
+ /* normal probing*/
+ if (!buffer) {
+ err("Wierd descriptor references\n");
+ return -EINVAL;
+ }
+
+ if (!buflen) {
+ if (intf->cur_altsetting->endpoint->extralen && intf->cur_altsetting->endpoint->extra) {
+ dev_dbg(&intf->dev,"Seeking extra descriptors on endpoint");
+ buflen = intf->cur_altsetting->endpoint->extralen;
+ buffer = intf->cur_altsetting->endpoint->extra;
+ } else {
+ err("Zero length descriptor references\n");
+ return -EINVAL;
+ }
+ }
+
+ while (buflen > 0) {
+ if (buffer [1] != USB_DT_CS_INTERFACE) {
+ err("skipping garbage\n");
+ goto next_desc;
+ }
+
+ switch (buffer [2]) {
+ case USB_CDC_UNION_TYPE: /* we've found it */
+ if (union_header) {
+ err("More than one union descriptor, skipping ...");
+ goto next_desc;
+ }
+ union_header = (struct usb_cdc_union_desc *)
+ buffer;
+ break;
+ case USB_CDC_COUNTRY_TYPE: /* maybe somehow export */
+ break; /* for now we ignore it */
+ case USB_CDC_HEADER_TYPE: /* maybe check version */
+ break; /* for now we ignore it */
+ case USB_CDC_ACM_TYPE:
+ ac_management_function = buffer[3];
+ break;
+ case USB_CDC_CALL_MANAGEMENT_TYPE:
+ call_management_function = buffer[3];
+ call_interface_num = buffer[4];
+ if ((call_management_function & 3) != 3)
+ err("This device cannot do calls on its own. It is no modem.");
+ break;
+
+ default:
+ err("Ignoring extra header, type %d, length %d", buffer[2], buffer[0]);
+ break;