svn commit: r183925 - head/sys/dev/usb
Nick Hibma
nick at van-laarhoven.org
Wed Oct 15 21:36:13 UTC 2008
I'm curious to hear back from people testing this driver.
Transfer speeds up to 260kB/s have been achieved with a Huawei E220 dongle
having a reasonable signal.
Please supply the usual: Output of usbctl -f /dev/usbX (or usbdevs -v),
dmesg, and if possible speed comparisons between FBSD and windows at the
same location and roughly in the same time frame.
Nick
> Author: n_hibma
> Date: Wed Oct 15 21:25:11 2008
> New Revision: 183925
> URL: http://svn.freebsd.org/changeset/base/183925
>
> Log:
> Rewrite the driver to better support the Huawei devices. It should now
> support the Sierra and Novatel devices, ignore all umass devices and hide
> the umass devices that represent the CD ROM devices (but not the SD card
> slot in the Huawei Mobile dongle).
>
> Note: This driver in FBSD7 seems to suffer from memory corruption when
> used with an Option GT Quad. The E220 however works flawlessly.
>
> Also add the ID for the Option GTMaxHSUPA, provided by Olivier Fromme.
>
> Modified:
> head/sys/dev/usb/u3g.c
> head/sys/dev/usb/ubsa.c
> head/sys/dev/usb/usbdevs
>
> Modified: head/sys/dev/usb/u3g.c
> =========================================================================
>===== --- head/sys/dev/usb/u3g.c Wed Oct 15 20:44:00 2008 (r183924)
> +++ head/sys/dev/usb/u3g.c Wed Oct 15 21:25:11 2008 (r183925)
> @@ -19,6 +19,14 @@
> * $FreeBSD$
> */
>
> +/*
> + * Notes:
> + * - The detour through the tty layer is ridiculously expensive wrt
> buffering + * due to the high speeds.
> + * We should consider adding a simple r/w device which allows
> attaching of PPP + * in a more efficient way.
> + */
> +
> #include <sys/param.h>
> #include <sys/systm.h>
> #include <sys/kernel.h>
> @@ -40,43 +48,39 @@
>
> #include "usbdevs.h"
>
> +#define U3G_DEBUG 1
> #ifdef U3G_DEBUG
> -#define DPRINTFN(n, x) do { if (u3gdebug > (n)) printf x; } while (0)
> -int u3gtebug = 0;
> +#define DPRINTF(x...) do { if (u3gdebug) device_printf(self, ##x); }
> while (0) +#define DPRINTFN(n, x...) do { if (u3gdebug > (n))
> device_printf(self, ##x); } while (0) +int u3gdebug = 1;
> #else
> -#define DPRINTFN(n, x)
> +#define DPRINTF(x...) /* nop */
> +#define DPRINTFN(n, x...) /* nop */
> #endif
> -#define DPRINTF(x) DPRINTFN(0, x)
>
> -#define U3G_BUFSIZ 1024
> +#define U3G_BUFSIZ 10240
> #define U3G_MAXPORTS 4
> #define U3G_CONFIG_INDEX 0
>
> struct u3g_softc {
> - struct ucom_softc sc_ucom[U3G_MAXPORTS];;
> + struct ucom_softc sc_ucom[U3G_MAXPORTS];
> device_t sc_dev;
> usbd_device_handle sc_udev;
> - u_int16_t sc_flags;
> - u_char sc_msr;
> - u_char sc_lsr;
> - u_char numports;
> -
> - usbd_interface_handle sc_intr_iface; /* interrupt interface */
> -#ifdef U3G_DEBUG
> - int sc_intr_number; /* interrupt number */
> - usbd_pipe_handle sc_intr_pipe; /* interrupt pipe */
> - u_char *sc_intr_buf; /* interrupt buffer */
> -#endif
> - int sc_isize;
> + u_int8_t sc_speed;
> + u_int8_t sc_flags;
> + u_char sc_numports;
> };
>
> +static int u3g_open(void *addr, int portno);
> +static void u3g_close(void *addr, int portno);
> +
> struct ucom_callback u3g_callback = {
> NULL,
> NULL,
> NULL,
> NULL,
> - NULL,
> - NULL,
> + u3g_open,
> + u3g_close,
> NULL,
> NULL,
> };
> @@ -86,81 +90,106 @@ struct ucom_callback u3g_callback = {
> * Various supported device vendors/products.
> */
> struct u3g_dev_type_s {
> - struct usb_devno u3g_dev;
> - u_int16_t u3g_flags;
> -#define U3GFL_NONE 0x0000
> -#define U3GFL_HUAWEI_INIT 0x0001 /* Send USB command to reset iface to
> ucom mode */ + struct usb_devno devno;
> + u_int8_t speed;
> +#define U3GSP_GPRS 1
> +#define U3GSP_EDGE 2
> +#define U3GSP_UMTS 3
> +#define U3GSP_HSDPA 4
> +#define U3GSP_HSUPA 5
> +#define U3GSP_HSPA 6
> +
> + u_int8_t flags;
> +#define U3GFL_NONE 0x00
> +#define U3GFL_HUAWEI_INIT 0x01 // Requires init (Huawei cards)
> +#define U3GFL_STUB_WAIT 0x02 // Device reappears after a short delay
> };
>
> static const struct u3g_dev_type_s u3g_devs[] = {
> /* OEM: Option */
> - {{ USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3G }, U3GFL_NONE },
> - {{ USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3GQUAD }, U3GFL_NONE },
> - {{ USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3GPLUS }, U3GFL_NONE },
> - {{ USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GTMAX36 }, U3GFL_NONE },
> - {{ USB_VENDOR_OPTION, USB_PRODUCT_OPTION_VODAFONEMC3G }, U3GFL_NONE },
> + {{ USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3G
> }, U3GSP_UMTS, U3GFL_NONE }, + {{ USB_VENDOR_OPTION,
> USB_PRODUCT_OPTION_GT3GQUAD }, U3GSP_UMTS, U3GFL_NONE }, + {{
> USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3GPLUS }, U3GSP_UMTS, U3GFL_NONE
> }, + {{ USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GTMAX36
> }, U3GSP_HSDPA, U3GFL_NONE }, + {{ USB_VENDOR_OPTION,
> USB_PRODUCT_OPTION_GTMAXHSUPA }, U3GSP_HSDPA, U3GFL_NONE }, + {{
> USB_VENDOR_OPTION, USB_PRODUCT_OPTION_VODAFONEMC3G
> }, U3GSP_UMTS, U3GFL_NONE }, /* OEM: Qualcomm, Inc. */
> - {{ USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_CDMA_MSM
> }, U3GFL_NONE }, + {{ USB_VENDOR_QUALCOMMINC,
> USB_PRODUCT_QUALCOMMINC_CDMA_MSM }, U3GSP_UMTS, U3GFL_STUB_WAIT }, // XXX
> /* OEM: Huawei */
> - /* Handled separately. Do not add!
> - {{ USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_MOBILE }, U3GFL_NONE },
> - {{ USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E220 }, U3GFL_NONE },
> - */
> + {{ USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_MOBILE
> }, U3GSP_HSDPA, U3GFL_HUAWEI_INIT }, + {{ USB_VENDOR_HUAWEI,
> USB_PRODUCT_HUAWEI_E220 }, U3GSP_HSDPA, U3GFL_HUAWEI_INIT }, /* OEM:
> Novatel */
> - {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_CDMA_MODEM }, U3GFL_NONE },
> - {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_ES620 }, U3GFL_NONE },
> - {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_MC950D }, U3GFL_NONE },
> - {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U720 }, U3GFL_NONE },
> - {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U727 }, U3GFL_NONE },
> - {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U740 }, U3GFL_NONE },
> - {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U740_2 }, U3GFL_NONE },
> - {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U870 }, U3GFL_NONE },
> - {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_V620 }, U3GFL_NONE },
> - {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_V640 }, U3GFL_NONE },
> - {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_V720 }, U3GFL_NONE },
> - {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_V740 }, U3GFL_NONE },
> - {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_X950D }, U3GFL_NONE },
> - {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_XU870 }, U3GFL_NONE },
> - {{ USB_VENDOR_DELL, USB_PRODUCT_DELL_U740 }, U3GFL_NONE },
> + {{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_CDMA_MODEM
> }, U3GSP_UMTS, U3GFL_STUB_WAIT }, // XXX + {{ USB_VENDOR_NOVATEL,
> USB_PRODUCT_NOVATEL_ES620 }, U3GSP_UMTS, U3GFL_STUB_WAIT }, // XXX + {{
> USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_MC950D
> }, U3GSP_HSUPA, U3GFL_STUB_WAIT }, + {{ USB_VENDOR_NOVATEL,
> USB_PRODUCT_NOVATEL_U720 }, U3GSP_UMTS, U3GFL_STUB_WAIT }, // XXX + {{
> USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U727
> }, U3GSP_UMTS, U3GFL_STUB_WAIT }, // XXX + {{ USB_VENDOR_NOVATEL,
> USB_PRODUCT_NOVATEL_U740 }, U3GSP_HSDPA, U3GFL_STUB_WAIT }, + {{
> USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U740_2
> }, U3GSP_HSDPA, U3GFL_STUB_WAIT }, + {{ USB_VENDOR_NOVATEL,
> USB_PRODUCT_NOVATEL_U870 }, U3GSP_UMTS, U3GFL_STUB_WAIT }, // XXX + {{
> USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_V620
> }, U3GSP_UMTS, U3GFL_STUB_WAIT }, // XXX + {{ USB_VENDOR_NOVATEL,
> USB_PRODUCT_NOVATEL_V640 }, U3GSP_UMTS, U3GFL_STUB_WAIT }, // XXX + {{
> USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_V720
> }, U3GSP_UMTS, U3GFL_STUB_WAIT }, // XXX + {{ USB_VENDOR_NOVATEL,
> USB_PRODUCT_NOVATEL_V740 }, U3GSP_HSDPA, U3GFL_STUB_WAIT }, + {{
> USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_X950D
> }, U3GSP_HSUPA, U3GFL_STUB_WAIT }, + {{ USB_VENDOR_NOVATEL,
> USB_PRODUCT_NOVATEL_XU870 }, U3GSP_HSDPA, U3GFL_STUB_WAIT }, + {{
> USB_VENDOR_DELL, USB_PRODUCT_DELL_U740
> }, U3GSP_HSDPA, U3GFL_STUB_WAIT }, + /* OEM: Merlin */
> + {{ USB_VENDOR_MERLIN, USB_PRODUCT_MERLIN_V620
> }, U3GSP_UMTS, U3GFL_NONE }, // XXX + /* OEM: Sierra Wireless: */
> + {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD580
> }, U3GSP_UMTS, U3GFL_NONE }, // XXX + {{ USB_VENDOR_SIERRA,
> USB_PRODUCT_SIERRA_AIRCARD595 }, U3GSP_UMTS, U3GFL_NONE }, // XXX + {{
> USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC595U }, U3GSP_UMTS, U3GFL_NONE
> }, // XXX + {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC597E
> }, U3GSP_UMTS, U3GFL_NONE }, // XXX + {{ USB_VENDOR_SIERRA,
> USB_PRODUCT_SIERRA_C597 }, U3GSP_UMTS, U3GFL_NONE }, // XXX + {{
> USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880 }, U3GSP_UMTS, U3GFL_NONE
> }, // XXX + {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880E
> }, U3GSP_UMTS, U3GFL_NONE }, // XXX + {{ USB_VENDOR_SIERRA,
> USB_PRODUCT_SIERRA_AC880U }, U3GSP_UMTS, U3GFL_NONE }, // XXX + {{
> USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881 }, U3GSP_UMTS, U3GFL_NONE
> }, // XXX + {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881E
> }, U3GSP_UMTS, U3GFL_NONE }, // XXX + {{ USB_VENDOR_SIERRA,
> USB_PRODUCT_SIERRA_AC881U }, U3GSP_UMTS, U3GFL_NONE }, // XXX + {{
> USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_EM5625 }, U3GSP_UMTS, U3GFL_NONE
> }, // XXX + {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720
> }, U3GSP_UMTS, U3GFL_NONE }, // XXX + {{ USB_VENDOR_SIERRA,
> USB_PRODUCT_SIERRA_MC5720_2 }, U3GSP_UMTS, U3GFL_NONE }, // XXX + {{
> USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5725 }, U3GSP_UMTS, U3GFL_NONE
> }, // XXX + {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MINI5725
> }, U3GSP_UMTS, U3GFL_NONE }, // XXX + {{ USB_VENDOR_SIERRA,
> USB_PRODUCT_SIERRA_AIRCARD875 }, U3GSP_UMTS, U3GFL_NONE }, // XXX + {{
> USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755 }, U3GSP_UMTS, U3GFL_NONE
> }, // XXX + {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_2
> }, U3GSP_UMTS, U3GFL_NONE }, // XXX + {{ USB_VENDOR_SIERRA,
> USB_PRODUCT_SIERRA_MC8755_3 }, U3GSP_UMTS, U3GFL_NONE }, // XXX + {{
> USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8765 }, U3GSP_UMTS, U3GFL_NONE
> }, // XXX + {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC875U
> }, U3GSP_UMTS, U3GFL_NONE }, // XXX + {{ USB_VENDOR_SIERRA,
> USB_PRODUCT_SIERRA_MC8775_2 }, U3GSP_UMTS, U3GFL_NONE }, // XXX + {{
> USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8780 }, U3GSP_UMTS, U3GFL_NONE
> }, // XXX + {{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8781
> }, U3GSP_UMTS, U3GFL_NONE }, // XXX };
> #define u3g_lookup(v, p) ((const struct u3g_dev_type_s
> *)usb_lookup(u3g_devs, v, p))
>
> -#ifdef U3G_DEBUG
> -static void
> -u3g_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status
> status) -{
> - struct u3g_softc *sc = (struct u3g_softc *)priv;
> - device_printf(sc->sc_dev, "Interrupt callback\n");
> -}
> -#endif
> -
> static int
> u3g_match(device_t self)
> {
> struct usb_attach_arg *uaa = device_get_ivars(self);
> - usb_interface_descriptor_t *id;
> const struct u3g_dev_type_s *u3g_dev_type;
>
> - if (uaa->vendor == USB_VENDOR_HUAWEI) {
> - if (uaa->iface) {
> - /* We attach to the interface instead of the device as
> - * some devices have a built-in SD card reader on the
> - * second interface. If the interface class of the
> - * first interface is no longer mass storage it has
> - * changed appearance and we should attach it.
> - */
> - id = usbd_get_interface_descriptor(uaa->iface);
> - if (id && id->bInterfaceClass == UICLASS_VENDOR)
> - return (UMATCH_VENDOR_PRODUCT_CONF_IFACE);
> - }
> + if (!uaa->iface)
> return UMATCH_NONE;
> - }
>
> u3g_dev_type = u3g_lookup(uaa->vendor, uaa->product);
> - if (u3g_dev_type)
> - return UMATCH_VENDOR_PRODUCT;
> + if (!u3g_dev_type)
> + return UMATCH_NONE;
>
> - return UMATCH_NONE;
> + if (u3g_dev_type->flags&U3GFL_HUAWEI_INIT) {
> + /* If the interface class of the first interface is no longer
> + * mass storage the card has changed to modem (see u3g_attach()
> + * below).
> + */
> + usb_interface_descriptor_t *id;
> + id = usbd_get_interface_descriptor(uaa->iface);
> + if (!id || id->bInterfaceClass == UICLASS_MASS)
> + return UMATCH_NONE;
> + }
> +
> + return UMATCH_VENDOR_PRODUCT_CONF_IFACE;
> }
>
> static int
> @@ -168,120 +197,105 @@ u3g_attach(device_t self)
> {
> struct u3g_softc *sc = device_get_softc(self);
> struct usb_attach_arg *uaa = device_get_ivars(self);
> + const struct u3g_dev_type_s *u3g_dev_type;
> usbd_device_handle dev = uaa->device;
> - usbd_interface_handle iface;
> usb_interface_descriptor_t *id;
> usb_endpoint_descriptor_t *ed;
> - usbd_status error;
> int i, n;
> usb_config_descriptor_t *cd;
> - struct ucom_softc *ucom = NULL;
> char devnamefmt[32];
>
> - sc->sc_dev = self;
> -#ifdef U3G_DEBUG
> - sc->sc_intr_number = -1;
> - sc->sc_intr_pipe = NULL;
> -#endif
> - /* Move the device into the configured state. */
> - error = usbd_set_config_index(dev, U3G_CONFIG_INDEX, 1);
> - if (error) {
> - device_printf(self, "failed to set configuration: %s\n",
> - usbd_errstr(error));
> - goto bad;
> - }
> -
> /* get the config descriptor */
> cd = usbd_get_config_descriptor(dev);
> -
> if (cd == NULL) {
> device_printf(self, "failed to get configuration descriptor\n");
> - goto bad;
> + return ENXIO;
> }
>
> + sc->sc_dev = self;
> sc->sc_udev = dev;
> - sc->numports = (cd->bNumInterface <=
> U3G_MAXPORTS)?cd->bNumInterface:U3G_MAXPORTS; - for ( i = 0; i <
> sc->numports; i++ ) {
> - ucom = &sc->sc_ucom[i];
> -
> - ucom->sc_dev = self;
> - ucom->sc_udev = dev;
> - error = usbd_device2interface_handle(dev, i, &iface);
> - if (error) {
> - device_printf(ucom->sc_dev,
> - "failed to get interface, err=%s\n",
> - usbd_errstr(error));
> - ucom->sc_dying = 1;
> - goto bad;
> +
> + u3g_dev_type = u3g_lookup(uaa->vendor, uaa->product);
> + sc->sc_flags = u3g_dev_type->flags;
> + sc->sc_speed = u3g_dev_type->speed;
> +
> + sprintf(devnamefmt,"U%d.%%d", device_get_unit(self));
> + int portno = 0;
> + for (i = 0; i < uaa->nifaces && portno < U3G_MAXPORTS; i++) {
> + if (uaa->ifaces[i] == NULL)
> + continue;
> +
> + id = usbd_get_interface_descriptor(uaa->ifaces[i]);
> + if (id && id->bInterfaceClass == UICLASS_MASS) {
> + /* We attach to the interface instead of the device as
> + * some devices have a built-in SD card reader.
> + * Claim the first umass device (cdX) as it contains
> + * only Windows drivers anyway (CD-ROM), hiding it.
> + */
> +#ifndef U3G_DEBUG
> + if (!bootverbose)
> + if (uaa->vendor == USB_VENDOR_HUAWEI)
> + if (id->bInterfaceNumber == 2)
> + uaa->ifaces[i] = NULL;
> +#endif
> + continue;
> }
> - id = usbd_get_interface_descriptor(iface);
> - ucom->sc_iface = iface;
>
> - ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1;
> + int bulkin_no = -1, bulkout_no = -1;
> for (n = 0; n < id->bNumEndpoints; n++) {
> - ed = usbd_interface2endpoint_descriptor(iface, n);
> - if (ed == NULL) {
> - device_printf(ucom->sc_dev,
> - "could not read endpoint descriptor\n");
> - goto bad;
> - }
> + ed = usbd_interface2endpoint_descriptor(uaa->ifaces[i], n);
> + if (ed == NULL)
> + continue;
> if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN
> && UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
> - ucom->sc_bulkin_no = ed->bEndpointAddress;
> + bulkin_no = ed->bEndpointAddress;
> else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT
> && UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
> - ucom->sc_bulkout_no = ed->bEndpointAddress;
> - }
> - if (ucom->sc_bulkin_no == -1 || ucom->sc_bulkout_no == -1) {
> - device_printf(ucom->sc_dev, "missing endpoint\n");
> - goto bad;
> - }
> - ucom->sc_parent = sc;
> - ucom->sc_ibufsize = U3G_BUFSIZ;
> - ucom->sc_obufsize = U3G_BUFSIZ;
> - ucom->sc_ibufsizepad = U3G_BUFSIZ;
> - ucom->sc_opkthdrlen = 0;
> -
> - ucom->sc_callback = &u3g_callback;
> -
> - sprintf(devnamefmt,"U%d.%%d", device_get_unit(self));
> - DPRINTF(("u3g: in=0x%x out=0x%x, devname=%s\n",
> - ucom->sc_bulkin_no, ucom->sc_bulkout_no, devnamefmt));
> + bulkout_no = ed->bEndpointAddress;
> +
> + /* If we have found a pair of bulk-in/-out endpoints
> + * create a serial port for it. Note: We assume that
> + * the bulk-in and bulk-out endpoints appear in pairs.
> + */
> + if (bulkin_no != -1 && bulkout_no != -1) {
> + struct ucom_softc *ucom = &sc->sc_ucom[portno];
> +
> + ucom->sc_dev = self;
> + ucom->sc_udev = dev;
> + ucom->sc_iface = uaa->ifaces[i];
> + ucom->sc_bulkin_no = bulkin_no;
> + ucom->sc_ibufsize = U3G_BUFSIZ;
> + ucom->sc_ibufsizepad = U3G_BUFSIZ; // XXX What's this?
> + ucom->sc_bulkout_no = bulkout_no;
> + ucom->sc_obufsize = U3G_BUFSIZ;
> + ucom->sc_opkthdrlen = 0;
> +
> + ucom->sc_callback = &u3g_callback;
> + ucom->sc_parent = sc;
> + ucom->sc_portno = portno;
> +
> + DPRINTF("port=%d iface=%d in=0x%x out=0x%x\n",
> + portno, i,
> + ucom->sc_bulkin_no,
> + ucom->sc_bulkout_no);
> #if __FreeBSD_version < 800000
> - ucom_attach_tty(ucom, TS_CALLOUT, devnamefmt, i);
> + ucom_attach_tty(ucom, TS_CALLOUT, devnamefmt, portno);
> #else
> - ucom_attach_tty(ucom, devnamefmt, i);
> + ucom_attach_tty(ucom, devnamefmt, portno);
> #endif
> - }
> -#ifdef U3G_DEBUG
> - if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) {
> - sc->sc_intr_buf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK);
> - error = usbd_open_pipe_intr(sc->sc_intr_iface,
> - sc->sc_intr_number,
> - USBD_SHORT_XFER_OK,
> - &sc->sc_intr_pipe,
> - sc,
> - sc->sc_intr_buf,
> - sc->sc_isize,
> - u3g_intr,
> - 100);
> - if (error) {
> - device_printf(self,
> - "cannot open interrupt pipe (addr %d)\n",
> - sc->sc_intr_number);
> - goto bad;
> +
> + uaa->ifaces[i] = NULL;
> + portno++;
> + bulkin_no = bulkout_no = -1;
> + }
> }
> +
> }
> -#endif
> - device_printf(self, "configured %d serial ports (/dev/cuaU%d.X)\n",
> - sc->numports, device_get_unit(self));
> + sc->sc_numports = portno;
>
> + device_printf(self, "configured %d serial ports (%s)\n",
> + sc->sc_numports, devnamefmt);
> return 0;
> -
> -bad:
> - DPRINTF(("u3g_attach: ATTACH ERROR\n"));
> - ucom->sc_dying = 1;
> - return ENXIO;
> }
>
> static int
> @@ -291,39 +305,98 @@ u3g_detach(device_t self)
> int rv = 0;
> int i;
>
> - DPRINTF(("u3g_detach: sc=%p\n", sc));
> -
> - for (i = 0; i < sc->numports; i++) {
> - if(sc->sc_ucom[i].sc_udev) {
> - sc->sc_ucom[i].sc_dying = 1;
> - rv = ucom_detach(&sc->sc_ucom[i]);
> - if(rv != 0) {
> - device_printf(self, "Can't deallocat port %d\n", i);
> - return rv;
> - }
> + for (i = 0; i < sc->sc_numports; i++) {
> + sc->sc_ucom[i].sc_dying = 1;
> + rv = ucom_detach(&sc->sc_ucom[i]);
> + if (rv != 0) {
> + device_printf(self, "ucom_detach(U%d.%d\n", device_get_unit(self),
> i); + return rv;
> }
> }
>
> + return 0;
> +}
> +
> +static int
> +u3g_open(void *addr, int portno)
> +{
> +#if __FreeBSD_version < 800000
> + /* Supply generous buffering for these cards to avoid disappointments
> + * when setting the speed incorrectly. Only do this for the first port
> + * assuming that the rest of the ports are used for diagnostics only
> + * anyway.
> + * Note: We abuse the fact that ucom sets the speed through
> + * ispeed/ospeed, not through ispeedwat/ospeedwat.
> + */
> + if (portno == 0) {
> + struct u3g_softc *sc = addr;
> + struct ucom_softc *ucom = &sc->sc_ucom[portno];
> + struct tty *tp = ucom->sc_tty;
> #ifdef U3G_DEBUG
> - if (sc->sc_intr_pipe != NULL) {
> - int err = usbd_abort_pipe(sc->sc_intr_pipe);
> - if (err)
> - device_printf(self,
> - "abort interrupt pipe failed: %s\n",
> - usbd_errstr(err));
> - err = usbd_close_pipe(sc->sc_intr_pipe);
> - if (err)
> - device_printf(self,
> - "close interrupt pipe failed: %s\n",
> - usbd_errstr(err));
> - free(sc->sc_intr_buf, M_USBDEV);
> - sc->sc_intr_pipe = NULL;
> + device_t self = sc->sc_dev;
> +#endif
> +
> + if (sc->sc_speed&U3GSP_HSPA) {
> + tp->t_ispeedwat = 7200000;
> + tp->t_ospeedwat = 384000;
> + } else if (sc->sc_speed&U3GSP_HSUPA) {
> + tp->t_ispeedwat = 1200000;
> + tp->t_ospeedwat = 384000;
> + } else if (sc->sc_speed&U3GSP_HSDPA) {
> + tp->t_ispeedwat = 1200000;
> + tp->t_ospeedwat = 384000;
> + } else if (sc->sc_speed&U3GSP_UMTS) {
> + tp->t_ispeedwat = 384000;
> + tp->t_ospeedwat = 64000;
> + } else if (sc->sc_speed&U3GSP_EDGE) {
> + tp->t_ispeedwat = 384000;
> + tp->t_ospeedwat = 64000;
> + } else {
> + tp->t_ispeedwat = 64000;
> + tp->t_ospeedwat = 64000;
> + }
> +
> + /* Avoid excessive buffer sizes. On modern fast machines this is
> + * not needed.
> + * XXX The values here should be checked. Lower them and see
> + * whether 'lost chars' messages appear.
> + */
> + if (tp->t_ispeedwat > 384000)
> + tp->t_ispeedwat = 384000;
> + if (tp->t_ospeedwat > 384000)
> + tp->t_ospeedwat = 384000;
> +
> + DPRINTF("ispeedwat = %d, ospeedwat = %d\n",
> + tp->t_ispeedwat, tp->t_ospeedwat);
> + ttsetwater(tp);
> }
> #endif
>
> return 0;
> }
>
> +static void
> +u3g_close(void *addr, int portno)
> +{
> +#if __FreeBSD_version < 800000
> + if (portno == 0) { /* see u3g_open() */
> + /* Reduce the buffers allocated above again */
> + struct u3g_softc *sc = addr;
> + struct ucom_softc *ucom = &sc->sc_ucom[portno];
> + struct tty *tp = ucom->sc_tty;
> +#ifdef U3G_DEBUG
> + device_t self = sc->sc_dev;
> +#endif
> +
> + tp->t_ispeedwat = (speed_t)-1;
> + tp->t_ospeedwat = (speed_t)-1;
> +
> + DPRINTF("ispeedwat = default, ospeedwat = default\n");
> + ttsetwater(tp);
> + }
> +#endif
> +}
> +
> static device_method_t u3g_methods[] = {
> /* Device interface */
> DEVMETHOD(device_probe, u3g_match),
> @@ -365,32 +438,29 @@ static int
> u3gstub_match(device_t self)
> {
> struct usb_attach_arg *uaa = device_get_ivars(self);
> - usb_device_descriptor_t *dd = usbd_get_device_descriptor(uaa->device);
> + const struct u3g_dev_type_s *u3g_dev_type;
> usb_interface_descriptor_t *id;
>
> - /* These are 3G modem devices (E220, Mobile, etc.) with auto-install
> - * flash disks for Windows/MacOSX through the first interface.
> + /* This stub handles 3G modem devices (E220, Mobile, etc.) with
> + * auto-install flash disks for Windows/MacOSX on the first interface.
> + * After some command or some delay they change appearance to a modem.
> */
> - if (uaa->vendor == USB_VENDOR_HUAWEI) {
> - /* The Huawei device presents itself as a umass device with
> - * Windows drivers on it. After installation of the driver, it
> - * reinits into a 3G serial device.
> - */
> - if (uaa->iface) {
> - id = usbd_get_interface_descriptor(uaa->iface);
> - if (id && id->bInterfaceNumber == 0 && id->bInterfaceClass ==
> UICLASS_MASS) { - u3gstub_huawei_init(uaa->device);
> - return (UMATCH_VENDOR_PRODUCT_CONF_IFACE);
> - }
> - }
> - }
>
> - if (UGETW(dd->idVendor) == USB_VENDOR_QUALCOMMINC
> - || UGETW(dd->idVendor) == USB_VENDOR_NOVATEL) {
> - /* Device by these vendors will automatically reappear as a
> - * ucom device if ignored (or if sent an eject command).
> + if (!uaa->iface)
> + return UMATCH_NONE;
> +
> + u3g_dev_type = u3g_lookup(uaa->vendor, uaa->product);
> + if (!u3g_dev_type)
> + return UMATCH_NONE;
> +
> + if (u3g_dev_type->flags&U3GFL_HUAWEI_INIT
> + || u3g_dev_type->flags&U3GFL_STUB_WAIT) {
> + /* We assume that if the first interface is still a mass
> + * storage device the device has not yet changed appearance.
> */
> - return UMATCH_VENDOR_PRODUCT;
> + id = usbd_get_interface_descriptor(uaa->iface);
> + if (id && id->bInterfaceNumber == 0 && id->bInterfaceClass ==
> UICLASS_MASS) + return UMATCH_VENDOR_PRODUCT;
> }
>
> return UMATCH_NONE;
> @@ -399,11 +469,28 @@ u3gstub_match(device_t self)
> static int
> u3gstub_attach(device_t self)
> {
> -#if 0
> - if (!bootverbose)
> + struct usb_attach_arg *uaa = device_get_ivars(self);
> + const struct u3g_dev_type_s *u3g_dev_type;
> + int i;
> +#ifndef U3G_DEBUG
> + if (!bootverbose) // hide the stub attachment
> device_quiet(self);
> #endif
>
> + if (uaa->iface)
> + for (i = 0; i < uaa->nifaces; i++)
> + uaa->ifaces[i] = NULL; // claim all interfaces
> +
> + u3g_dev_type = u3g_lookup(uaa->vendor, uaa->product);
> + if (u3g_dev_type->flags&U3GFL_HUAWEI_INIT) {
> + /* XXX Should we delay the kick?
> + */
> + DPRINTF("changing Huawei modem to modem mode\n");
> + u3gstub_huawei_init(uaa->device);
> + } else if (u3g_dev_type->flags&U3GFL_STUB_WAIT) {
> + /* nop */
> + }
> +
> return 0;
> }
>
>
> Modified: head/sys/dev/usb/ubsa.c
> =========================================================================
>===== --- head/sys/dev/usb/ubsa.c Wed Oct 15 20:44:00 2008 (r183924)
> +++ head/sys/dev/usb/ubsa.c Wed Oct 15 21:25:11 2008 (r183925)
> @@ -226,52 +226,6 @@ static const struct ubsa_product {
> { USB_VENDOR_GOHUBS, USB_PRODUCT_GOHUBS_GOCOM232 },
> /* Peracom */
> { USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_SERIAL1 },
> - /* Merlin */
> - { USB_VENDOR_MERLIN, USB_PRODUCT_MERLIN_V620 },
> - /* Sierra Wireless AirCard 580 */
> - { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD580 },
> - /* Sierra Wireless AirCard 595 */
> - { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD595 },
> - /* Sierra Wireless AirCard 595U */
> - { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC595U },
> - /* Sierra Wireless AirCard 597E */
> - { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC597E },
> - /* Sierra Wireless Compass 597 */
> - { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_C597 },
> - /* Sierra Wireless AirCard 880 */
> - { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880 },
> - /* Sierra Wireless AirCard 880E */
> - { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880E },
> - /* Sierra Wireless AirCard 880U */
> - { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880U },
> - /* Sierra Wireless AirCard 881 */
> - { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881 },
> - /* Sierra Wireless AirCard 881E */
> - { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881E },
> - /* Sierra Wireless AirCard 881U */
> - { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881U },
> - /* Sierra Wireless EM5625 */
> - { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_EM5625 },
> - /* Sierra Wireless MC5720 */
> - { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720 },
> - { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720_2 },
> - /* Sierra Wireless MC5725 */
> - { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5725 },
> - { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MINI5725 },
> - /* Sierra Wireless MC8755 */
> - { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD875 },
> - { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755 },
> - { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_2 },
> - { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_3 },
> - /* Sierra Wireless MC8765 */
> - { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8765 },
> - /* Sierra Wireless MC8775 */
> - { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC875U },
> - { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8775_2 },
> - /* Sierra Wireless MC8780 */
> - { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8780 },
> - /* Sierra Wireless MC8781 */
> - { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8781 },
> { 0, 0 }
> };
>
>
> Modified: head/sys/dev/usb/usbdevs
> =========================================================================
>===== --- head/sys/dev/usb/usbdevs Wed Oct 15 20:44:00 2008 (r183924)
> +++ head/sys/dev/usb/usbdevs Wed Oct 15 21:25:11 2008 (r183925)
> @@ -1872,6 +1872,7 @@ product OPTION GT3G 0x6000 GlobeTrotter
> product OPTION GT3GQUAD 0x6300 GlobeTrotter 3G QUAD datacard
> product OPTION GT3GPLUS 0x6600 GlobeTrotter 3G+ datacard
> product OPTION GTMAX36 0x6701 GlobeTrotter Max 3.6 Modem
> +product OPTION GTMAXHSUPA 0x7001 GlobeTrotter HSUPA
>
> /* OQO */
> product OQO WIFI01 0x0002 model 01 WiFi interface
> _______________________________________________
> svn-src-all at freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/svn-src-all
> To unsubscribe, send any mail to "svn-src-all-unsubscribe at freebsd.org"
More information about the svn-src-all
mailing list