usb/117185: [umodem] [patch] Add support for UNION interface descriptor

Alexey Dokuchaev danfe at nsu.ru
Wed Jul 16 13:00:12 UTC 2008


The following reply was made to PR usb/117185; it has been noted by GNATS.

From: Alexey Dokuchaev <danfe at nsu.ru>
To: bug-followup at FreeBSD.org, eugen at grosbein.pp.ru
Cc: imp at 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--


More information about the freebsd-usb mailing list