NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
kern/40049: Openmoko Freerunner CDC Ethernet emulation does not work
>Number: 40049
>Category: kern
>Synopsis: Support more USB CDC Ethernet devices (eg Openmoko Freerunner)
>Confidential: no
>Severity: serious
>Priority: high
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Thu Nov 27 18:05:00 +0000 2008
>Originator: Pierre Pronchery <ppronchery%bearstech.com@localhost>
>Release: NetBSD 5.0_BETA
>Organization:
Bearstech
>Environment:
System: NetBSD syn.defora.rom 5.0_BETA NetBSD 5.0_BETA (GENERIC) #11: Thu Nov
27 17:41:49 CET 2008
khorben%syn.defora.rom@localhost:/usr/obj/sys/arch/amd64/compile/GENERIC amd64
Architecture: x86_64
Machine: amd64
>Description:
The Openmoko Freerunner is not successfully recognized as a CDC Ethernet
device. FreeBSD has code for USB cable modems that makes this work (patch
attached).
>How-To-Repeat:
Plug an Openmoko Freerunner into the USB port:
$ dmesg | grep cdce0
cdce0 at uhub0 port 2 configuration 1 interface 0
cdce0: Linux 2.6.24/s3c2410_udc RNDIS/Ethernet Gadget, rev 2.00/2.12, addr 2
cdce0: could not find data bulk in
And then the cdce0 interface does not exist.
>Fix:
With the following patch from FreeBSD:
$ ifconfig cdce0
cdce0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
address: 2a:27:01:00:00:00
inet 192.168.0.200 netmask 0xffffff00 broadcast 192.168.0.255
Index: sys/dev/usb/if_cdce.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/if_cdce.c,v
retrieving revision 1.18
diff -p -u -r1.18 if_cdce.c
--- sys/dev/usb/if_cdce.c 24 Sep 2008 07:19:18 -0000 1.18
+++ sys/dev/usb/if_cdce.c 27 Nov 2008 16:54:55 -0000
@@ -154,8 +154,9 @@ USB_ATTACH(cdce)
usb_interface_descriptor_t *id;
usb_endpoint_descriptor_t *ed;
const usb_cdc_union_descriptor_t *ud;
+ usb_config_descriptor_t *cd;
int data_ifcno;
- int i;
+ int i, j, numalts;
u_char eaddr[ETHER_ADDR_LEN];
const usb_cdc_ethernet_descriptor_t *ue;
char eaddr_str[USB_MAX_ENCODED_STRING_LEN];
@@ -202,29 +203,61 @@ USB_ATTACH(cdce)
USB_ATTACH_ERROR_RETURN;
}
- /* Find endpoints. */
+ /*
+ * <quote>
+ * The Data Class interface of a networking device shall have a minimum
+ * of two interface settings. The first setting (the default interface
+ * setting) includes no endpoints and therefore no networking traffic
is
+ * exchanged whenever the default interface setting is selected. One or
+ * more additional interface settings are used for normal operation,
and
+ * therefore each includes a pair of endpoints (one IN, and one OUT) to
+ * exchange network traffic. Select an alternate interface setting to
+ * initialize the network aspects of the device and to enable the
+ * exchange of network traffic.
+ * </quote>
+ *
+ * Some devices, most notably cable modems, include interface settings
+ * that have no IN or OUT endpoint, therefore loop through the list of
all
+ * available interface settings looking for one with both IN and OUT
+ * 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) {
- aprint_error_dev(self,
- "could not read endpoint descriptor\n");
+ 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)) {
+ aprint_error_dev(sc->cdce_dev,
+ "setting alternate interface failed\n");
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 {
- aprint_error_dev(self, "unexpected endpoint\n");
+ /* 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) {
+ aprint_error_dev(self,
+ "could not read endpoint
descriptor\n");
+ 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 {
+ aprint_error_dev(self, "unexpected endpoint\n");
+ }
}
+ /* 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) {
Home |
Main Index |
Thread Index |
Old Index