umodem(4) doesn't support devices that don't have a data interface.
this patch moves a chunk of code from the driver's attach function
that iterates over the usb descriptors to find the data endpoint
and other capabilities to a separate function.  this function is
then used in the match function, and if the data interface isn't
found, returns UMATCH_NONE.

this keeps umodem from attaching to the MSP430 on the TI Launchapd,
which has no data interface.  (jasper@ has a port for mspdebug which
can be used with the Launchpad through ugen(4)).

this is like what I did before with umidi/uaudio ...

except I don't have a umodem(4) to actually test that I didn't break
this.  please test this if you have a umodem(4).  thanks.

-- 
[email protected]
SDF Public Access UNIX System - http://sdf.lonestar.org

Index: umodem.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/umodem.c,v
retrieving revision 1.38
diff -u -p -r1.38 umodem.c
--- umodem.c    24 Sep 2010 08:33:59 -0000      1.38
+++ umodem.c    30 Nov 2010 01:04:08 -0000
@@ -91,7 +91,6 @@ struct umodem_softc {
 
        int                      sc_ctl_iface_no;
        usbd_interface_handle    sc_ctl_iface;  /* control interface */
-       int                      sc_data_iface_no;
        usbd_interface_handle    sc_data_iface; /* data interface */
 
        int                      sc_cm_cap;     /* CM capabilities */
@@ -148,6 +147,8 @@ void umodem_attach(struct device *, stru
 int umodem_detach(struct device *, int); 
 int umodem_activate(struct device *, int); 
 
+void umodem_get_caps(struct usb_attach_arg *, int, int *, int *, int *);
+
 struct cfdriver umodem_cd = { 
        NULL, "umodem", DV_DULL 
 }; 
@@ -160,21 +161,63 @@ const struct cfattach umodem_ca = { 
        umodem_activate, 
 };
 
+void
+umodem_get_caps(struct usb_attach_arg *uaa, int ctl_iface_no,
+    int *data_iface_no, int *cm_cap, int *acm_cap)
+{
+       const usb_descriptor_t *desc;
+       const usb_interface_descriptor_t *id;
+       const usb_cdc_cm_descriptor_t *cmd;
+       const usb_cdc_acm_descriptor_t *acmd;
+       const usb_cdc_union_descriptor_t *uniond;
+       usbd_desc_iter_t iter;
+       int current_iface_no = -1;
+
+       *cm_cap = *acm_cap = 0;
+       usb_desc_iter_init(uaa->device, &iter);
+       desc = usb_desc_iter_next(&iter);
+       while (desc) {
+               if (desc->bDescriptorType == UDESC_INTERFACE) {
+                   id = (usb_interface_descriptor_t *)desc;
+                   current_iface_no = id->bInterfaceNumber;
+               }
+               if (current_iface_no == ctl_iface_no &&
+                   desc->bDescriptorType == UDESC_CS_INTERFACE) {
+                       switch(desc->bDescriptorSubtype) {
+                       case UDESCSUB_CDC_CM:
+                               cmd = (usb_cdc_cm_descriptor_t *)desc;
+                               *cm_cap = cmd->bmCapabilities;
+                               *data_iface_no = cmd->bDataInterface;
+                               break;
+                       case UDESCSUB_CDC_ACM:
+                               acmd = (usb_cdc_acm_descriptor_t *)desc;
+                               *acm_cap = acmd->bmCapabilities;
+                               break;
+                       case UDESCSUB_CDC_UNION:
+                               uniond = (usb_cdc_union_descriptor_t *)desc;
+                               *data_iface_no = uniond->bSlaveInterface[0];
+                               break;
+                       }
+               }
+               desc = usb_desc_iter_next(&iter);
+       }
+}
+
 int
 umodem_match(struct device *parent, void *match, void *aux)
 {
        struct usb_attach_arg *uaa = aux;
        usb_interface_descriptor_t *id;
        usb_device_descriptor_t *dd;
-       int ret;
+       int data_iface_no, cm_cap, acm_cap, ret = UMATCH_NONE;
 
        if (uaa->iface == NULL)
-               return (UMATCH_NONE);
+               return (ret);
 
        id = usbd_get_interface_descriptor(uaa->iface);
        dd = usbd_get_device_descriptor(uaa->device);
        if (id == NULL || dd == NULL)
-               return (UMATCH_NONE);
+               return (ret);
 
        ret = UMATCH_NONE;
        if (UGETW(dd->idVendor) == USB_VENDOR_KYOCERA &&
@@ -188,6 +231,15 @@ umodem_match(struct device *parent, void
            id->bInterfaceProtocol == UIPROTO_CDC_AT)
                ret = UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO;
 
+       if (ret == UMATCH_NONE)
+               return (ret);
+
+       /* umodem doesn't yet support devices without a data iface */
+       umodem_get_caps(uaa, id->bInterfaceNumber, &data_iface_no,
+           &cm_cap, &acm_cap);
+       if (data_iface_no == 0)
+               ret = UMATCH_NONE;
+
        return (ret);
 }
 
@@ -199,14 +251,8 @@ umodem_attach(struct device *parent, str
        usbd_device_handle dev = uaa->device;
        usb_interface_descriptor_t *id;
        usb_endpoint_descriptor_t *ed;
-       usb_cdc_cm_descriptor_t *cmd;      
-       usb_interface_descriptor_t *idesc;
-       const usb_cdc_acm_descriptor_t *acmd;
-       const usb_cdc_union_descriptor_t *uniond;
-       const usb_descriptor_t *desc;
-       usbd_desc_iter_t iter;
        usbd_status err;
-       int current_iface_no = -1;
+       int data_iface_no = 0;
        int i;
        struct ucom_attach_args uca;
 
@@ -218,47 +264,17 @@ umodem_attach(struct device *parent, str
        //    id->bInterfaceClass, id->bInterfaceSubClass);
        sc->sc_ctl_iface_no = id->bInterfaceNumber;
 
-       /* Get the data interface no. and capabilities */
-       sc->sc_cm_cap = 0;
-       sc->sc_data_iface_no = 0;
-       sc->sc_acm_cap = 0;
-       usb_desc_iter_init(dev, &iter);
-       desc = usb_desc_iter_next(&iter);
-       while (desc) {
-               if (desc->bDescriptorType == UDESC_INTERFACE) {
-                   idesc = (usb_interface_descriptor_t *)desc;
-                   current_iface_no = idesc->bInterfaceNumber;
-               }
-               if (current_iface_no == sc->sc_ctl_iface_no &&
-                   desc->bDescriptorType == UDESC_CS_INTERFACE) {
-                       switch(desc->bDescriptorSubtype) {
-                       case UDESCSUB_CDC_CM:
-                               cmd = (usb_cdc_cm_descriptor_t *)desc;
-                               sc->sc_cm_cap = cmd->bmCapabilities;
-                               sc->sc_data_iface_no = cmd->bDataInterface;
-                               break;
-                       case UDESCSUB_CDC_ACM:
-                               acmd = (usb_cdc_acm_descriptor_t *)desc;
-                               sc->sc_acm_cap = acmd->bmCapabilities;
-                               break;
-                       case UDESCSUB_CDC_UNION:
-                               uniond = (usb_cdc_union_descriptor_t *)desc;
-                               sc->sc_data_iface_no =
-                                   uniond->bSlaveInterface[0];
-                               break;
-                       }
-               }
-               desc = usb_desc_iter_next(&iter);
-       }
-
-       if (sc->sc_data_iface_no == 0) {
+       /* Get the capabilities. */
+       umodem_get_caps(uaa, id->bInterfaceNumber, &data_iface_no,
+           &sc->sc_cm_cap, &sc->sc_acm_cap);
+       if (data_iface_no == 0) {
                printf("%s: no pointer to data interface\n",
                       sc->sc_dev.dv_xname);
                goto bad;
        }
 
        printf("%s: data interface %d, has %sCM over data, has %sbreak\n",
-              sc->sc_dev.dv_xname, sc->sc_data_iface_no,
+              sc->sc_dev.dv_xname, data_iface_no,
               sc->sc_cm_cap & USB_CDC_CM_OVER_DATA ? "" : "no ",
               sc->sc_acm_cap & USB_CDC_ACM_HAS_BREAK ? "" : "no ");
 
@@ -267,7 +283,7 @@ umodem_attach(struct device *parent, str
                if (uaa->ifaces[i] != NULL) {
                        id = usbd_get_interface_descriptor(uaa->ifaces[i]);
                        if (id != NULL &&
-                            id->bInterfaceNumber == sc->sc_data_iface_no) {
+                            id->bInterfaceNumber == data_iface_no) {
                                sc->sc_data_iface = uaa->ifaces[i];
                                uaa->ifaces[i] = NULL;
                        }

Reply via email to