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