Minimal (relatively) patch to make my Nokia 9300 smartphone which uses
authorHasso Tepper <hasso@dragonflybsd.org>
Thu, 2 Aug 2007 16:19:17 +0000 (16:19 +0000)
committerHasso Tepper <hasso@dragonflybsd.org>
Thu, 2 Aug 2007 16:19:17 +0000 (16:19 +0000)
union descriptors, work in DF.

Obtained-from: NetBSD with modifications

sys/bus/usb/usbdi_util.c
sys/bus/usb/usbdi_util.h
sys/dev/usbmisc/umodem/umodem.c

index d3a89e8..f5cabd3 100644 (file)
@@ -1,6 +1,6 @@
 /*     $NetBSD: usbdi_util.c,v 1.42 2004/12/03 08:53:40 augustss Exp $ */
 /*     $FreeBSD: src/sys/dev/usb/usbdi_util.c,v 1.34 2005/03/01 08:01:22 sobomax Exp $ */
-/*     $DragonFly: src/sys/bus/usb/usbdi_util.c,v 1.15 2007/07/03 19:28:16 hasso Exp $ */
+/*     $DragonFly: src/sys/bus/usb/usbdi_util.c,v 1.16 2007/08/02 16:19:17 hasso Exp $ */
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -535,3 +535,30 @@ usb_find_desc(usbd_device_handle dev, int type, int subtype)
        }
        return desc;
 }
+
+/* same as usb_find_desc(), but searches only in the specified interface. */
+const usb_descriptor_t *
+usb_find_desc_if(usbd_device_handle dev, int type, int subtype,
+                usb_interface_descriptor_t *id)
+{
+       usbd_desc_iter_t iter;
+       const usb_descriptor_t *desc;
+
+       usb_desc_iter_init(dev, &iter);
+
+       iter.cur = (void *)id;          /* start from the interface desc */
+       usb_desc_iter_next(&iter);      /* and skip it */
+
+       while ((desc = usb_desc_iter_next(&iter)) != NULL) {
+               if (desc->bDescriptorType == UDESC_INTERFACE) {
+                       /* we ran into the next interface --- not found */
+                       return NULL;
+               }
+               if (desc->bDescriptorType == type &&
+                    (subtype == USBD_SUBTYPE_ANY ||
+                     subtype == desc->bDescriptorSubtype))
+                       break;
+       }
+       return desc;
+}
+
index ceb6960..ba6d94a 100644 (file)
@@ -1,6 +1,6 @@
 /*     $NetBSD: usbdi_util.h,v 1.31 2004/12/03 08:53:40 augustss Exp $ */
 /*     $FreeBSD: src/sys/dev/usb/usbdi_util.h,v 1.19 2005/03/01 08:01:22 sobomax Exp $ */
-/*     $DragonFly: src/sys/bus/usb/usbdi_util.h,v 1.6 2007/07/03 19:28:16 hasso Exp $  */
+/*     $DragonFly: src/sys/bus/usb/usbdi_util.h,v 1.7 2007/08/02 16:19:17 hasso Exp $  */
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -92,5 +92,8 @@ void usb_detach_wakeup(device_t);
 
 const usb_descriptor_t *usb_find_desc(usbd_device_handle dev, int type,
                                      int subtype);
+const usb_descriptor_t *usb_find_desc_if(usbd_device_handle dev, int type,
+                                        int subtype,
+                                        usb_interface_descriptor_t *id);
 #define USBD_SUBTYPE_ANY (~0)
 
index 62f5961..cdeda9c 100644 (file)
@@ -2,7 +2,7 @@
  * $NetBSD: umodem.c,v 1.5 1999/01/08 11:58:25 augustss Exp $
  * $NetBSD: umodem.c,v 1.45 2002/09/23 05:51:23 simonb Exp $
  * $FreeBSD: src/sys/dev/usb/umodem.c,v 1.48 2003/08/24 17:55:55 obrien Exp $
- * $DragonFly: src/sys/dev/usbmisc/umodem/umodem.c,v 1.16 2007/07/03 19:28:16 hasso Exp $
+ * $DragonFly: src/sys/dev/usbmisc/umodem/umodem.c,v 1.17 2007/08/02 16:19:17 hasso Exp $
  */
 
 /*-
@@ -157,13 +157,13 @@ struct umodem_softc {
        u_char                  sc_msr;         /* Modem status register */
 };
 
-static void    *umodem_get_desc(usbd_device_handle dev, int type, int subtype);
 static usbd_status umodem_set_comm_feature(struct umodem_softc *sc,
                                           int feature, int state);
 static usbd_status umodem_set_line_coding(struct umodem_softc *sc,
                                          usb_cdc_line_state_t *state);
 
-static void    umodem_get_caps(usbd_device_handle, int *, int *);
+static int     umodem_get_caps(usbd_device_handle, int *, int *,
+                               usb_interface_descriptor_t *);
 
 static void    umodem_get_status(void *, int portno, u_char *lsr, u_char *msr);
 static void    umodem_set(void *, int, int, int);
@@ -228,10 +228,7 @@ umodem_match(device_t self)
            id->bInterfaceProtocol != UIPROTO_CDC_AT)
                return (UMATCH_NONE);
 
-       umodem_get_caps(uaa->device, &cm, &acm);
-       if (!(cm & USB_CDC_CM_DOES_CM) ||
-           !(cm & USB_CDC_CM_OVER_DATA) ||
-           !(acm & USB_CDC_ACM_HAS_LINE))
+       if (umodem_get_caps(uaa->device, &cm, &acm, id) == -1)
                return (UMATCH_NONE);
 
        return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO);
@@ -245,7 +242,6 @@ umodem_attach(device_t self)
        usbd_device_handle dev = uaa->device;
        usb_interface_descriptor_t *id;
        usb_endpoint_descriptor_t *ed;
-       usb_cdc_cm_descriptor_t *cmd;
        char *devinfo = NULL;
        const char *devname;
        usbd_status err;
@@ -272,15 +268,13 @@ umodem_attach(device_t self)
          id->bInterfaceClass, id->bInterfaceSubClass);
        sc->sc_ctl_iface_no = id->bInterfaceNumber;
 
-       umodem_get_caps(dev, &sc->sc_cm_cap, &sc->sc_acm_cap);
+       sc->sc_data_iface_no = data_ifcno =
+               umodem_get_caps(dev, &sc->sc_cm_cap, &sc->sc_acm_cap, id);
 
-       /* Get the data interface no. */
-       cmd = umodem_get_desc(dev, UDESC_CS_INTERFACE, UDESCSUB_CDC_CM);
-       if (cmd == NULL) {
-               kprintf("%s: no CM descriptor\n", devname);
+       if (data_ifcno == -1) {
+               kprintf("%s: no pointer to data interface\n", devname);
                goto bad;
        }
-       sc->sc_data_iface_no = data_ifcno = cmd->bDataInterface;
 
        kprintf("%s: data interface %d, has %sCM over data, has %sbreak\n",
               devname, data_ifcno,
@@ -505,27 +499,39 @@ umodem_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
        }
 }
 
-void
-umodem_get_caps(usbd_device_handle dev, int *cm, int *acm)
+int
+umodem_get_caps(usbd_device_handle dev, int *cm, int *acm,
+               usb_interface_descriptor_t *id)
 {
-       usb_cdc_cm_descriptor_t *cmd;
-       usb_cdc_acm_descriptor_t *cad;
+       const usb_cdc_cm_descriptor_t *cmd;
+       const usb_cdc_acm_descriptor_t *cad;
+       const usb_cdc_union_descriptor_t *cud;
 
        *cm = *acm = 0;
 
-       cmd = umodem_get_desc(dev, UDESC_CS_INTERFACE, UDESCSUB_CDC_CM);
-       if (cmd == NULL) {
-               DPRINTF(("umodem_get_desc: no CM desc\n"));
-               return;
-       }
-       *cm = cmd->bmCapabilities;
+       cmd = (const usb_cdc_cm_descriptor_t *)usb_find_desc_if(dev,
+                                                       UDESC_CS_INTERFACE,
+                                                       UDESCSUB_CDC_CM, id);
+       if (cmd == NULL)
+               DPRINTF(("umodem_get_caps: no CM desc\n"));
+       else
+               *cm = cmd->bmCapabilities;
 
-       cad = umodem_get_desc(dev, UDESC_CS_INTERFACE, UDESCSUB_CDC_ACM);
-       if (cad == NULL) {
-               DPRINTF(("umodem_get_desc: no ACM desc\n"));
-               return;
-       }
-       *acm = cad->bmCapabilities;
+       cad = (const usb_cdc_acm_descriptor_t *)usb_find_desc_if(dev,
+                                                       UDESC_CS_INTERFACE,
+                                                       UDESCSUB_CDC_ACM, id);
+       if (cad == NULL)
+               DPRINTF(("umodem_get_caps: no ACM desc\n"));
+       else
+               *acm = cad->bmCapabilities;
+
+       cud = (const usb_cdc_union_descriptor_t *)usb_find_desc_if(dev,
+                                                       UDESC_CS_INTERFACE,
+                                                       UDESCSUB_CDC_UNION, id);
+       if (cud == NULL)
+               DPRINTF(("umodem_get_caps: no UNION desc\n"));
+
+       return cmd ? cmd->bDataInterface : cud ? cud->bSlaveInterface[0] : -1;
 }
 
 void
@@ -731,25 +737,6 @@ umodem_set_line_coding(struct umodem_softc *sc, usb_cdc_line_state_t *state)
        return (USBD_NORMAL_COMPLETION);
 }
 
-void *
-umodem_get_desc(usbd_device_handle dev, int type, int subtype)
-{
-       usb_descriptor_t *desc;
-       usb_config_descriptor_t *cd = usbd_get_config_descriptor(dev);
-        uByte *p = (uByte *)cd;
-        uByte *end = p + UGETW(cd->wTotalLength);
-
-       while (p < end) {
-               desc = (usb_descriptor_t *)p;
-               if (desc->bDescriptorType == type &&
-                   desc->bDescriptorSubtype == subtype)
-                       return (desc);
-               p += desc->bLength;
-       }
-
-       return (0);
-}
-
 usbd_status
 umodem_set_comm_feature(struct umodem_softc *sc, int feature, int state)
 {