summaryrefslogtreecommitdiff
path: root/comms/cdce/files/patch-if_cdce.c
blob: 18d48f299adeb80a6a3be57b88e18b293f2c77c6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
$FreeBSD$

--- if_cdce.c
+++ if_cdce.c
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$Id: if_cdce.c,v 1.1 2005/02/27 08:06:48 root Exp root $");
+__FBSDID("$Id: if_cdce.c 148 2005-01-16 02:20:53Z craig $");
 
 /* USB Communication Device Class (Ethernet Networking Control Model)
  *
@@ -158,11 +158,12 @@
     usb_interface_descriptor_t *id;
     usb_endpoint_descriptor_t *ed;
     usb_cdc_union_descriptor_t *ud;
+    usb_config_descriptor_t *cd;
     struct ifnet *ifp;
     int data_ifcno;
     u_int16_t macaddr_hi;
     char devinfo[1024];
-    int i;
+    int i, j, numalts;
 
     bzero(sc, sizeof(struct cdce_softc));
     sc->cdce_udev = uaa->device;
@@ -206,29 +207,52 @@
 	USB_ATTACH_ERROR_RETURN;
     }
     
-    /* Find endpoints. */
+    /*
+     * In the case of my CDCEthernet modem, there are several alternate
+     * interface possibilities -- the default first one does not work
+     * (though in the original code it probably worked for those devices
+     * which were supported), and in my case, the next alternate setting
+     * gives me the desired interface.  There's another one that also
+     * does not work, so we loop through the possibilities and take the
+     * first one that works.
+     */
     id = usbd_get_interface_descriptor(sc->cdce_data_iface);
-    sc->cdce_bulkin_no = sc->cdce_bulkout_no = -1;
-    for (i = 0; i < id->bNumEndpoints; i++) {
-	ed = usbd_interface2endpoint_descriptor(sc->cdce_data_iface, i);
-	if (!ed) {
-	    printf("%s: could not read endpoint descriptor\n",
-		   sc->cdce_name);
-	    USB_ATTACH_ERROR_RETURN;
-	}
-	if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
-		UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
-	    sc->cdce_bulkin_no = ed->bEndpointAddress;
-	} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
-		UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
-	    sc->cdce_bulkout_no = ed->bEndpointAddress;
-	} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
-		UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
-	    /* XXX: CDC spec defines an interrupt pipe, but it is not
-	     * needed for simple host-to-host applications. */
-	} else {
-	    printf("%s: unexpected endpoint\n", sc->cdce_name);
-	}
+    cd = usbd_get_config_descriptor(sc->cdce_udev);
+    numalts = usbd_get_no_alts(cd, id->bInterfaceNumber);
+
+    for (j = 0; j < numalts; j++) {
+        if (usbd_set_interface(sc->cdce_data_iface, j)) {
+            printf("%s: setting alternate interface failed\n",
+                sc->cdce_name);
+            USB_ATTACH_ERROR_RETURN;
+        }
+        /* Find endpoints. */
+        id = usbd_get_interface_descriptor(sc->cdce_data_iface);
+        sc->cdce_bulkin_no = sc->cdce_bulkout_no = -1;
+        for (i = 0; i < id->bNumEndpoints; i++) {
+	    ed = usbd_interface2endpoint_descriptor(sc->cdce_data_iface, i);
+	    if (!ed) {
+	        printf("%s: could not read endpoint descriptor\n",
+		       sc->cdce_name);
+	        USB_ATTACH_ERROR_RETURN;
+	    }
+	    if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
+		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
+	        sc->cdce_bulkin_no = ed->bEndpointAddress;
+	    } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
+		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
+	        sc->cdce_bulkout_no = ed->bEndpointAddress;
+	    } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
+		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
+	        /* XXX: CDC spec defines an interrupt pipe, but it is not
+	         * needed for simple host-to-host applications. */
+	    } else {
+	        printf("%s: unexpected endpoint\n", sc->cdce_name);
+	    }
+        }
+        /* If we found something, try and use it... */
+        if ((sc->cdce_bulkin_no != -1) && (sc->cdce_bulkout_no != -1))
+            break;
     }
 
     if (sc->cdce_bulkin_no == -1) {