Date: Wed, 16 Jul 2008 13:00:10 GMT From: Alexey Dokuchaev <danfe@nsu.ru> To: freebsd-usb@FreeBSD.org Subject: Re: usb/117185: [umodem] [patch] Add support for UNION interface descriptor Message-ID: <200807161300.m6GD0A8a042062@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR usb/117185; it has been noted by GNATS. From: Alexey Dokuchaev <danfe@nsu.ru> To: bug-followup@FreeBSD.org, eugen@grosbein.pp.ru Cc: imp@bsdimp.com Subject: Re: usb/117185: [umodem] [patch] Add support for UNION interface descriptor Date: Wed, 16 Jul 2008 19:00:17 +0700 --YiEDa0DAkWCtVeE4 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Just confirmed to fix my Nokia E60 on 6-STABLE (had to change the patch slightly to fit 6.x codebase). P.S. Warner, you mentioned that you were going to take a look at NetBSD (which this patch originates from) changes and merge the fix (usb/91546, obsolete now). Could you possibly take a look now? People say this code had been pretty stable for them for several months by now. Provided 6.x is also covered, I look forward for a merge. Thanks. --YiEDa0DAkWCtVeE4 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="umodem-nokia-releng6.patch" --- umodem.c.orig 2008-07-16 12:01:22.000000000 +0700 +++ umodem.c 2008-07-16 12:43:32.000000000 +0700 @@ -172,13 +172,14 @@ struct task sc_task; }; -Static void *umodem_get_desc(usbd_device_handle dev, int type, int subtype); +Static void *umodem_get_desc(usbd_device_handle dev, usb_descriptor_t *, int type, int subtype); +Static usbd_interface_handle umodem_get_interface(struct usb_attach_arg *uaa, int ifcno); 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(struct usb_attach_arg *, int, int *, int *); Static void umodem_get_status(void *, int portno, u_char *lsr, u_char *msr); Static void umodem_set(void *, int, int, int); @@ -261,10 +262,7 @@ if (ret == UMATCH_NONE) return (ret); - 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, -1, &cm, &acm) == -1) return (UMATCH_NONE); return ret; @@ -276,7 +274,6 @@ 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; @@ -304,15 +301,14 @@ id->bInterfaceClass, id->bInterfaceSubClass); sc->sc_ctl_iface_no = id->bInterfaceNumber; - umodem_get_caps(dev, &sc->sc_cm_cap, &sc->sc_acm_cap); - /* Get the data interface no. */ - cmd = umodem_get_desc(dev, UDESC_CS_INTERFACE, UDESCSUB_CDC_CM); - if (cmd == NULL) { - printf("%s: no CM descriptor\n", devname); + sc->sc_data_iface_no = data_ifcno = + umodem_get_caps(uaa, sc->sc_ctl_iface_no, &sc->sc_cm_cap, &sc->sc_acm_cap); + + if (data_ifcno == -1) { + printf("%s: no pointer to data interface\n", devname); goto bad; } - sc->sc_data_iface_no = data_ifcno = cmd->bDataInterface; printf("%s: data interface %d, has %sCM over data, has %sbreak\n", devname, data_ifcno, @@ -550,27 +546,50 @@ ucom_status_change(&sc->sc_ucom); } -void -umodem_get_caps(usbd_device_handle dev, int *cm, int *acm) +Static int +umodem_get_caps(struct usb_attach_arg *uaa, int ctl_iface_no, int *cm, int *acm) { usb_cdc_cm_descriptor_t *cmd; usb_cdc_acm_descriptor_t *cad; + usb_cdc_union_descriptor_t *cud; + usbd_device_handle dev = uaa->device; + usbd_interface_handle iface; + int iface_no = 0; *cm = *acm = 0; - cmd = umodem_get_desc(dev, UDESC_CS_INTERFACE, UDESCSUB_CDC_CM); + cmd = umodem_get_desc(dev, NULL, UDESC_CS_INTERFACE, UDESCSUB_CDC_CM); if (cmd == NULL) { DPRINTF(("umodem_get_desc: no CM desc\n")); - return; + } else { + *cm = cmd->bmCapabilities; } - *cm = cmd->bmCapabilities; - cad = umodem_get_desc(dev, UDESC_CS_INTERFACE, UDESCSUB_CDC_ACM); + cad = umodem_get_desc(dev, NULL, UDESC_CS_INTERFACE, UDESCSUB_CDC_ACM); if (cad == NULL) { DPRINTF(("umodem_get_desc: no ACM desc\n")); - return; + } else { + *acm = cad->bmCapabilities; + } + + cud = NULL; + while ((cud = umodem_get_desc(dev, (usb_descriptor_t *)cud, + UDESC_CS_INTERFACE, UDESCSUB_CDC_UNION))) + { + iface_no = cud->bSlaveInterface[0]; + if (ctl_iface_no == -1) + break; + + iface = umodem_get_interface(uaa,iface_no); + if (ctl_iface_no == cud->bMasterInterface && + usbd_get_interface_descriptor(iface)->bNumEndpoints >= 2) + break; } - *acm = cad->bmCapabilities; + if (cud == NULL) { + DPRINTF(("umodem_get_caps: no UNION desc\n")); + } + + return cmd ? cmd->bDataInterface : cud ? iface_no : -1; } void @@ -586,6 +605,23 @@ *msr = sc->sc_msr; } +Static usbd_interface_handle +umodem_get_interface(struct usb_attach_arg *uaa, int ifcno) +{ + int i; + usb_interface_descriptor_t *id; + + for (i = 0; i < uaa->nifaces; i++) { + if (uaa->ifaces[i] != NULL) { + id = usbd_get_interface_descriptor(uaa->ifaces[i]); + if (id != NULL && id->bInterfaceNumber == ifcno) { + return uaa->ifaces[i]; + } + } + } + return NULL; +} + int umodem_param(void *addr, int portno, struct termios *t) { @@ -776,14 +812,17 @@ return (USBD_NORMAL_COMPLETION); } -void * -umodem_get_desc(usbd_device_handle dev, int type, int subtype) +static void * +umodem_get_desc(usbd_device_handle dev, usb_descriptor_t *restart, 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); + if (restart) + p = (uByte *)(restart) + restart->bLength; + while (p < end) { desc = (usb_descriptor_t *)p; if (desc->bDescriptorType == type && --YiEDa0DAkWCtVeE4--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200807161300.m6GD0A8a042062>