Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 25 Nov 2007 08:20:02 GMT
From:      Eugene Grosbein <eugen@grosbein.pp.ru>
To:        freebsd-usb@FreeBSD.org
Subject:   Re: usb/117185: [patch] [umodem] Add support for UNION interface descriptor
Message-ID:  <200711250820.lAP8K24k045179@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: Eugene Grosbein <eugen@grosbein.pp.ru>
To: bug-followup@freebsd.org
Cc: Heikki Suonsivu <heikki@suonsivu.net>
Subject: Re: usb/117185: [patch] [umodem] Add support for UNION interface descriptor
Date: Sun, 25 Nov 2007 15:17:26 +0700

 > The patch does not seem to compile. Removing the offending %s lets it
 > compile. Triggering this may require -O2.
 
 Yes, thank you. It seems I've sent wrong (unfinished) version
 of patch, sorry; right one that I really use follows (see below).
 
 > When starting pppd on boot, there seems to be some hick-ups, not getting
 > phone to respond, etc. After replugging the phone it starts to work,
 > but this is undesirable when trying to build unattended operation.
 > Usb bus does not seem to get proper reset at any time, is there any way
 > to enforce it? This problem seems to happen with Nokia 9300. When the
 > phone is replugged when the system is up and running, it seems to work
 >better.
 
 I'd not compile ucom(4) and umodem(4) drivers into a kernel in such case,
 rather kldload them manually just before starting of pppd.
 This also gives a possibility to "reset usb" by unloading/reloading
 modules. Or, you may try to load these modules with loader(8) - perhaps,
 drivers will behave better. Btw, it seems to me as
 hardware/motherboard/phone problem - you may also try to use
 other USB ports or USB controller.
 
 > I also noticethat if pppd is started without delay on boot, it gets
 > sighup from where, triggering loss of connection to both Nokia phones I
 > have tried. If 30 second delay is added before starting pppd, the
 > system gets up and running, and then ppp seems to work fine without
 > getting extra hups.
 
 The kernel sends SIGHUP at the moment of switching to multi-user mode
 to all processes that did not daemonize properly to this moment.
 I've already seen reports about this problem with pppd for recent versions
 of FreeBSD. For 4.x, there was no such problem. Someone (c) needs to dig
 this problem in more details.
 
 Now the patch for RELENG_7:
 
 --- sys/dev/usb/umodem.c.orig	2007-10-14 20:51:58.000000000 +0800
 +++ sys/dev/usb/umodem.c	2007-10-14 21:03:58.000000000 +0800
 @@ -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);
 @@ -262,10 +263,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;
 @@ -279,7 +277,6 @@
  	usbd_device_handle dev = uaa->device;
  	usb_interface_descriptor_t *id;
  	usb_endpoint_descriptor_t *ed;
 -	usb_cdc_cm_descriptor_t *cmd;
  	int data_ifcno;
  	int i;
  	struct ucom_softc *ucom;
 @@ -297,15 +294,14 @@
  	device_printf(self, "iclass %d/%d\n", id->bInterfaceClass,
  	  id->bInterfaceSubClass);
  
 -	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) {
 -		device_printf(sc->sc_dev, "no CM descriptor\n");
 + 	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) {
 +		device_printf(sc->sc_dev,"no pointer to data interface\n");
  		goto bad;
  	}
 -	sc->sc_data_iface_no = data_ifcno = cmd->bDataInterface;
  
  	device_printf(sc->sc_dev,
  	    "data interface %d, has %sCM over data, has %sbreak\n",
 @@ -530,27 +526,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;
 +	}
 +	if (cud == NULL) {
 +		DPRINTF(("umodem_get_caps: no UNION desc\n"));
  	}
 -	*acm = cad->bmCapabilities;
 +	
 +	return cmd ? cmd->bDataInterface : cud ? iface_no : -1;
  }
  
  void
 @@ -566,6 +585,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)
  {
 @@ -756,14 +792,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 &&
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200711250820.lAP8K24k045179>