Home | History | Annotate | Line # | Download | only in usb
ugensa.c revision 1.14
      1  1.14       smb /*	$NetBSD: ugensa.c,v 1.14 2007/12/30 21:49:47 smb Exp $	*/
      2   1.1     elric 
      3   1.1     elric /*
      4   1.1     elric  * Copyright (c) 2004, 2005 The NetBSD Foundation, Inc.
      5   1.1     elric  * All rights reserved.
      6   1.1     elric  *
      7   1.1     elric  * This code is derived from software contributed to The NetBSD Foundation
      8   1.1     elric  * by Roland C. Dowdeswell <elric (at) netbsd.org>.
      9   1.1     elric  *
     10   1.1     elric  * Redistribution and use in source and binary forms, with or without
     11   1.1     elric  * modification, are permitted provided that the following conditions
     12   1.1     elric  * are met:
     13   1.1     elric  * 1. Redistributions of source code must retain the above copyright
     14   1.1     elric  *    notice, this list of conditions and the following disclaimer.
     15   1.1     elric  * 2. Redistributions in binary form must reproduce the above copyright
     16   1.1     elric  *    notice, this list of conditions and the following disclaimer in the
     17   1.1     elric  *    documentation and/or other materials provided with the distribution.
     18   1.1     elric  * 3. All advertising materials mentioning features or use of this software
     19   1.1     elric  *    must display the following acknowledgement:
     20   1.1     elric  *        This product includes software developed by the NetBSD
     21   1.1     elric  *        Foundation, Inc. and its contributors.
     22   1.1     elric  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23   1.1     elric  *    contributors may be used to endorse or promote products derived
     24   1.1     elric  *    from this software without specific prior written permission.
     25   1.1     elric  *
     26   1.1     elric  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27   1.1     elric  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28   1.1     elric  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29   1.1     elric  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30   1.1     elric  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31   1.1     elric  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32   1.1     elric  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33   1.1     elric  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34   1.1     elric  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35   1.1     elric  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36   1.1     elric  * POSSIBILITY OF SUCH DAMAGE.
     37   1.1     elric  */
     38   1.1     elric 
     39  1.13     lukem #include <sys/cdefs.h>
     40  1.14       smb __KERNEL_RCSID(0, "$NetBSD: ugensa.c,v 1.14 2007/12/30 21:49:47 smb Exp $");
     41  1.13     lukem 
     42   1.1     elric #include <sys/param.h>
     43   1.1     elric #include <sys/systm.h>
     44   1.1     elric #include <sys/kernel.h>
     45   1.1     elric #include <sys/device.h>
     46   1.1     elric #include <sys/conf.h>
     47   1.1     elric #include <sys/tty.h>
     48   1.1     elric 
     49   1.1     elric #include <dev/usb/usb.h>
     50   1.1     elric 
     51   1.1     elric #include <dev/usb/usbdi.h>
     52   1.1     elric #include <dev/usb/usbdi_util.h>
     53   1.1     elric #include <dev/usb/usbdevs.h>
     54   1.1     elric 
     55   1.1     elric #include <dev/usb/ucomvar.h>
     56   1.1     elric 
     57   1.1     elric /* XXXrcd: heh */
     58   1.1     elric #define UGENSA_DEBUG 1
     59   1.1     elric 
     60   1.1     elric #ifdef UGENSA_DEBUG
     61   1.1     elric #define DPRINTF(x)	if (ugensadebug) printf x
     62   1.1     elric #define DPRINTFN(n,x)	if (ugensadebug>(n)) printf x
     63   1.1     elric int ugensadebug = 0;
     64   1.1     elric #else
     65   1.1     elric #define DPRINTF(x)
     66   1.1     elric #define DPRINTFN(n,x)
     67   1.1     elric #endif
     68   1.1     elric 
     69   1.1     elric struct ugensa_softc {
     70   1.1     elric 	USBBASEDEVICE		sc_dev;		/* base device */
     71   1.1     elric 	usbd_device_handle	sc_udev;	/* device */
     72   1.1     elric 	usbd_interface_handle	sc_iface;	/* interface */
     73   1.1     elric 
     74   1.1     elric 	device_ptr_t		sc_subdev;
     75   1.1     elric 	int			sc_numcon;
     76   1.1     elric 
     77   1.1     elric 	u_char			sc_dying;
     78   1.1     elric };
     79   1.1     elric 
     80   1.1     elric struct ucom_methods ugensa_methods = {
     81   1.1     elric 	NULL,
     82   1.1     elric 	NULL,
     83   1.1     elric 	NULL,
     84   1.1     elric 	NULL,
     85   1.1     elric 	NULL,
     86   1.1     elric 	NULL,
     87   1.1     elric 	NULL,
     88   1.1     elric 	NULL,
     89   1.1     elric };
     90   1.1     elric 
     91   1.1     elric #define UGENSA_CONFIG_INDEX	0
     92   1.1     elric #define UGENSA_IFACE_INDEX	0
     93   1.1     elric #define UGENSA_BUFSIZE		1024
     94   1.1     elric 
     95   1.1     elric static const struct usb_devno ugensa_devs[] = {
     96   1.1     elric 	{ USB_VENDOR_AIRPRIME, USB_PRODUCT_AIRPRIME_PC5220 },
     97   1.8       gdt 	{ USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_FLEXPACKGPS },
     98   1.5       gdt 	{ USB_VENDOR_QUALCOMM_K, USB_PRODUCT_QUALCOMM_K_CDMA_MSM_K },
     99   1.8       gdt 	{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD580 },
    100  1.14       smb 	{ USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MINI5725},
    101   1.9       gdt 	{ USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_CDMA_MODEM },
    102  1.12   xtraeme 	{ USB_VENDOR_DELL, USB_PRODUCT_DELL_HSDPA }
    103   1.1     elric };
    104   1.1     elric #define ugensa_lookup(v, p) usb_lookup(ugensa_devs, v, p)
    105   1.1     elric 
    106   1.1     elric USB_DECLARE_DRIVER(ugensa);
    107   1.1     elric 
    108   1.1     elric USB_MATCH(ugensa)
    109   1.1     elric {
    110   1.1     elric 	USB_MATCH_START(ugensa, uaa);
    111   1.1     elric 
    112   1.1     elric 	DPRINTFN(20,("ugensa: vendor=0x%x, product=0x%x\n",
    113   1.1     elric 		     uaa->vendor, uaa->product));
    114   1.1     elric 
    115   1.1     elric 	return (ugensa_lookup(uaa->vendor, uaa->product) != NULL ?
    116   1.1     elric 		UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
    117   1.1     elric }
    118   1.1     elric 
    119   1.1     elric USB_ATTACH(ugensa)
    120   1.1     elric {
    121   1.1     elric 	USB_ATTACH_START(ugensa, sc, uaa);
    122   1.1     elric 	usbd_device_handle dev = uaa->device;
    123   1.1     elric 	usbd_interface_handle iface;
    124   1.1     elric 	usb_interface_descriptor_t *id;
    125   1.1     elric 	usb_endpoint_descriptor_t *ed;
    126   1.3  augustss 	char *devinfop;
    127   1.1     elric 	char *devname = USBDEVNAME(sc->sc_dev);
    128   1.1     elric 	usbd_status err;
    129   1.1     elric 	struct ucom_attach_args uca;
    130   1.1     elric 	int i;
    131   1.1     elric 
    132   1.1     elric 	DPRINTFN(10,("\nugensa_attach: sc=%p\n", sc));
    133   1.1     elric 
    134   1.1     elric 	/* Move the device into the configured state. */
    135   1.1     elric 	err = usbd_set_config_index(dev, UGENSA_CONFIG_INDEX, 1);
    136   1.1     elric 	if (err) {
    137   1.1     elric 		printf("\n%s: failed to set configuration, err=%s\n",
    138   1.1     elric 		       devname, usbd_errstr(err));
    139   1.1     elric 		goto bad;
    140   1.1     elric 	}
    141   1.1     elric 
    142   1.1     elric 	err = usbd_device2interface_handle(dev, UGENSA_IFACE_INDEX, &iface);
    143   1.1     elric 	if (err) {
    144   1.1     elric 		printf("\n%s: failed to get interface, err=%s\n",
    145   1.1     elric 		       devname, usbd_errstr(err));
    146   1.1     elric 		goto bad;
    147   1.1     elric 	}
    148   1.1     elric 
    149   1.3  augustss 	devinfop = usbd_devinfo_alloc(dev, 0);
    150   1.1     elric 	USB_ATTACH_SETUP;
    151   1.3  augustss 	printf("%s: %s\n", devname, devinfop);
    152   1.3  augustss 	usbd_devinfo_free(devinfop);
    153   1.1     elric 
    154   1.1     elric 	id = usbd_get_interface_descriptor(iface);
    155   1.1     elric 
    156   1.1     elric 	sc->sc_udev = dev;
    157   1.1     elric 	sc->sc_iface = iface;
    158   1.1     elric 
    159   1.2     elric 	uca.info = "Generic Serial Device";
    160   1.1     elric 	uca.ibufsize = UGENSA_BUFSIZE;
    161   1.1     elric 	uca.obufsize = UGENSA_BUFSIZE;
    162   1.1     elric 	uca.ibufsizepad = UGENSA_BUFSIZE;
    163   1.7    martin 	uca.portno = UCOM_UNK_PORTNO;
    164   1.1     elric 	uca.opkthdrlen = 0;
    165   1.1     elric 	uca.device = dev;
    166   1.1     elric 	uca.iface = iface;
    167   1.1     elric 	uca.methods = &ugensa_methods;
    168   1.1     elric 	uca.arg = sc;
    169   1.1     elric 
    170   1.1     elric 	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
    171   1.1     elric 			   USBDEV(sc->sc_dev));
    172   1.1     elric 
    173   1.1     elric 	uca.bulkin = uca.bulkout = -1;
    174   1.1     elric 	for (i = 0; i < id->bNumEndpoints; i++) {
    175   1.1     elric 		int addr, dir, attr;
    176   1.1     elric 
    177   1.1     elric 		ed = usbd_interface2endpoint_descriptor(iface, i);
    178   1.1     elric 		if (ed == NULL) {
    179   1.1     elric 			printf("%s: could not read endpoint descriptor"
    180   1.1     elric 			       ": %s\n", devname, usbd_errstr(err));
    181   1.1     elric 			goto bad;
    182   1.1     elric 		}
    183   1.1     elric 
    184   1.1     elric 		addr = ed->bEndpointAddress;
    185   1.1     elric 		dir = UE_GET_DIR(ed->bEndpointAddress);
    186   1.1     elric 		attr = ed->bmAttributes & UE_XFERTYPE;
    187   1.1     elric 		if (dir == UE_DIR_IN && attr == UE_BULK)
    188   1.1     elric 			uca.bulkin = addr;
    189   1.1     elric 		else if (dir == UE_DIR_OUT && attr == UE_BULK)
    190   1.1     elric 			uca.bulkout = addr;
    191   1.1     elric 		else
    192   1.1     elric 			printf("%s: unexpected endpoint\n", devname);
    193   1.1     elric 	}
    194   1.1     elric 	if (uca.bulkin == -1) {
    195   1.1     elric 		printf("%s: Could not find data bulk in\n",
    196   1.1     elric 		       USBDEVNAME(sc->sc_dev));
    197   1.1     elric 		goto bad;
    198   1.1     elric 	}
    199   1.1     elric 	if (uca.bulkout == -1) {
    200   1.1     elric 		printf("%s: Could not find data bulk out\n",
    201   1.1     elric 		       USBDEVNAME(sc->sc_dev));
    202   1.1     elric 		goto bad;
    203   1.1     elric 	}
    204   1.1     elric 
    205   1.1     elric 	DPRINTF(("ugensa: in=0x%x out=0x%x\n", uca.bulkin, uca.bulkout));
    206   1.1     elric 	sc->sc_subdev = config_found_sm_loc(self, "ucombus", NULL, &uca,
    207   1.1     elric 					    ucomprint, ucomsubmatch);
    208   1.1     elric 
    209  1.14       smb 	if (!pmf_device_register(self, NULL, NULL))
    210  1.14       smb 		aprint_error_dev(self, "couldn't establish power handler\n");
    211   1.1     elric 	USB_ATTACH_SUCCESS_RETURN;
    212   1.1     elric 
    213   1.1     elric bad:
    214   1.1     elric 	DPRINTF(("ugensa_attach: ATTACH ERROR\n"));
    215   1.1     elric 	sc->sc_dying = 1;
    216   1.1     elric 	USB_ATTACH_ERROR_RETURN;
    217   1.1     elric }
    218   1.1     elric 
    219   1.1     elric int
    220   1.1     elric ugensa_activate(device_ptr_t self, enum devact act)
    221   1.1     elric {
    222   1.1     elric 	struct ugensa_softc *sc = (struct ugensa_softc *)self;
    223   1.1     elric 	int rv = 0;
    224   1.1     elric 
    225   1.1     elric 	switch (act) {
    226   1.1     elric 	case DVACT_ACTIVATE:
    227   1.1     elric 		return (EOPNOTSUPP);
    228   1.1     elric 		break;
    229   1.1     elric 
    230   1.1     elric 	case DVACT_DEACTIVATE:
    231   1.1     elric 		sc->sc_dying = 1;
    232   1.1     elric 		if (sc->sc_subdev)
    233   1.1     elric 			rv = config_deactivate(sc->sc_subdev);
    234   1.1     elric 		break;
    235   1.1     elric 	}
    236   1.1     elric 	return (rv);
    237   1.1     elric }
    238   1.1     elric 
    239   1.1     elric USB_DETACH(ugensa)
    240   1.1     elric {
    241   1.1     elric 	USB_DETACH_START(ugensa, sc);
    242   1.1     elric 	int rv = 0;
    243   1.1     elric 
    244   1.1     elric 	DPRINTF(("ugensa_detach: sc=%p flags=%d\n", sc, flags));
    245   1.1     elric 
    246   1.1     elric 	sc->sc_dying = 1;
    247  1.14       smb 	pmf_device_deregister(self);
    248   1.1     elric 
    249   1.1     elric 	if (sc->sc_subdev != NULL)
    250   1.1     elric 		rv = config_detach(sc->sc_subdev, flags);
    251   1.1     elric 
    252   1.1     elric 	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
    253   1.1     elric 			   USBDEV(sc->sc_dev));
    254   1.1     elric 
    255   1.1     elric 	return (rv);
    256   1.1     elric }
    257