Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/usb Match all pairs of bulkin-bulkout interfaces to ...



details:   https://anonhg.NetBSD.org/src/rev/d7123cbe2616
branches:  trunk
changeset: 782380:d7123cbe2616
user:      christos <christos%NetBSD.org@localhost>
date:      Thu Nov 01 00:38:43 2012 +0000

description:
Match all pairs of bulkin-bulkout interfaces to ucom's, configuring multiple
ucoms per modem as they are available, instead of picking up the last bulkin
bulkout pair. This makes my Sierra U250 3G portion of the modem to work.

diffstat:

 sys/dev/usb/u3g.c |  141 ++++++++++++++++++++++++++++++-----------------------
 1 files changed, 80 insertions(+), 61 deletions(-)

diffs (truncated from 346 to 300 lines):

diff -r 205a49e85977 -r d7123cbe2616 sys/dev/usb/u3g.c
--- a/sys/dev/usb/u3g.c Wed Oct 31 21:30:27 2012 +0000
+++ b/sys/dev/usb/u3g.c Thu Nov 01 00:38:43 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: u3g.c,v 1.26 2012/10/05 22:04:56 khorben Exp $ */
+/*     $NetBSD: u3g.c,v 1.27 2012/11/01 00:38:43 christos Exp $        */
 
 /*-
  * Copyright (c) 2009 The NetBSD Foundation, Inc.
@@ -50,7 +50,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: u3g.c,v 1.26 2012/10/05 22:04:56 khorben Exp $");
+__KERNEL_RCSID(0, "$NetBSD: u3g.c,v 1.27 2012/11/01 00:38:43 christos Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -113,16 +113,19 @@
        device_t                sc_dev;
        usbd_device_handle      sc_udev;
        bool                    sc_dying;       /* We're going away */
-
-       device_t                sc_ucom;        /* Child ucom(4) handle */
        int                     sc_ifaceno;     /* Device interface number */
 
-       bool                    sc_open;        /* Device is in use */
-       bool                    sc_purging;     /* Purging stale data */
-       struct timeval          sc_purge_start; /* Control duration of purge */
+       struct u3g_com {
+               device_t        c_dev;          /* Child ucom(4) handle */
 
-       u_char                  sc_msr;         /* Emulated 'msr' */
-       uint16_t                sc_outpins;     /* Output pin state */
+               bool            c_open;         /* Device is in use */
+               bool            c_purging;      /* Purging stale data */
+               struct timeval  c_purge_start;  /* Control duration of purge */
+
+               u_char          c_msr;          /* Emulated 'msr' */
+               uint16_t        c_outpins;      /* Output pin state */
+       } sc_com[10];
+       size_t                  sc_ncom;
 
        usbd_pipe_handle        sc_intr_pipe;   /* Interrupt pipe */
        u_char                  *sc_intr_buff;  /* Interrupt buffer */
@@ -246,7 +249,7 @@
        { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8781 },
        { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MINI5725 },
        { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_USB305 },
-
+       { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_250U },
        /* Toshiba */
        { USB_VENDOR_TOSHIBA, USB_PRODUCT_TOSHIBA_HSDPA_MODEM_EU870DT1 },
 
@@ -629,20 +632,16 @@
        uca.ibufsize = U3G_BUFF_SIZE;
        uca.obufsize = U3G_BUFF_SIZE;
        uca.ibufsizepad = U3G_BUFF_SIZE;
-       uca.portno = uaa->ifaceno;
        uca.opkthdrlen = 0;
        uca.device = dev;
        uca.iface = iface;
        uca.methods = &u3g_methods;
        uca.arg = sc;
+       uca.portno = -1;
        uca.bulkin = uca.bulkout = -1;
 
-       sc->sc_outpins = 0;
-       sc->sc_msr = UMSR_DSR | UMSR_CTS | UMSR_DCD;
+
        sc->sc_ifaceno = uaa->ifaceno;
-       sc->sc_open = false;
-       sc->sc_purging = false;
-
        intr_address = -1;
        intr_size = 0;
 
@@ -668,25 +667,33 @@
                    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
                        uca.bulkout = ed->bEndpointAddress;
                }
+               if (uca.bulkin != -1 && uca.bulkout != -1) {
+                       struct u3g_com *com;
+                       if (sc->sc_ncom == __arraycount(sc->sc_com)) {
+                               aprint_error_dev(self, "Need to configure "
+                                   "more than %zu ttys", sc->sc_ncom);
+                               continue;
+                       }
+                       uca.portno = sc->sc_ncom++;
+                       com = &sc->sc_com[uca.portno];
+                       com->c_outpins = 0;
+                       com->c_msr = UMSR_DSR | UMSR_CTS | UMSR_DCD;
+                       com->c_open = false;
+                       com->c_purging = false;
+                       com->c_dev = config_found_sm_loc(self, "ucombus",
+                               NULL, &uca, ucomprint, ucomsubmatch);
+                       uca.bulkin = -1;
+                       uca.bulkout = -1;
+               }
        }
 
-       if (uca.bulkin == -1) {
-               aprint_error_dev(self, "Missing bulk in for interface %d\n",
+       if (sc->sc_ncom == 0) {
+               aprint_error_dev(self, "Missing bulk in/out for interface %d\n",
                    sc->sc_ifaceno);
                sc->sc_dying = true;
                return;
        }
 
-       if (uca.bulkout == -1) {
-               aprint_error_dev(self, "Missing bulk out for interface %d\n",
-                   sc->sc_ifaceno);
-               sc->sc_dying = true;
-               return;
-       }
-
-       sc->sc_ucom = config_found_sm_loc(self, "ucombus",
-           NULL, &uca, ucomprint, ucomsubmatch);
-
        /*
         * If the interface has an interrupt pipe, open it immediately so
         * that we can track input pin state changes regardless of whether
@@ -722,13 +729,14 @@
 
        pmf_device_deregister(self);
 
-       if (sc->sc_ucom != NULL) {
-               rv = config_detach(sc->sc_ucom, flags);
-               if (rv != 0) {
-                       aprint_verbose_dev(self, "Can't deallocate "
-                           "port (%d)", rv);
+       for (size_t i = 0; i < sc->sc_ncom; i++)
+               if (sc->sc_com[i].c_dev != NULL) {
+                       rv = config_detach(sc->sc_com[i].c_dev, flags);
+                       if (rv != 0) {
+                               aprint_verbose_dev(self, "Can't deallocate "
+                                   "port (%d)", rv);
+                       }
                }
-       }
 
        if (sc->sc_intr_pipe != NULL) {
                (void) usbd_abort_pipe(sc->sc_intr_pipe);
@@ -748,30 +756,32 @@
 {
        struct u3g_softc *sc = device_private(self);
 
-       if (sc->sc_ucom == child)
-               sc->sc_ucom = NULL;
+       for (size_t i = 0; i < sc->sc_ncom; i++)
+                   if (sc->sc_com[i].c_dev == child)
+                           sc->sc_com[i].c_dev = NULL;
 }
 
 static int
 u3g_activate(device_t self, enum devact act)
 {
        struct u3g_softc *sc = device_private(self);
-       int rv;
+       int rv = 0;
 
        switch (act) {
        case DVACT_DEACTIVATE:
-               if (sc->sc_ucom != NULL && config_deactivate(sc->sc_ucom))
+               for (size_t i = 0; i < sc->sc_ncom; i++)
+                       if (sc->sc_com[i].c_dev != NULL &&
+                           config_deactivate(sc->sc_com[i].c_dev) && rv == 0)
                        rv = -1;
                else
                        rv = 0;
                break;
 
        default:
-               rv = 0;
                break;
        }
 
-       return (rv);
+       return rv;
 }
 
 static void
@@ -779,6 +789,8 @@
 {
        struct u3g_softc *sc = (struct u3g_softc *)priv;
        u_char *buf;
+       int portno = 0; /* XXX */
+       struct u3g_com *com = &sc->sc_com[portno];
 
        if (sc->sc_dying)
                return;
@@ -794,7 +806,7 @@
        if (buf[0] == 0xa1 && buf[1] == 0x20) {
                u_char msr;
 
-               msr = sc->sc_msr & ~(UMSR_DCD | UMSR_DSR | UMSR_RI);
+               msr = com->c_msr & ~(UMSR_DCD | UMSR_DSR | UMSR_RI);
 
                if (buf[8] & U3G_INPIN_DCD)
                        msr |= UMSR_DCD;
@@ -805,10 +817,10 @@
                if (buf[8] & U3G_INPIN_RI)
                        msr |= UMSR_RI;
 
-               if (msr != sc->sc_msr) {
-                       sc->sc_msr = msr;
-                       if (sc->sc_open)
-                               ucom_status_change(device_private(sc->sc_ucom));
+               if (msr != com->c_msr) {
+                       com->c_msr = msr;
+                       if (com->c_open)
+                               ucom_status_change(device_private(com->c_dev));
                }
        }
 }
@@ -822,7 +834,7 @@
        if (lsr != NULL)
                *lsr = 0;       /* LSR isn't supported */
        if (msr != NULL)
-               *msr = sc->sc_msr;
+               *msr = sc->sc_com[portno].c_msr;
 }
 
 /*ARGSUSED*/
@@ -833,6 +845,7 @@
        usb_device_request_t req;
        uint16_t mask, new_state;
        usbd_status err;
+       struct u3g_com *com = &sc->sc_com[portno];
 
        if (sc->sc_dying)
                return;
@@ -848,14 +861,14 @@
                return;
        }
 
-       new_state = sc->sc_outpins & ~mask;
+       new_state = com->c_outpins & ~mask;
        if (onoff)
                new_state |= mask;
 
-       if (new_state == sc->sc_outpins)
+       if (new_state == com->c_outpins)
                return;
 
-       sc->sc_outpins = new_state;
+       com->c_outpins = new_state;
 
        req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
        req.bRequest = U3G_SET_PIN;
@@ -878,23 +891,26 @@
        usb_interface_descriptor_t *id;
        usbd_interface_handle ih;
        usbd_status err;
-       int i;
+       struct u3g_com *com = &sc->sc_com[portno];
+       int i, nin;
 
        if (sc->sc_dying)
                return (0);
 
-       err = usbd_device2interface_handle(sc->sc_udev, portno, &ih);
+       err = usbd_device2interface_handle(sc->sc_udev, sc->sc_ifaceno, &ih);
        if (err)
                return (EIO);
 
        id = usbd_get_interface_descriptor(ih);
 
-       for (i = 0; i < id->bNumEndpoints; i++) {
+       for (nin = i = 0; i < id->bNumEndpoints; i++) {
                ed = usbd_interface2endpoint_descriptor(ih, i);
                if (ed == NULL) 
                        return (EIO);
 
-               if (UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
+               if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
+                   UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK &&
+                   nin++ == portno) {
                        /* Issue ENDPOINT_HALT request */
                        req.bmRequestType = UT_WRITE_ENDPOINT;
                        req.bRequest = UR_CLEAR_FEATURE;
@@ -907,9 +923,9 @@
                }
        }
 
-       sc->sc_open = true;
-       sc->sc_purging = true;
-       getmicrotime(&sc->sc_purge_start);
+       com->c_open = true;
+       com->c_purging = true;
+       getmicrotime(&com->c_purge_start);
 
        return (0);
 }
@@ -919,8 +935,9 @@
 u3g_close(void *arg, int portno)
 {
        struct u3g_softc *sc = arg;
+       struct u3g_com *com = &sc->sc_com[portno];



Home | Main Index | Thread Index | Old Index