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