Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 12 Jan 2011 13:09:53 GMT
From:      Mykhaylo Yehorov <yehorov@gmail.com>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   usb/153929: The umodem driver doesn't support the MTK 3329 GPS chipset.
Message-ID:  <201101121309.p0CD9rRD070704@red.freebsd.org>
Resent-Message-ID: <201101121310.p0CDA9F8092635@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         153929
>Category:       usb
>Synopsis:       The umodem driver doesn't support the MTK 3329 GPS chipset.
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-usb
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Wed Jan 12 13:10:09 UTC 2011
>Closed-Date:
>Last-Modified:
>Originator:     Mykhaylo Yehorov
>Release:        FreeBSD 8-STABLE
>Organization:
>Environment:
FreeBSD box.interexc.com 8.2-PRERELEASE FreeBSD 8.2-PRERELEASE #1 r197782M: Tue Jan  4 14:49:50 EET 2011     mika@box.interexc.com:/usr/obj/usr/src/sys/MINI  i386
>Description:
I'm trying to connect my GPS receiver based on the MTK 3329 GPS chipset to a FreeBSD box.
The umodem driver matches to the device but fails to attach to it.

My kernel is built with "options USB_DEBUG".
Sysctl variable syshw.usb.umodem.debug is set to 11.
After attaching the GPS receiver to an USB port the following lines appear in dmesg.

ugen1.3: <MTK> at usbus1
umodem_probe: 
umodem_probe: 
umodem_probe: 
umodem0: <GPS COM(comm_if)> on usbus1
umodem_get_caps: no CM desc (faking one)
umodem_get_caps: no ACM desc
umodem0: Missing descriptor. Assuming data interface is next.
umodem0: data interface 2, has CM over data, has no break
umodem0: no data interface
umodem_detach: sc=0xc907aa00
device_attach: umodem0 attach returned 6
umodem_probe: 
umodem0: <GPS COM(comm_if)> on usbus1
umodem_get_caps: no CM desc (faking one)
umodem_get_caps: no ACM desc
umodem0: Missing descriptor. Assuming data interface is next.
umodem0: data interface 2, has CM over data, has no break
umodem0: no data interface
umodem_detach: sc=0xc9ddf800
device_attach: umodem0 attach returned 6

usbconfig shows the following.

ugen1.3: <GPS Receiver MTK> at usbus1, cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON

  bLength = 0x0012 
  bDescriptorType = 0x0001 
  bcdUSB = 0x0200 
  bDeviceClass = 0x0002 
  bDeviceSubClass = 0x0000 
  bDeviceProtocol = 0x0000 
  bMaxPacketSize0 = 0x0040 
  idVendor = 0x0e8d 
  idProduct = 0x3329 
  bcdDevice = 0x0100 
  iManufacturer = 0x0003  <MTK>
  iProduct = 0x0004  <GPS Receiver>
  iSerialNumber = 0x0000  <no string>
  bNumConfigurations = 0x0001 


 Configuration index 0

    bLength = 0x0009 
    bDescriptorType = 0x0002 
    wTotalLength = 0x0043 
    bNumInterfaces = 0x0002 
    bConfigurationValue = 0x0001 
    iConfiguration = 0x0000  <no string>
    bmAttributes = 0x0080 
    bMaxPower = 0x00fa 

    Interface 0
      bLength = 0x0009 
      bDescriptorType = 0x0004 
      bInterfaceNumber = 0x0000 
      bAlternateSetting = 0x0000 
      bNumEndpoints = 0x0002 
      bInterfaceClass = 0x000a 
      bInterfaceSubClass = 0x0000 
      bInterfaceProtocol = 0x0000 
      iInterface = 0x0001  <GPS COM(data_if)>

     Endpoint 0
        bLength = 0x0007 
        bDescriptorType = 0x0005 
        bEndpointAddress = 0x0081  <IN>
        bmAttributes = 0x0002  <BULK>
        wMaxPacketSize = 0x0040 
        bInterval = 0x0000 
        bRefresh = 0x0000 
        bSynchAddress = 0x0000 

     Endpoint 1
        bLength = 0x0007 
        bDescriptorType = 0x0005 
        bEndpointAddress = 0x0001  <OUT>
        bmAttributes = 0x0002  <BULK>
        wMaxPacketSize = 0x0040 
        bInterval = 0x0000 
        bRefresh = 0x0000 
        bSynchAddress = 0x0000 


    Interface 1
      bLength = 0x001c 
      bDescriptorType = 0x0004 
      bInterfaceNumber = 0x0001 
      bAlternateSetting = 0x0000 
      bNumEndpoints = 0x0001 
      bInterfaceClass = 0x0002 
      bInterfaceSubClass = 0x0002 
      bInterfaceProtocol = 0x0001 
      iInterface = 0x0002  <GPS COM(comm_if)>

     Endpoint 0
        bLength = 0x0007 
        bDescriptorType = 0x0005 
        bEndpointAddress = 0x0082  <IN>
        bmAttributes = 0x0003  <INTERRUPT>
        wMaxPacketSize = 0x0040 
        bInterval = 0x0001 
        bRefresh = 0x0000 
        bSynchAddress = 0x0000 

>How-To-Repeat:
Attach a GPS receiver based on the MTK 3329 chipset to an USB port.
>Fix:
If driver cannot obtain descriptors about data interface it assumes data interface is next that is wrong for this device.
Data interface can be find by bInterfaceClass and bInterfaceSubClass codes.

My patch fixes driver behaviour.
After applying the umodem driver can attach to the device.
And GPS software works fine with the GPS receiver.

ugen1.3: <MTK> at usbus1
umodem_probe: 
umodem_probe: 
umodem_probe: 
umodem0: <GPS COM(comm_if)> on usbus1
umodem_get_caps: no CM desc (faking one)
umodem_get_caps: no ACM desc
umodem0: data interface 0, has CM over data, has no break


Patch attached with submission follows:

--- orig/sys/dev/usb/serial/umodem.c	2010-04-30 01:44:04.000000000 +0300
+++ sys/dev/usb/serial/umodem.c	2011-01-12 14:32:14.000000000 +0200
@@ -198,6 +198,7 @@
 static usb_error_t umodem_set_comm_feature(struct usb_device *, uint8_t,
 		    uint16_t, uint16_t);
 static void	umodem_poll(struct ucom_softc *ucom);
+static int	umodem_find_data_interface(struct usb_attach_arg *, uint8_t *);
 
 static const struct usb_config umodem_config[UMODEM_N_TRANSFER] = {
 
@@ -312,13 +313,15 @@
 		    0 - 1, UDESCSUB_CDC_UNION, 0 - 1);
 
 		if ((cud == NULL) || (cud->bLength < sizeof(*cud))) {
-			device_printf(dev, "Missing descriptor. "
-			    "Assuming data interface is next.\n");
 			if (sc->sc_ctrl_iface_no == 0xFF)
 				goto detach;
-			else
+			else if (!umodem_find_data_interface(uaa,
+			    &sc->sc_data_iface_no)) {
+				device_printf(dev, "Missing descriptor. "
+				    "Assuming data interface is next.\n");
 				sc->sc_data_iface_no = 
 				    sc->sc_ctrl_iface_no + 1;
+			}
 		} else {
 			sc->sc_data_iface_no = cud->bSlaveInterface[0];
 		}
@@ -829,3 +832,31 @@
 	struct umodem_softc *sc = ucom->sc_parent;
 	usbd_transfer_poll(sc->sc_xfer, UMODEM_N_TRANSFER);
 }
+
+static int
+umodem_find_data_interface(struct usb_attach_arg *uaa, uint8_t *data_iface)
+{
+	uint8_t i;
+
+	for (i = 0;; i++) {
+		struct usb_interface *iface;
+		struct usb_interface_descriptor *id;
+
+		iface = usbd_get_iface(uaa->device, i);
+
+		if (iface) {
+
+			id = usbd_get_interface_descriptor(iface);
+
+			if (id->bInterfaceClass == UICLASS_CDC_DATA &&
+			    id->bInterfaceSubClass == UISUBCLASS_DATA) {
+				*data_iface = i;
+				return (1);
+			}
+		}
+		else
+			break;
+	}
+
+	return (0);
+}


>Release-Note:
>Audit-Trail:
>Unformatted:



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