usb/128485: Nokia N80 modem support

Andrey dron_2 at ua.fm
Thu Oct 30 10:30:01 PDT 2008


>Number:         128485
>Category:       usb
>Synopsis:       Nokia N80 modem support
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-usb
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Oct 30 17:30:00 UTC 2008
>Closed-Date:
>Last-Modified:
>Originator:     Andrey
>Release:        FreeBSD 6.3-RELEASE #0
>Organization:
none
>Environment:
FreeBSD dron-hm.dron.dp.ua 6.3-RELEASE FreeBSD 6.3-RELEASE #0: Wed Jan 16 04:45:45 UTC 2008     root at dessler.cse.buffalo.edu:/usr/obj/usr/src/sys/SMP  i386

>Description:
I have an Nokia N80 smartphone, but in FreeBSD there is no modem were defined, only ugen device...
So I can't use this hardwae to connect to internet...

>How-To-Repeat:
install FreeBSD and plug an Nokia N80 :)
>Fix:
after some debug and using google next patch were born:

--- umodem.c.orig       2008-10-22 23:02:46.000000000 +0300
+++ umodem.c.without_debug      2008-10-30 19:04:44.000000000 +0200
@@ -69,6 +69,7 @@
 /*
  * Comm Class spec:  http://www.usb.org/developers/devclass_docs/usbccs10.pdf
  *                   http://www.usb.org/developers/devclass_docs/usbcdc11.pdf
+ *                   http://www.usb.org/developers/devclass_docs/cdc_wmc10.zip
  */

 /*
@@ -127,6 +128,7 @@
        { USB_VENDOR_KYOCERA, USB_PRODUCT_KYOCERA_AHK3001V, 0 },
        { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720, 0 },
        { USB_VENDOR_CURITEL, USB_PRODUCT_CURITEL_PC5740, 0 },
+       { 0x0421, 0x0445, 0 },
        { 0, 0, 0 },
 };

@@ -179,7 +181,8 @@
                                          usb_cdc_line_state_t *state);

 Static void    umodem_get_caps(usbd_device_handle, int *, int *);
-
+Static usb_cdc_union_descriptor_t  *
+    umodem_get_union(usbd_device_handle dev, int iface_no);
 Static void    umodem_get_status(void *, int portno, u_char *lsr, u_char *msr);
 Static void    umodem_set(void *, int, int, int);
 Static void    umodem_dtr(struct umodem_softc *, int);
@@ -269,7 +272,6 @@

        return ret;
 }
-
 USB_ATTACH(umodem)
 {
        USB_ATTACH_START(umodem, sc, uaa);
@@ -277,6 +279,7 @@
        usb_interface_descriptor_t *id;
        usb_endpoint_descriptor_t *ed;
        usb_cdc_cm_descriptor_t *cmd;
+        usb_cdc_union_descriptor_t *cud;
        char *devinfo = NULL;
        const char *devname;
        usbd_status err;
@@ -309,10 +312,13 @@
        /* 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);
+                cud = umodem_get_union(dev, sc->sc_ctl_iface_no);
+                if (cud == NULL) {
+                    printf("%s: no CM and Union descriptors\n", devname);
                goto bad;
-       }
-       sc->sc_data_iface_no = data_ifcno = cmd->bDataInterface;
+                }else data_ifcno = cud->bSlaveInterface[0];
+        }else data_ifcno = cmd->bDataInterface;
+        sc->sc_data_iface_no = data_ifcno;

        printf("%s: data interface %d, has %sCM over data, has %sbreak\n",
               devname, data_ifcno,
@@ -558,19 +564,36 @@

        *cm = *acm = 0;

-       cmd = umodem_get_desc(dev, UDESC_CS_INTERFACE, UDESCSUB_CDC_CM);
-       if (cmd == NULL) {
-               DPRINTF(("umodem_get_desc: no CM desc\n"));
-               return;
-       }
-       *cm = cmd->bmCapabilities;
-
        cad = umodem_get_desc(dev, UDESC_CS_INTERFACE, UDESCSUB_CDC_ACM);
        if (cad == NULL) {
                DPRINTF(("umodem_get_desc: no ACM desc\n"));
                return;
        }
        *acm = cad->bmCapabilities;
+
+        cmd = umodem_get_desc(dev, UDESC_CS_INTERFACE, UDESCSUB_CDC_CM);
+        if (cmd == NULL) {
+                DPRINTF(("umodem_get_desc: no CM desc\n"));
+                *cm = USB_CDC_CM_DOES_CM | USB_CDC_CM_OVER_DATA;
+        }else *cm = cmd->bmCapabilities;
+}
+
+usb_cdc_union_descriptor_t  *
+umodem_get_union(usbd_device_handle dev, int iface_no)
+{
+    usb_cdc_union_descriptor_t *desc;
+    usb_config_descriptor_t *cd = usbd_get_config_descriptor(dev);
+    uByte *p = (uByte *)cd;
+    uByte *end = p + UGETW(cd->wTotalLength);
+    while (p < end) {
+        desc = (usb_cdc_union_descriptor_t *)p;
+        if (desc->bDescriptorType ==  UDESC_CS_INTERFACE &&
+                desc->bDescriptorSubtype == UDESCSUB_CDC_UNION &&
+                desc->bMasterInterface == iface_no)
+            return (desc);
+        p += desc->bLength;
+    }
+    return (0);
 }

 void

With this patch moden is appeared in a system...

Patch attached with submission follows:

--- umodem.c.orig       2008-10-22 23:02:46.000000000 +0300
+++ umodem.c.without_debug      2008-10-30 19:04:44.000000000 +0200
@@ -69,6 +69,7 @@
 /*
  * Comm Class spec:  http://www.usb.org/developers/devclass_docs/usbccs10.pdf
  *                   http://www.usb.org/developers/devclass_docs/usbcdc11.pdf
+ *                   http://www.usb.org/developers/devclass_docs/cdc_wmc10.zip
  */

 /*
@@ -127,6 +128,7 @@
        { USB_VENDOR_KYOCERA, USB_PRODUCT_KYOCERA_AHK3001V, 0 },
        { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720, 0 },
        { USB_VENDOR_CURITEL, USB_PRODUCT_CURITEL_PC5740, 0 },
+       { 0x0421, 0x0445, 0 },
        { 0, 0, 0 },
 };

@@ -179,7 +181,8 @@
                                          usb_cdc_line_state_t *state);

 Static void    umodem_get_caps(usbd_device_handle, int *, int *);
-
+Static usb_cdc_union_descriptor_t  *
+    umodem_get_union(usbd_device_handle dev, int iface_no);
 Static void    umodem_get_status(void *, int portno, u_char *lsr, u_char *msr);
 Static void    umodem_set(void *, int, int, int);
 Static void    umodem_dtr(struct umodem_softc *, int);
@@ -269,7 +272,6 @@

        return ret;
 }
-
 USB_ATTACH(umodem)
 {
        USB_ATTACH_START(umodem, sc, uaa);
@@ -277,6 +279,7 @@
        usb_interface_descriptor_t *id;
        usb_endpoint_descriptor_t *ed;
        usb_cdc_cm_descriptor_t *cmd;
+        usb_cdc_union_descriptor_t *cud;
        char *devinfo = NULL;
        const char *devname;
        usbd_status err;
@@ -309,10 +312,13 @@
        /* 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);
+                cud = umodem_get_union(dev, sc->sc_ctl_iface_no);
+                if (cud == NULL) {
+                    printf("%s: no CM and Union descriptors\n", devname);
                goto bad;
-       }
-       sc->sc_data_iface_no = data_ifcno = cmd->bDataInterface;
+                }else data_ifcno = cud->bSlaveInterface[0];
+        }else data_ifcno = cmd->bDataInterface;
+        sc->sc_data_iface_no = data_ifcno;

        printf("%s: data interface %d, has %sCM over data, has %sbreak\n",
               devname, data_ifcno,
@@ -558,19 +564,36 @@

        *cm = *acm = 0;

-       cmd = umodem_get_desc(dev, UDESC_CS_INTERFACE, UDESCSUB_CDC_CM);
-       if (cmd == NULL) {
-               DPRINTF(("umodem_get_desc: no CM desc\n"));
-               return;
-       }
-       *cm = cmd->bmCapabilities;
-
        cad = umodem_get_desc(dev, UDESC_CS_INTERFACE, UDESCSUB_CDC_ACM);
        if (cad == NULL) {
                DPRINTF(("umodem_get_desc: no ACM desc\n"));
                return;
        }
        *acm = cad->bmCapabilities;
+
+        cmd = umodem_get_desc(dev, UDESC_CS_INTERFACE, UDESCSUB_CDC_CM);
+        if (cmd == NULL) {
+                DPRINTF(("umodem_get_desc: no CM desc\n"));
+                *cm = USB_CDC_CM_DOES_CM | USB_CDC_CM_OVER_DATA;
+        }else *cm = cmd->bmCapabilities;
+}
+
+usb_cdc_union_descriptor_t  *
+umodem_get_union(usbd_device_handle dev, int iface_no)
+{
+    usb_cdc_union_descriptor_t *desc;
+    usb_config_descriptor_t *cd = usbd_get_config_descriptor(dev);
+    uByte *p = (uByte *)cd;
+    uByte *end = p + UGETW(cd->wTotalLength);
+    while (p < end) {
+        desc = (usb_cdc_union_descriptor_t *)p;
+        if (desc->bDescriptorType ==  UDESC_CS_INTERFACE &&
+                desc->bDescriptorSubtype == UDESCSUB_CDC_UNION &&
+                desc->bMasterInterface == iface_no)
+            return (desc);
+        p += desc->bLength;
+    }
+    return (0);
 }

 void


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


More information about the freebsd-usb mailing list