Module Name: src
Committed By: tron
Date: Sun Aug 16 14:18:49 UTC 2009
Modified Files:
src/sys/dev/usb: if_cdce.c
Log Message:
Add support for the Openmoko Freerunner to cdce(4) ported from FreeBSD.
The patch was supplied by Pierre Pronchery in PR kern/40049.
To generate a diff of this commit:
cvs rdiff -u -r1.21 -r1.22 src/sys/dev/usb/if_cdce.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/usb/if_cdce.c
diff -u src/sys/dev/usb/if_cdce.c:1.21 src/sys/dev/usb/if_cdce.c:1.22
--- src/sys/dev/usb/if_cdce.c:1.21 Sat Apr 18 14:58:04 2009
+++ src/sys/dev/usb/if_cdce.c Sun Aug 16 14:18:49 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: if_cdce.c,v 1.21 2009/04/18 14:58:04 tsutsui Exp $ */
+/* $NetBSD: if_cdce.c,v 1.22 2009/08/16 14:18:49 tron Exp $ */
/*
* Copyright (c) 1997, 1998, 1999, 2000-2003 Bill Paul <[email protected]>
@@ -41,7 +41,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_cdce.c,v 1.21 2009/04/18 14:58:04 tsutsui Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_cdce.c,v 1.22 2009/08/16 14:18:49 tron Exp $");
#include "bpfilter.h"
#ifdef __NetBSD__
#include "opt_inet.h"
@@ -154,8 +154,9 @@
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_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) {