Annotation of sys/dev/usb/umsm.c, Revision 1.1
1.1 ! nbrk 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: }
CVSweb