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