Subject: Re: Verizon 1xevdo (Wireless Broadband card)
To: Roland Dowdeswell <elric@imrryr.org>
From: Lennart Augustsson <lennart@augustsson.net>
List: tech-kern
Date: 01/16/2005 19:39:54
Looks all right to me.  I'm unsure if it's the best name, though. :)

	-- Lennart

Roland Dowdeswell wrote:
> So, I recently purchased a Verizon Wireless broadband card and
> noted that NetBSD did not support it.  It is a pcmcia card on which
> there is a usb hub to which connects a ``serial device''.  None of
> the NetBSD serial drivers recognised it, so I hacked together a
> new generic serial driver which just looks for a bulk in and a bulk
> out and uses them.
> 
> This works for my card.  But, I am not terribly familiar with the
> USB framework, so I am probably missing a couple of things.  Could
> someone who is more familiar with the USB framework review and
> provide feedback on the code so that I can either check it in or
> pursue a different strategy?  (diffs attached.)
> 
> Thanks,
> 
> 
> --
>     Roland Dowdeswell                      http://www.Imrryr.ORG/~elric/
> cvs diff: Diffing .
> Index: files.usb
> ===================================================================
> RCS file: /cvsroot/src/sys/dev/usb/files.usb,v
> retrieving revision 1.56
> diff -u -p -r1.56 files.usb
> --- files.usb	23 Oct 2004 13:38:26 -0000	1.56
> +++ files.usb	11 Jan 2005 17:12:25 -0000
> @@ -135,6 +135,11 @@ device	uvisor: ucombus
>  attach	uvisor at uhub
>  file	dev/usb/uvisor.c		uvisor
>  
> +# Generic Serial Adapter
> +device	ugensa: ucombus
> +attach	ugensa at uhub
> +file	dev/usb/ugensa.c		ugensa
> +
>  # YAP phone firmware loader
>  device	uyap: ezload
>  attach	uyap at uhub
> Index: ugensa.c
> ===================================================================
> RCS file: ugensa.c
> diff -N ugensa.c
> --- /dev/null	1 Jan 1970 00:00:00 -0000
> +++ ugensa.c	11 Jan 2005 17:12:25 -0000
> @@ -0,0 +1,245 @@
> +/*	$NetBSD: ugensa.c,v 1.27 2004/09/13 12:55:49 drochner Exp $	*/
> +
> +/*
> + * Copyright (c) 2004 The NetBSD Foundation, Inc.
> + * All rights reserved.
> + *
> + * This code is derived from software contributed to The NetBSD Foundation
> + * by Roland C. Dowdeswell <elric@netbsd.org>.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + * 3. All advertising materials mentioning features or use of this software
> + *    must display the following acknowledgement:
> + *        This product includes software developed by the NetBSD
> + *        Foundation, Inc. and its contributors.
> + * 4. Neither the name of The NetBSD Foundation nor the names of its
> + *    contributors may be used to endorse or promote products derived
> + *    from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
> + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
> + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
> + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
> + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
> + * POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include <sys/param.h>
> +#include <sys/systm.h>
> +#include <sys/kernel.h>
> +#include <sys/device.h>
> +#include <sys/conf.h>
> +#include <sys/tty.h>
> +
> +#include <dev/usb/usb.h>
> +#include <dev/usb/usbhid.h>
> +
> +#include <dev/usb/usbdi.h>
> +#include <dev/usb/usbdi_util.h>
> +#include <dev/usb/usbdevs.h>
> +
> +#include <dev/usb/ucomvar.h>
> +
> +/* XXXrcd: heh */
> +#define UGENSA_DEBUG 1
> +
> +#ifdef UGENSA_DEBUG
> +#define DPRINTF(x)	if (ugensadebug) printf x
> +#define DPRINTFN(n,x)	if (ugensadebug>(n)) printf x
> +int ugensadebug = 0;
> +#else
> +#define DPRINTF(x)
> +#define DPRINTFN(n,x)
> +#endif
> +
> +struct ugensa_softc {
> +	USBBASEDEVICE		sc_dev;		/* base device */
> +	usbd_device_handle	sc_udev;	/* device */
> +	usbd_interface_handle	sc_iface;	/* interface */
> +
> +	device_ptr_t		sc_subdev;
> +	int			sc_numcon;
> +
> +	u_char			sc_dying;
> +};
> +
> +struct ucom_methods ugensa_methods = {
> +	NULL,
> +	NULL,
> +	NULL,
> +	NULL,
> +	NULL,
> +	NULL,
> +	NULL,
> +	NULL,
> +};
> +
> +#define UGENSA_CONFIG_INDEX	0
> +#define UGENSA_IFACE_INDEX	0
> +#define UGENSA_BUFSIZE		1024
> +
> +static const struct usb_devno ugensa_devs[] = {
> +	{ USB_VENDOR_AIRPRIME, USB_PRODUCT_AIRPRIME_PC5220 },
> +};
> +#define ugensa_lookup(v, p) usb_lookup(ugensa_devs, v, p)
> +
> +USB_DECLARE_DRIVER(ugensa);
> +
> +USB_MATCH(ugensa)
> +{
> +	USB_MATCH_START(ugensa, uaa);
> +
> +	if (uaa->iface != NULL)
> +		return (UMATCH_NONE);
> +
> +	DPRINTFN(20,("ugensa: vendor=0x%x, product=0x%x\n",
> +		     uaa->vendor, uaa->product));
> +
> +	return (ugensa_lookup(uaa->vendor, uaa->product) != NULL ?
> +		UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
> +}
> +
> +USB_ATTACH(ugensa)
> +{
> +	USB_ATTACH_START(ugensa, sc, uaa);
> +	usbd_device_handle dev = uaa->device;
> +	usbd_interface_handle iface;
> +	usb_interface_descriptor_t *id;
> +	usb_endpoint_descriptor_t *ed;
> +	char devinfo[1024];
> +	char *devname = USBDEVNAME(sc->sc_dev);
> +	usbd_status err;
> +	struct ucom_attach_args uca;
> +	int i;
> +
> +	DPRINTFN(10,("\nugensa_attach: sc=%p\n", sc));
> +
> +	/* Move the device into the configured state. */
> +	err = usbd_set_config_index(dev, UGENSA_CONFIG_INDEX, 1);
> +	if (err) {
> +		printf("\n%s: failed to set configuration, err=%s\n",
> +		       devname, usbd_errstr(err));
> +		goto bad;
> +	}
> +
> +	err = usbd_device2interface_handle(dev, UGENSA_IFACE_INDEX, &iface);
> +	if (err) {
> +		printf("\n%s: failed to get interface, err=%s\n",
> +		       devname, usbd_errstr(err));
> +		goto bad;
> +	}
> +
> +	usbd_devinfo(dev, 0, devinfo, sizeof(devinfo));
> +	USB_ATTACH_SETUP;
> +	printf("%s: %s\n", devname, devinfo);
> +
> +	id = usbd_get_interface_descriptor(iface);
> +
> +	sc->sc_udev = dev;
> +	sc->sc_iface = iface;
> +
> +	uca.info = "Generic Serial Device";
> +	uca.ibufsize = UGENSA_BUFSIZE;
> +	uca.obufsize = UGENSA_BUFSIZE;
> +	uca.ibufsizepad = UGENSA_BUFSIZE;
> +	uca.opkthdrlen = 0;
> +	uca.device = dev;
> +	uca.iface = iface;
> +	uca.methods = &ugensa_methods;
> +	uca.arg = sc;
> +
> +	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
> +			   USBDEV(sc->sc_dev));
> +
> +	uca.bulkin = uca.bulkout = -1;
> +	for (i = 0; i < id->bNumEndpoints; i++) {
> +		int addr, dir, attr;
> +		ed = usbd_interface2endpoint_descriptor(iface, i);
> +		if (ed == NULL) {
> +			printf("%s: could not read endpoint descriptor"
> +			       ": %s\n", devname, usbd_errstr(err));
> +			goto bad;
> +		}
> +
> +		addr = ed->bEndpointAddress;
> +		dir = UE_GET_DIR(ed->bEndpointAddress);
> +		attr = ed->bmAttributes & UE_XFERTYPE;
> +		if (dir == UE_DIR_IN && attr == UE_BULK)
> +			uca.bulkin = addr;
> +		else if (dir == UE_DIR_OUT && attr == UE_BULK)
> +			uca.bulkout = addr;
> +		else
> +			printf("%s: unexpected endpoint\n", devname);
> +	}
> +	if (uca.bulkin == -1) {
> +		printf("%s: Could not find data bulk in\n",
> +		       USBDEVNAME(sc->sc_dev));
> +		goto bad;
> +	}
> +	if (uca.bulkout == -1) {
> +		printf("%s: Could not find data bulk out\n",
> +		       USBDEVNAME(sc->sc_dev));
> +		goto bad;
> +	}
> +
> +	DPRINTF(("ugensa: in=0x%x out=0x%x\n", uca.bulkin, uca.bulkout));
> +	sc->sc_subdev = config_found_sm_loc(self, "ucombus", NULL, &uca,
> +					    ucomprint, ucomsubmatch);
> +
> +	USB_ATTACH_SUCCESS_RETURN;
> +
> +bad:
> +	DPRINTF(("ugensa_attach: ATTACH ERROR\n"));
> +	sc->sc_dying = 1;
> +	USB_ATTACH_ERROR_RETURN;
> +}
> +
> +int
> +ugensa_activate(device_ptr_t self, enum devact act)
> +{
> +	struct ugensa_softc *sc = (struct ugensa_softc *)self;
> +	int rv = 0;
> +
> +	switch (act) {
> +	case DVACT_ACTIVATE:
> +		return (EOPNOTSUPP);
> +		break;
> +
> +	case DVACT_DEACTIVATE:
> +		sc->sc_dying = 1;
> +		if (sc->sc_subdev)
> +			rv = config_deactivate(sc->sc_subdev);
> +		break;
> +	}
> +	return (rv);
> +}
> +
> +USB_DETACH(ugensa)
> +{
> +	USB_DETACH_START(ugensa, sc);
> +	int rv = 0;
> +
> +	DPRINTF(("ugensa_detach: sc=%p flags=%d\n", sc, flags));
> +
> +	sc->sc_dying = 1;
> +
> +	if (sc->sc_subdev != NULL)
> +		rv = config_detach(sc->sc_subdev, flags);
> +
> +	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
> +			   USBDEV(sc->sc_dev));
> +
> +	return (rv);
> +}
> Index: usbdevs
> ===================================================================
> RCS file: /cvsroot/src/sys/dev/usb/usbdevs,v
> retrieving revision 1.392
> diff -u -p -r1.392 usbdevs
> --- usbdevs	29 Dec 2004 08:38:44 -0000	1.392
> +++ usbdevs	11 Jan 2005 17:12:31 -0000
> @@ -387,6 +387,7 @@ vendor HAWKING		0x0e66	Hawking
>  vendor OTI		0x0ea0	Ours Technology
>  vendor PILOTECH		0x0eaf	Pilotech
>  vendor EGALAX		0x0eef	eGalax
> +vendor AIRPRIME		0x0f3d	AirPrime, Incorporated
>  vendor QUALCOMM		0x1004	Qualcomm
>  vendor MOTOROLA		0x1063	Motorola
>  vendor CCYU		0x1065	CCYU Technology
> @@ -532,6 +533,9 @@ product AGFA SNAPSCANE25	0x2095	SnapScan
>  product AGFA SNAPSCANE26	0x2097	SnapScan e26
>  product AGFA SNAPSCANE52	0x20fd	SnapScan e52
>  
> +/* AirPrime products */
> +product AIRPRIME PC5220		0x0112	CDMA Wireless PC Card
> +
>  /* AIPTEK International products */
>  product AIPTEK2 PENCAM_MEGA_1_3	0x504a	PenCam Mega 1.3
>  
> Index: usbdevs.h
> ===================================================================
> RCS file: /cvsroot/src/sys/dev/usb/usbdevs.h,v
> retrieving revision 1.396
> diff -u -p -r1.396 usbdevs.h
> --- usbdevs.h	29 Dec 2004 08:40:30 -0000	1.396
> +++ usbdevs.h	11 Jan 2005 17:12:36 -0000
> @@ -1,4 +1,4 @@
> -/*	$NetBSD: usbdevs.h,v 1.396 2004/12/29 08:40:30 imp Exp $	*/
> +/*	$NetBSD$	*/
>  
>  /*
>   * THIS FILE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
> @@ -394,6 +394,7 @@
>  #define	USB_VENDOR_OTI	0x0ea0		/* Ours Technology */
>  #define	USB_VENDOR_PILOTECH	0x0eaf		/* Pilotech */
>  #define	USB_VENDOR_EGALAX	0x0eef		/* eGalax */
> +#define	USB_VENDOR_AIRPRIME	0x0f3d		/* AirPrime, Incorporated */
>  #define	USB_VENDOR_QUALCOMM	0x1004		/* Qualcomm */
>  #define	USB_VENDOR_MOTOROLA	0x1063		/* Motorola */
>  #define	USB_VENDOR_CCYU	0x1065		/* CCYU Technology */
> @@ -539,6 +540,9 @@
>  #define	USB_PRODUCT_AGFA_SNAPSCANE26	0x2097		/* SnapScan e26 */
>  #define	USB_PRODUCT_AGFA_SNAPSCANE52	0x20fd		/* SnapScan e52 */
>  
> +/* AirPrime products */
> +#define	USB_PRODUCT_AIRPRIME_PC5220	0x0112		/* CDMA Wireless PC Card */
> +
>  /* AIPTEK International products */
>  #define	USB_PRODUCT_AIPTEK2_PENCAM_MEGA_1_3	0x504a		/* PenCam Mega 1.3 */
>  
> Index: usbdevs_data.h
> ===================================================================
> RCS file: /cvsroot/src/sys/dev/usb/usbdevs_data.h,v
> retrieving revision 1.397
> diff -u -p -r1.397 usbdevs_data.h
> --- usbdevs_data.h	29 Dec 2004 08:40:30 -0000	1.397
> +++ usbdevs_data.h	11 Jan 2005 17:12:47 -0000
> @@ -1,4 +1,4 @@
> -/*	$NetBSD: usbdevs_data.h,v 1.397 2004/12/29 08:40:30 imp Exp $	*/
> +/*	$NetBSD$	*/
>  
>  /*
>   * THIS FILE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
> @@ -430,6 +430,12 @@ const struct usb_knowndev usb_knowndevs[
>  	    "SnapScan e52",
>  	},
>  	{
> +	    USB_VENDOR_AIRPRIME, USB_PRODUCT_AIRPRIME_PC5220,
> +	    0,
> +	    "AirPrime, Incorporated",
> +	    "CDMA Wireless PC Card",
> +	},
> +	{
>  	    USB_VENDOR_AIPTEK2, USB_PRODUCT_AIPTEK2_PENCAM_MEGA_1_3,
>  	    0,
>  	    "AIPTEK International",
> @@ -7414,6 +7420,12 @@ const struct usb_knowndev usb_knowndevs[
>  	    NULL,
>  	},
>  	{
> +	    USB_VENDOR_AIRPRIME, 0,
> +	    USB_KNOWNDEV_NOPROD,
> +	    "AirPrime, Incorporated",
> +	    NULL,
> +	},
> +	{
>  	    USB_VENDOR_QUALCOMM, 0,
>  	    USB_KNOWNDEV_NOPROD,
>  	    "Qualcomm",
>