1 /* $DragonFly: src/sys/dev/usbmisc/umsm/Attic/umsm.c,v 1.1 2007/08/16 20:38:33 hasso Exp $ */
2 /* $OpenBSD: umsm.c,v 1.15 2007/06/14 10:11:16 mbalmer Exp $ */
5 * Copyright (c) 2006 Jonathan Gray <jsg@openbsd.org>
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 /* Driver for Qualcomm MSM EVDO and UMTS communication devices */
22 #include <sys/param.h>
23 #include <sys/systm.h>
24 #include <sys/kernel.h>
25 #include <sys/device.h>
28 #include <sys/types.h>
30 #include <sys/module.h>
32 #include <bus/usb/usb.h>
33 #include <bus/usb/usbdi.h>
34 #include <bus/usb/usbdi_util.h>
35 #include <bus/usb/usbdevs.h>
36 #include <dev/usbmisc/ucom/ucomvar.h>
39 static int umsmdebug = 1;
40 #define DPRINTFN(n, x) do { if (umsmdebug > (n)) printf x; } while (0)
42 #define DPRINTFN(n, x)
44 #define DPRINTF(x) DPRINTFN(0, x)
46 #define UMSMBUFSZ 2048
47 #define UMSM_CONFIG_NO 0
48 #define UMSM_IFACE_NO 0
51 struct ucom_softc sc_ucom;
54 struct ucom_callback umsm_callback = {
65 static const struct usb_devno umsm_devs[] = {
66 { USB_VENDOR_AIRPRIME, USB_PRODUCT_AIRPRIME_PC5220 },
67 { USB_VENDOR_DELL, USB_PRODUCT_DELL_W5500 },
68 { USB_VENDOR_KYOCERA2, USB_PRODUCT_KYOCERA2_KPC650 },
69 { USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_EXPRESSCARD },
70 { USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_MERLINV620 },
71 { USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_S720 },
72 { USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U720 },
73 { USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_XU870 },
74 { USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_ES620 },
75 { USB_VENDOR_QUALCOMM, USB_PRODUCT_QUALCOMM_MSM_HSDPA },
76 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_EM5625 },
77 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD_580 },
78 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD_595 },
79 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD_875 },
80 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720 },
81 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720_2 },
82 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5725 },
83 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755 },
84 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_2 },
85 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8765 },
86 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8775 },
89 static device_probe_t umsm_match;
90 static device_attach_t umsm_attach;
91 static device_detach_t umsm_detach;
93 static device_method_t umsm_methods[] = {
94 /* Device interface */
95 DEVMETHOD(device_probe, umsm_match),
96 DEVMETHOD(device_attach, umsm_attach),
97 DEVMETHOD(device_detach, umsm_detach),
101 static driver_t umsm_driver = {
104 sizeof (struct umsm_softc)
107 DRIVER_MODULE(umsm, uhub, umsm_driver, ucom_devclass, usbd_driver_load, 0);
108 MODULE_DEPEND(umsm, usb, 1, 1, 1);
109 MODULE_DEPEND(umsm, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER);
110 MODULE_VERSION(umsm, 1);
113 umsm_match(device_t self)
115 struct usb_attach_arg *uaa = device_get_ivars(self);
117 if (uaa->iface != NULL)
120 return (usb_lookup(umsm_devs, uaa->vendor, uaa->product) != NULL) ?
121 UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
125 umsm_attach(device_t self)
127 struct umsm_softc *sc = device_get_softc(self);
128 struct usb_attach_arg *uaa = device_get_ivars(self);
129 struct ucom_softc *ucom;
130 usb_interface_descriptor_t *id;
131 usb_endpoint_descriptor_t *ed;
137 devinfo = kmalloc(1024, M_USBDEV, M_INTWAIT);
140 bzero(sc, sizeof (struct umsm_softc));
142 usbd_devinfo(uaa->device, 0, devinfo);
144 device_set_desc_copy(self, devinfo);
146 ucom->sc_udev = uaa->device;
147 ucom->sc_iface = uaa->iface;
149 devname = device_get_nameunit(ucom->sc_dev);
150 kprintf("%s: %s\n", devname, devinfo);
151 kfree(devinfo, M_USBDEV);
153 if (usbd_set_config_index(ucom->sc_udev, UMSM_CONFIG_NO, 1) != 0) {
154 kprintf("%s: could not set configuration no\n", devname);
158 /* get the first interface handle */
159 error = usbd_device2interface_handle(ucom->sc_udev, UMSM_IFACE_NO,
162 kprintf("%s: could not get interface handle\n", devname);
166 id = usbd_get_interface_descriptor(ucom->sc_iface);
168 ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1;
169 for (i = 0; i < id->bNumEndpoints; i++) {
170 ed = usbd_interface2endpoint_descriptor(ucom->sc_iface, i);
172 kprintf("%s: no endpoint descriptor found for %d\n",
177 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
178 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
179 ucom->sc_bulkin_no = ed->bEndpointAddress;
180 else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
181 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
182 ucom->sc_bulkout_no = ed->bEndpointAddress;
184 if (ucom->sc_bulkin_no == -1 || ucom->sc_bulkout_no == -1) {
185 kprintf("%s: missing endpoint\n", devname);
189 ucom->sc_parent = sc;
190 ucom->sc_portno = UCOM_UNK_PORTNO;
191 ucom->sc_ibufsize = UMSMBUFSZ;
192 ucom->sc_obufsize = UMSMBUFSZ;
193 ucom->sc_ibufsizepad = UMSMBUFSZ;
194 ucom->sc_opkthdrlen = 0;
195 ucom->sc_callback = &umsm_callback;
197 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, ucom->sc_udev,
200 DPRINTF(("umsm: in = 0x%x, out = 0x%x, intr = 0x%x\n",
201 ucom->sc_bulkin_no, ucom->sc_bulkout_no, sc->sc_intr_number));
203 ucom_attach(&sc->sc_ucom);
213 umsm_detach(device_t self)
215 struct umsm_softc *sc = device_get_softc(self);
218 DPRINTF(("umsm_detach: sc=%p\n", sc));
219 sc->sc_ucom.sc_dying = 1;
220 rv = ucom_detach(&sc->sc_ucom);
221 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_ucom.sc_udev,
229 umsm_activate(struct device *self, enum devact act)
231 struct umsm_softc *sc = (struct umsm_softc *)self;
238 case DVACT_DEACTIVATE:
239 if (sc->sc_subdev != NULL)
240 rv = config_deactivate(sc->sc_subdev);