summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorthompsa <thompsa@FreeBSD.org>2009-03-05 16:15:07 +0000
committerthompsa <thompsa@FreeBSD.org>2009-03-05 16:15:07 +0000
commitb361d86b12aff3f4070e243c13a0597d415825f1 (patch)
treef7be45db05c4932e22c963b690b5dfa193b3694d
parent95e639db1b991fdc54d20f37e7074d73033bdcd8 (diff)
downloadFreeBSD-src-b361d86b12aff3f4070e243c13a0597d415825f1.zip
FreeBSD-src-b361d86b12aff3f4070e243c13a0597d415825f1.tar.gz
Add support for the UNION interface descriptor, used by Nokia phones.
PR: usb/117185
-rw-r--r--sys/dev/usb/serial/umodem.c49
1 files changed, 22 insertions, 27 deletions
diff --git a/sys/dev/usb/serial/umodem.c b/sys/dev/usb/serial/umodem.c
index 88c5dd9..9960635 100644
--- a/sys/dev/usb/serial/umodem.c
+++ b/sys/dev/usb/serial/umodem.c
@@ -69,6 +69,7 @@ __FBSDID("$FreeBSD$");
/*
* Comm Class spec: http://www.usb.org/developers/devclass_docs/usbccs10.pdf
* http://www.usb.org/developers/devclass_docs/usbcdc11.pdf
+ * http://www.usb.org/developers/devclass_docs/cdc_wmc10.zip
*/
/*
@@ -253,8 +254,6 @@ static int
umodem_probe(device_t dev)
{
struct usb2_attach_arg *uaa = device_get_ivars(dev);
- uint8_t cm;
- uint8_t acm;
int error;
DPRINTFN(11, "\n");
@@ -263,19 +262,6 @@ umodem_probe(device_t dev)
return (ENXIO);
}
error = usb2_lookup_id_by_uaa(umodem_devs, sizeof(umodem_devs), uaa);
- if (error) {
- return (error);
- }
- if (uaa->driver_info == NULL) {
- /* some modems do not have any capabilities */
- return (error);
- }
- umodem_get_caps(uaa, &cm, &acm);
- if (!(cm & USB_CDC_CM_DOES_CM) ||
- !(cm & USB_CDC_CM_OVER_DATA) ||
- !(acm & USB_CDC_ACM_HAS_LINE)) {
- error = ENXIO;
- }
return (error);
}
@@ -285,6 +271,7 @@ umodem_attach(device_t dev)
struct usb2_attach_arg *uaa = device_get_ivars(dev);
struct umodem_softc *sc = device_get_softc(dev);
struct usb2_cdc_cm_descriptor *cmd;
+ struct usb2_cdc_union_descriptor *cud;
uint8_t i;
int error;
@@ -302,10 +289,20 @@ umodem_attach(device_t dev)
cmd = umodem_get_desc(uaa, UDESC_CS_INTERFACE, UDESCSUB_CDC_CM);
if ((cmd == NULL) || (cmd->bLength < sizeof(*cmd))) {
- device_printf(dev, "no CM descriptor!\n");
- goto detach;
+
+ cud = usb2_find_descriptor(uaa->device, NULL,
+ uaa->info.bIfaceIndex, UDESC_CS_INTERFACE,
+ 0 - 1, UDESCSUB_CDC_UNION, 0 - 1);
+
+ if ((cud == NULL) || (cud->bLength < sizeof(*cud))) {
+ device_printf(dev, "no CM or union descriptor!\n");
+ goto detach;
+ }
+
+ sc->sc_data_iface_no = cud->bSlaveInterface[0];
+ } else {
+ sc->sc_data_iface_no = cmd->bDataInterface;
}
- sc->sc_data_iface_no = cmd->bDataInterface;
device_printf(dev, "data interface %d, has %sCM over "
"data, has %sbreak\n",
@@ -419,21 +416,19 @@ umodem_get_caps(struct usb2_attach_arg *uaa, uint8_t *cm, uint8_t *acm)
struct usb2_cdc_cm_descriptor *cmd;
struct usb2_cdc_acm_descriptor *cad;
- *cm = *acm = 0;
-
cmd = umodem_get_desc(uaa, UDESC_CS_INTERFACE, UDESCSUB_CDC_CM);
if ((cmd == NULL) || (cmd->bLength < sizeof(*cmd))) {
- DPRINTF("no CM desc\n");
- return;
- }
- *cm = cmd->bmCapabilities;
+ DPRINTF("no CM desc (faking one)\n");
+ *cm = USB_CDC_CM_DOES_CM | USB_CDC_CM_OVER_DATA;
+ } else
+ *cm = cmd->bmCapabilities;
cad = umodem_get_desc(uaa, UDESC_CS_INTERFACE, UDESCSUB_CDC_ACM);
if ((cad == NULL) || (cad->bLength < sizeof(*cad))) {
DPRINTF("no ACM desc\n");
- return;
- }
- *acm = cad->bmCapabilities;
+ *acm = 0;
+ } else
+ *acm = cad->bmCapabilities;
}
static void
OpenPOWER on IntegriCloud