u3g.c revision 1.3.2.2 1 /*
2 * Copyright (c) 2008 AnyWi Technologies
3 * Author: Andrea Guzzo <aguzzo (at) anywi.com>
4 * * based on uark.c 1.1 2006/08/14 08:30:22 jsg *
5 * * parts from ubsa.c 183348 2008-09-25 12:00:56Z phk *
6 *
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.
10 *
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.
18 *
19 * $FreeBSD$
20 */
21
22 #include <sys/param.h>
23 #include <sys/systm.h>
24 #include <sys/kernel.h>
25 #include <sys/malloc.h>
26 #include <sys/module.h>
27 #include <sys/bus.h>
28 #include <sys/ioccom.h>
29 #include <sys/fcntl.h>
30 #include <sys/conf.h>
31 #include <sys/tty.h>
32 #include <sys/file.h>
33 #include <sys/selinfo.h>
34
35 #include <dev/usb/usb.h>
36 #include <dev/usb/usbdi.h>
37 #include <dev/usb/usbdivar.h>
38 #include <dev/usb/usbdi_util.h>
39
40 #include <dev/usb/ucomvar.h>
41
42 #include "usbdevs.h"
43
44 #define U3GBUFSZ 1024
45 #define U3G_MAXPORTS 4
46
47 struct u3g_softc {
48 device_t sc_ucom[U3G_MAXPORTS];;
49 device_t sc_dev;
50 usbd_device_handle sc_udev;
51 u_char sc_msr;
52 u_char sc_lsr;
53 u_char numports;
54
55 usbd_interface_handle sc_intr_iface; /* interrupt interface */
56 #ifdef U3G_DEBUG
57 int sc_intr_number; /* interrupt number */
58 usbd_pipe_handle sc_intr_pipe; /* interrupt pipe */
59 u_char *sc_intr_buf; /* interrupt buffer */
60 #endif
61 int sc_isize;
62 bool sc_pseudodev;
63 };
64
65 struct ucom_methods u3g_methods = {
66 NULL,
67 NULL,
68 NULL,
69 NULL,
70 NULL,
71 NULL,
72 NULL,
73 NULL,
74 };
75
76 static const struct usb_devno u3g_devs[] = {
77 /* OEM: Option N.V. */
78 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_QUADPLUSUMTS },
79 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_HSDPA },
80 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_GTMAXHSUPA },
81 /* OEM: Qualcomm, Inc. */
82 { USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_CDMA_MSM },
83 /* OEM: Huawei */
84 { USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_MOBILE },
85 { USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E220 },
86 /* OEM: Novatel */
87 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_MERLINV620 },
88 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_ES620 },
89 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_MC950D },
90 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U720 },
91 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U727 },
92 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_MERLINU740 },
93 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U740_2 },
94 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U870 },
95 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_MERLINV620 },
96 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_S720 },
97 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_V740 },
98 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_X950D },
99 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_XU870 },
100 { USB_VENDOR_DELL, USB_PRODUCT_DELL_W5500 },
101 #if 0
102 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_MC950D_DRIVER },
103 #endif
104 /* OEM: Merlin */
105 { USB_VENDOR_MERLIN, USB_PRODUCT_MERLIN_V620 },
106
107 /* OEM: Sierra Wireless: */
108 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD580 },
109 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD595 },
110 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC595U },
111 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC597E },
112 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_C597 },
113 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880 },
114 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880E },
115 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880U },
116 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881 },
117 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881E },
118 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881U },
119 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_EM5625 },
120 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720 },
121 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720_2 },
122 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5725 },
123 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MINI5725 },
124 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD875 },
125 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755 },
126 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_2 },
127 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_3 },
128 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8765 },
129 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC875U },
130 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8775_2 },
131 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8780 },
132 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8781 },
133 { 0, 0 }
134 };
135
136 #ifdef U3G_DEBUG
137 static void
138 u3g_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
139 {
140 struct u3g_softc *sc = (struct u3g_softc *)priv;
141 aprint_normal_dev(sc->sc_dev, "INTERRUPT CALLBACK\n");
142 }
143 #endif
144
145 static int
146 u3g_novatel_reinit(struct usb_attach_arg *uaa)
147 {
148 unsigned char cmd[31];
149 usbd_interface_handle iface;
150 usb_interface_descriptor_t *id;
151 usb_endpoint_descriptor_t *ed;
152 usbd_pipe_handle pipe;
153 usbd_xfer_handle xfer;
154 int err, i;
155
156 memset(cmd, 0, sizeof(cmd));
157 /* Byte 0..3: Command Block Wrapper (CBW) signature */
158 cmd[0] = 0x55;
159 cmd[1] = 0x53;
160 cmd[2] = 0x42;
161 cmd[3] = 0x43;
162 /* 4..7: CBW Tag, has to unique, but only a single transfer used. */
163 cmd[4] = 0x01;
164 /* 8..11: CBW Transfer Length, no data here */
165 /* 12: CBW Flag: output, so 0 */
166 /* 13: CBW Lun: 0 */
167 /* 14: CBW Length */
168 cmd[14] = 0x06;
169 /* Rest is the SCSI payload */
170 /* 0: SCSI START/STOP opcode */
171 cmd[15] = 0x1b;
172 /* 1..3 unused */
173 /* 4 Load/Eject command */
174 cmd[19] = 0x02;
175 /* 5: unused */
176
177
178 /* Move the device into the configured state. */
179 err = usbd_set_config_index(uaa->device, 0, 0);
180 if (err) {
181 aprint_error("u3g: failed to set configuration index\n");
182 return UMATCH_NONE;
183 }
184
185 err = usbd_device2interface_handle(uaa->device, 0, &iface);
186 if (err != 0) {
187 aprint_error("u3g: failed to get interface\n");
188 return UMATCH_NONE;
189 }
190
191 id = usbd_get_interface_descriptor(iface);
192 ed = NULL;
193 for (i = 0 ; i < id->bNumEndpoints ; i++) {
194 ed = usbd_interface2endpoint_descriptor(iface, i);
195 if (ed == NULL)
196 continue;
197 if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_OUT)
198 continue;
199 if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK)
200 break;
201 }
202
203 if (i == id->bNumEndpoints)
204 return UMATCH_NONE;
205
206 err = usbd_open_pipe(iface, ed->bEndpointAddress, USBD_EXCLUSIVE_USE,
207 &pipe);
208 if (err != 0) {
209 aprint_error("u3g: failed to open bulk transfer pipe %d\n",
210 ed->bEndpointAddress);
211 return UMATCH_NONE;
212 }
213
214 xfer = usbd_alloc_xfer(uaa->device);
215 if (xfer != NULL) {
216 usbd_setup_xfer(xfer, pipe, NULL, cmd, sizeof(cmd),
217 USBD_SYNCHRONOUS, USBD_DEFAULT_TIMEOUT, NULL);
218
219 err = usbd_transfer(xfer);
220 if (err)
221 aprint_error("u3g: transfer failed\n");
222 usbd_free_xfer(xfer);
223 } else {
224 aprint_error("u3g: failed to allocate xfer\n");
225 err = USBD_NOMEM;
226 }
227
228 usbd_abort_pipe(pipe);
229 usbd_close_pipe(pipe);
230
231 return (err == USBD_NORMAL_COMPLETION ? UMATCH_HIGHEST : UMATCH_NONE);
232 }
233
234 static int
235 u3g_huawei_reinit(usbd_device_handle dev)
236 {
237 /* The Huawei device presents itself as a umass device with Windows
238 * drivers on it. After installation of the driver, it reinits into a
239 * 3G serial device.
240 */
241 usb_device_request_t req;
242 usb_config_descriptor_t *cdesc;
243
244 /* Get the config descriptor */
245 cdesc = usbd_get_config_descriptor(dev);
246 if (cdesc == NULL)
247 return (UMATCH_NONE);
248
249 /* One iface means umass mode, more than 1 (4 usually) means 3G mode */
250 if (cdesc->bNumInterface > 1)
251 return (UMATCH_VENDOR_PRODUCT);
252
253 req.bmRequestType = UT_WRITE_DEVICE;
254 req.bRequest = UR_SET_FEATURE;
255 USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP);
256 USETW(req.wIndex, UHF_PORT_SUSPEND);
257 USETW(req.wLength, 0);
258
259 (void) usbd_do_request(dev, &req, 0);
260
261
262 return (UMATCH_HIGHEST); /* Match to prevent umass from attaching */
263 }
264
265 static int
266 u3g_match(device_t parent, cfdata_t match, void *aux)
267 {
268 struct usb_attach_arg *uaa = aux;
269
270 if (uaa->vendor == USB_VENDOR_HUAWEI)
271 return u3g_huawei_reinit(uaa->device);
272
273 if (uaa->vendor == USB_VENDOR_NOVATEL2 &&
274 uaa->product == USB_PRODUCT_NOVATEL2_MC950D_DRIVER)
275 return u3g_novatel_reinit(uaa);
276
277 if (usb_lookup(u3g_devs, uaa->vendor, uaa->product))
278 return UMATCH_VENDOR_PRODUCT;
279
280 return UMATCH_NONE;
281 }
282
283 static void
284 u3g_attach(device_t parent, device_t self, void *aux)
285 {
286 struct u3g_softc *sc = device_private(self);
287 struct usb_attach_arg *uaa = aux;
288 usbd_device_handle dev = uaa->device;
289 usbd_interface_handle iface;
290 usb_interface_descriptor_t *id;
291 usb_endpoint_descriptor_t *ed;
292 usbd_status error;
293 int i, n;
294 usb_config_descriptor_t *cdesc;
295
296 aprint_naive("\n");
297 aprint_normal("\n");
298
299 if (uaa->vendor == USB_VENDOR_NOVATEL2 &&
300 uaa->product == USB_PRODUCT_NOVATEL2_MC950D_DRIVER) {
301 /* About to disappear... */
302 sc->sc_pseudodev = true;
303 return;
304 }
305
306 sc->sc_dev = self;
307 #ifdef U3G_DEBUG
308 sc->sc_intr_number = -1;
309 sc->sc_intr_pipe = NULL;
310 #endif
311 /* Move the device into the configured state. */
312 error = usbd_set_config_index(dev, 0, 1);
313 if (error) {
314 aprint_error_dev(self, "failed to set configuration: %s\n",
315 usbd_errstr(error));
316 return;
317 }
318
319 /* get the config descriptor */
320 cdesc = usbd_get_config_descriptor(dev);
321
322 if (cdesc == NULL) {
323 aprint_error_dev(self, "failed to get configuration descriptor\n");
324 return;
325 }
326
327 if (uaa->vendor == USB_VENDOR_HUAWEI && cdesc->bNumInterface > 1) {
328 /* About to disappear... */
329 sc->sc_pseudodev = true;
330 return;
331 }
332
333 sc->sc_udev = dev;
334 sc->numports = (cdesc->bNumInterface <= U3G_MAXPORTS)?cdesc->bNumInterface:U3G_MAXPORTS;
335 for ( i = 0; i < sc->numports; i++ ) {
336 struct ucom_attach_args uca;
337
338 error = usbd_device2interface_handle(dev, i, &iface);
339 if (error) {
340 aprint_error_dev(self,
341 "failed to get interface, err=%s\n",
342 usbd_errstr(error));
343 return;
344 }
345 id = usbd_get_interface_descriptor(iface);
346
347 uca.info = "Generic 3G Serial Device";
348 uca.ibufsize = U3GBUFSZ;
349 uca.obufsize = U3GBUFSZ;
350 uca.ibufsizepad = U3GBUFSZ;
351 uca.portno = i;
352 uca.opkthdrlen = 0;
353 uca.device = dev;
354 uca.iface = iface;
355 uca.methods = &u3g_methods;
356 uca.arg = sc;
357
358 uca.bulkin = uca.bulkout = -1;
359 for (n = 0; n < id->bNumEndpoints; n++) {
360 ed = usbd_interface2endpoint_descriptor(iface, n);
361 if (ed == NULL) {
362 aprint_error_dev(self,
363 "could not read endpoint descriptor\n");
364 return;
365 }
366 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
367 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
368 uca.bulkin = ed->bEndpointAddress;
369 else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
370 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
371 uca.bulkout = ed->bEndpointAddress;
372 }
373 if (uca.bulkin == -1 || uca.bulkout == -1) {
374 aprint_error_dev(self, "missing endpoint\n");
375 return;
376 }
377
378 sc->sc_ucom[i] = config_found_sm_loc(self, "ucombus", NULL, &uca,
379 ucomprint, ucomsubmatch);
380 }
381
382 #ifdef U3G_DEBUG
383 if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) {
384 sc->sc_intr_buf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK);
385 error = usbd_open_pipe_intr(sc->sc_intr_iface,
386 sc->sc_intr_number,
387 USBD_SHORT_XFER_OK,
388 &sc->sc_intr_pipe,
389 sc,
390 sc->sc_intr_buf,
391 sc->sc_isize,
392 u3g_intr,
393 100);
394 if (error) {
395 aprint_error_dev(self,
396 "cannot open interrupt pipe (addr %d)\n",
397 sc->sc_intr_number);
398 return;
399 }
400 }
401 #endif
402
403
404 if (!pmf_device_register(self, NULL, NULL))
405 aprint_error_dev(self, "couldn't establish power handler\n");
406 }
407
408 static int
409 u3g_detach(device_t self, int flags)
410 {
411 struct u3g_softc *sc = device_private(self);
412 int rv = 0;
413 int i;
414
415 if (sc->sc_pseudodev)
416 return 0;
417
418 pmf_device_deregister(self);
419
420 for (i = 0; i < sc->numports; i++) {
421 if(sc->sc_ucom[i]) {
422 rv = config_detach(sc->sc_ucom[i], flags);
423 if(rv != 0) {
424 aprint_verbose_dev(self, "Can't deallocat port %d", i);
425 return rv;
426 }
427 }
428 }
429
430 #ifdef U3G_DEBUG
431 if (sc->sc_intr_pipe != NULL) {
432 int err = usbd_abort_pipe(sc->sc_intr_pipe);
433 if (err)
434 aprint_error_dev(self,
435 "abort interrupt pipe failed: %s\n",
436 usbd_errstr(err));
437 err = usbd_close_pipe(sc->sc_intr_pipe);
438 if (err)
439 aprint_error_dev(self,
440 "close interrupt pipe failed: %s\n",
441 usbd_errstr(err));
442 free(sc->sc_intr_buf, M_USBDEV);
443 sc->sc_intr_pipe = NULL;
444 }
445 #endif
446
447 return 0;
448 }
449
450 static void
451 u3g_childdet(device_t self, device_t child)
452 {
453 struct u3g_softc *sc = device_private(self);
454 int i;
455
456 for (i = 0; i < sc->numports; i++) {
457 if (sc->sc_ucom[i] == child)
458 sc->sc_ucom[i] = NULL;
459 }
460 }
461
462 static int
463 u3g_activate(device_t self, enum devact act)
464 {
465 struct u3g_softc *sc = device_private(self);
466 int i, rv = 0;
467
468 switch (act) {
469 case DVACT_ACTIVATE:
470 return (EOPNOTSUPP);
471 break;
472
473 case DVACT_DEACTIVATE:
474 for (i = 0; i < sc->numports; i++) {
475 if (sc->sc_ucom[i] && config_deactivate(sc->sc_ucom[i]))
476 rv = -1;
477 }
478 break;
479 }
480 return (rv);
481 }
482
483 CFATTACH_DECL2_NEW(u3g, sizeof(struct u3g_softc), u3g_match,
484 u3g_attach, u3g_detach, u3g_activate, NULL, u3g_childdet);
485