root/dev/usb/umsm.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. umsm_match
  2. umsm_attach
  3. umsm_detach
  4. umsm_activate

    1 /*      $OpenBSD: umsm.c,v 1.16 2007/06/19 23:59:27 jcs Exp $   */
    2 
    3 /*
    4  * Copyright (c) 2006 Jonathan Gray <jsg@openbsd.org>
    5  *
    6  * Permission to use, copy, modify, and distribute this software for any
    7  * purpose with or without fee is hereby granted, provided that the above
    8  * copyright notice and this permission notice appear in all copies.
    9  *
   10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   17  */
   18 
   19 /* Driver for Qualcomm MSM EVDO and UMTS communication devices */
   20 
   21 #include <sys/param.h>
   22 #include <sys/systm.h>
   23 #include <sys/kernel.h>
   24 #include <sys/device.h>
   25 #include <sys/conf.h>
   26 #include <sys/tty.h>
   27 
   28 #include <dev/usb/usb.h>
   29 #include <dev/usb/usbdi.h>
   30 #include <dev/usb/usbdi_util.h>
   31 #include <dev/usb/usbdevs.h>
   32 #include <dev/usb/ucomvar.h>
   33 
   34 #define UMSMBUFSZ       2048
   35 #define UMSM_CONFIG_NO  0
   36 #define UMSM_IFACE_NO   0
   37 
   38 struct umsm_softc {
   39         struct device            sc_dev;
   40         usbd_device_handle       sc_udev;
   41         usbd_interface_handle    sc_iface;
   42         struct device           *sc_subdev;
   43         u_char                   sc_dying;
   44 };
   45 
   46 struct ucom_methods umsm_methods = {
   47         NULL,
   48         NULL,
   49         NULL,
   50         NULL,
   51         NULL,
   52         NULL,
   53         NULL,
   54         NULL,
   55 };
   56 
   57 static const struct usb_devno umsm_devs[] = {
   58         { USB_VENDOR_AIRPRIME,  USB_PRODUCT_AIRPRIME_PC5220 },
   59         { USB_VENDOR_DELL,      USB_PRODUCT_DELL_W5500 },
   60         { USB_VENDOR_KYOCERA2,  USB_PRODUCT_KYOCERA2_KPC650 },
   61         { USB_VENDOR_NOVATEL,   USB_PRODUCT_NOVATEL_EXPRESSCARD },
   62         { USB_VENDOR_NOVATEL,   USB_PRODUCT_NOVATEL_MERLINV620 },
   63         { USB_VENDOR_NOVATEL,   USB_PRODUCT_NOVATEL_S720 },
   64         { USB_VENDOR_NOVATEL,   USB_PRODUCT_NOVATEL_U720 },
   65         { USB_VENDOR_NOVATEL,   USB_PRODUCT_NOVATEL_XU870 },
   66         { USB_VENDOR_NOVATEL,   USB_PRODUCT_NOVATEL_ES620 },
   67         { USB_VENDOR_QUALCOMM,  USB_PRODUCT_QUALCOMM_MSM_HSDPA },
   68         { USB_VENDOR_SIERRA,    USB_PRODUCT_SIERRA_EM5625 },
   69         { USB_VENDOR_SIERRA,    USB_PRODUCT_SIERRA_AIRCARD_580 },
   70         { USB_VENDOR_SIERRA,    USB_PRODUCT_SIERRA_AIRCARD_595 },
   71         { USB_VENDOR_SIERRA,    USB_PRODUCT_SIERRA_AIRCARD_875 },
   72         { USB_VENDOR_SIERRA,    USB_PRODUCT_SIERRA_MC5720 },
   73         { USB_VENDOR_SIERRA,    USB_PRODUCT_SIERRA_MC5725 },
   74         { USB_VENDOR_SIERRA,    USB_PRODUCT_SIERRA_MC8755 },
   75         { USB_VENDOR_SIERRA,    USB_PRODUCT_SIERRA_MC8755_2 },
   76         { USB_VENDOR_SIERRA,    USB_PRODUCT_SIERRA_MC8765 },
   77         { USB_VENDOR_SIERRA,    USB_PRODUCT_SIERRA_MC8775 },
   78 };
   79 
   80 int umsm_match(struct device *, void *, void *); 
   81 void umsm_attach(struct device *, struct device *, void *); 
   82 int umsm_detach(struct device *, int); 
   83 int umsm_activate(struct device *, enum devact); 
   84 
   85 struct cfdriver umsm_cd = { 
   86         NULL, "umsm", DV_DULL 
   87 }; 
   88 
   89 const struct cfattach umsm_ca = { 
   90         sizeof(struct umsm_softc), 
   91         umsm_match, 
   92         umsm_attach, 
   93         umsm_detach, 
   94         umsm_activate, 
   95 };
   96 
   97 int
   98 umsm_match(struct device *parent, void *match, void *aux)
   99 {
  100         struct usb_attach_arg *uaa = aux;
  101 
  102         if (uaa->iface != NULL)
  103                 return UMATCH_NONE;
  104 
  105         return (usb_lookup(umsm_devs, uaa->vendor, uaa->product) != NULL) ?
  106             UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
  107 }
  108 
  109 void
  110 umsm_attach(struct device *parent, struct device *self, void *aux)
  111 {
  112         struct umsm_softc *sc = (struct umsm_softc *)self;
  113         struct usb_attach_arg *uaa = aux;
  114         struct ucom_attach_args uca;
  115         usb_interface_descriptor_t *id;
  116         usb_endpoint_descriptor_t *ed;
  117         usbd_status error;
  118         char *devinfop;
  119         int i;
  120 
  121         bzero(&uca, sizeof(uca));
  122         sc->sc_udev = uaa->device;
  123         devinfop = usbd_devinfo_alloc(uaa->device, 0);
  124         printf("\n%s: %s\n", sc->sc_dev.dv_xname, devinfop);
  125         usbd_devinfo_free(devinfop);
  126 
  127         if (usbd_set_config_index(sc->sc_udev, UMSM_CONFIG_NO, 1) != 0) {
  128                 printf("%s: could not set configuration no\n",
  129                     sc->sc_dev.dv_xname);
  130                 sc->sc_dying = 1;
  131                 return;
  132         }
  133 
  134         /* get the first interface handle */
  135         error = usbd_device2interface_handle(sc->sc_udev, UMSM_IFACE_NO,
  136             &sc->sc_iface);
  137         if (error != 0) {
  138                 printf("%s: could not get interface handle\n",
  139                     sc->sc_dev.dv_xname);
  140                 sc->sc_dying = 1;
  141                 return;
  142         }
  143 
  144         id = usbd_get_interface_descriptor(sc->sc_iface);
  145 
  146         uca.bulkin = uca.bulkout = -1;
  147         for (i = 0; i < id->bNumEndpoints; i++) {
  148                 ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
  149                 if (ed == NULL) {
  150                         printf("%s: no endpoint descriptor found for %d\n",
  151                             sc->sc_dev.dv_xname, i);
  152                         sc->sc_dying = 1;
  153                         return;
  154                 }
  155 
  156                 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
  157                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
  158                         uca.bulkin = ed->bEndpointAddress;
  159                 else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
  160                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
  161                         uca.bulkout = ed->bEndpointAddress;
  162         }
  163         if (uca.bulkin == -1 || uca.bulkout == -1) {
  164                 printf("%s: missing endpoint\n", sc->sc_dev.dv_xname);
  165                 sc->sc_dying = 1;
  166                 return;
  167         }
  168 
  169         /* We need to force size as some devices lie */
  170         uca.ibufsize = UMSMBUFSZ;
  171         uca.obufsize = UMSMBUFSZ;
  172         uca.ibufsizepad = UMSMBUFSZ;
  173         uca.opkthdrlen = 0;
  174         uca.device = sc->sc_udev;
  175         uca.iface = sc->sc_iface;
  176         uca.methods = &umsm_methods;
  177         uca.arg = sc;
  178         uca.info = NULL;
  179 
  180         usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
  181             &sc->sc_dev);
  182         
  183         sc->sc_subdev = config_found_sm(self, &uca, ucomprint, ucomsubmatch);
  184 }
  185 
  186 int
  187 umsm_detach(struct device *self, int flags)
  188 {
  189         struct umsm_softc *sc = (struct umsm_softc *)self;
  190         int rv = 0;
  191 
  192         sc->sc_dying = 1;
  193         if (sc->sc_subdev != NULL) {
  194                 rv = config_detach(sc->sc_subdev, flags);
  195                 sc->sc_subdev = NULL;
  196         }
  197 
  198         usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
  199                            &sc->sc_dev);
  200 
  201         return (rv);
  202 }
  203 
  204 int
  205 umsm_activate(struct device *self, enum devact act)
  206 {
  207         struct umsm_softc *sc = (struct umsm_softc *)self;
  208         int rv = 0;
  209 
  210         switch (act) {
  211         case DVACT_ACTIVATE:
  212                 break;
  213 
  214         case DVACT_DEACTIVATE:
  215                 if (sc->sc_subdev != NULL)
  216                         rv = config_deactivate(sc->sc_subdev);
  217                 sc->sc_dying = 1;
  218                 break;
  219         }
  220         return (rv);
  221 }

/* [<][>][^][v][top][bottom][index][help] */