u3g.c revision 1.6.6.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 };
134
135 #ifdef U3G_DEBUG
136 static void
137 u3g_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
138 {
139 struct u3g_softc *sc = (struct u3g_softc *)priv;
140 aprint_normal_dev(sc->sc_dev, "INTERRUPT CALLBACK\n");
141 }
142 #endif
143
144 static int
145 u3g_novatel_reinit(struct usb_attach_arg *uaa)
146 {
147 unsigned char cmd[31];
148 usbd_interface_handle iface;
149 usb_interface_descriptor_t *id;
150 usb_endpoint_descriptor_t *ed;
151 usbd_pipe_handle pipe;
152 usbd_xfer_handle xfer;
153 int err, i;
154
155 memset(cmd, 0, sizeof(cmd));
156 /* Byte 0..3: Command Block Wrapper (CBW) signature */
157 cmd[0] = 0x55;
158 cmd[1] = 0x53;
159 cmd[2] = 0x42;
160 cmd[3] = 0x43;
161 /* 4..7: CBW Tag, has to unique, but only a single transfer used. */
162 cmd[4] = 0x01;
163 /* 8..11: CBW Transfer Length, no data here */
164 /* 12: CBW Flag: output, so 0 */
165 /* 13: CBW Lun: 0 */
166 /* 14: CBW Length */
167 cmd[14] = 0x06;
168 /* Rest is the SCSI payload */
169 /* 0: SCSI START/STOP opcode */
170 cmd[15] = 0x1b;
171 /* 1..3 unused */
172 /* 4 Load/Eject command */
173 cmd[19] = 0x02;
174 /* 5: unused */
175
176
177 /* Move the device into the configured state. */
178 err = usbd_set_config_index(uaa->device, 0, 0);
179 if (err) {
180 aprint_error("u3g: failed to set configuration index\n");
181 return UMATCH_NONE;
182 }
183
184 err = usbd_device2interface_handle(uaa->device, 0, &iface);
185 if (err != 0) {
186 aprint_error("u3g: failed to get interface\n");
187 return UMATCH_NONE;
188 }
189
190 id = usbd_get_interface_descriptor(iface);
191 ed = NULL;
192 for (i = 0 ; i < id->bNumEndpoints ; i++) {
193 ed = usbd_interface2endpoint_descriptor(iface, i);
194 if (ed == NULL)
195 continue;
196 if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_OUT)
197 continue;
198 if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK)
199 break;
200 }
201
202 if (i == id->bNumEndpoints)
203 return UMATCH_NONE;
204
205 err = usbd_open_pipe(iface, ed->bEndpointAddress, USBD_EXCLUSIVE_USE,
206 &pipe);
207 if (err != 0) {
208 aprint_error("u3g: failed to open bulk transfer pipe %d\n",
209 ed->bEndpointAddress);
210 return UMATCH_NONE;
211 }
212
213 xfer = usbd_alloc_xfer(uaa->device);
214 if (xfer != NULL) {
215 usbd_setup_xfer(xfer, pipe, NULL, cmd, sizeof(cmd),
216 USBD_SYNCHRONOUS, USBD_DEFAULT_TIMEOUT, NULL);
217
218 err = usbd_transfer(xfer);
219 if (err)
220 aprint_error("u3g: transfer failed\n");
221 usbd_free_xfer(xfer);
222 } else {
223 aprint_error("u3g: failed to allocate xfer\n");
224 err = USBD_NOMEM;
225 }
226
227 usbd_abort_pipe(pipe);
228 usbd_close_pipe(pipe);
229
230 return (err == USBD_NORMAL_COMPLETION ? UMATCH_HIGHEST : UMATCH_NONE);
231 }
232
233 static int
234 u3g_huawei_reinit(usbd_device_handle dev)
235 {
236 /* The Huawei device presents itself as a umass device with Windows
237 * drivers on it. After installation of the driver, it reinits into a
238 * 3G serial device.
239 */
240 usb_device_request_t req;
241 usb_config_descriptor_t *cdesc;
242
243 /* Get the config descriptor */
244 cdesc = usbd_get_config_descriptor(dev);
245 if (cdesc == NULL)
246 return (UMATCH_NONE);
247
248 /* One iface means umass mode, more than 1 (4 usually) means 3G mode */
249 if (cdesc->bNumInterface > 1)
250 return (UMATCH_VENDOR_PRODUCT);
251
252 req.bmRequestType = UT_WRITE_DEVICE;
253 req.bRequest = UR_SET_FEATURE;
254 USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP);
255 USETW(req.wIndex, UHF_PORT_SUSPEND);
256 USETW(req.wLength, 0);
257
258 (void) usbd_do_request(dev, &req, 0);
259
260
261 return (UMATCH_HIGHEST); /* Match to prevent umass from attaching */
262 }
263
264 static int
265 u3g_sierra_reinit(usbd_device_handle dev)
266 {
267 /* Some Sierra devices presents themselves as a umass device with
268 * Windows drivers on it. After installation of the driver, it
269 * reinits into a * 3G serial device.
270 */
271 usb_device_request_t req;
272 usb_config_descriptor_t *cdesc;
273
274 /* Get the config descriptor */
275 cdesc = usbd_get_config_descriptor(dev);
276 if (cdesc == NULL)
277 return (UMATCH_NONE);
278
279 req.bmRequestType = UT_VENDOR;
280 req.bRequest = UR_SET_INTERFACE;
281 USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP);
282 USETW(req.wIndex, UHF_PORT_CONNECTION);
283 USETW(req.wLength, 0);
284
285 (void) usbd_do_request(dev, &req, 0);
286
287 return (UMATCH_HIGHEST); /* Match to prevent umass from attaching */
288 }
289
290 static int
291 u3g_match(device_t parent, cfdata_t match, void *aux)
292 {
293 struct usb_attach_arg *uaa = aux;
294
295 if (uaa->vendor == USB_VENDOR_HUAWEI)
296 return u3g_huawei_reinit(uaa->device);
297
298 if (uaa->vendor == USB_VENDOR_NOVATEL2 &&
299 uaa->product == USB_PRODUCT_NOVATEL2_MC950D_DRIVER)
300 return u3g_novatel_reinit(uaa);
301
302 if (uaa->vendor == USB_VENDOR_SIERRA &&
303 uaa->product == USB_PRODUCT_SIERRA_INSTALLER)
304 return u3g_sierra_reinit(uaa->device);
305
306 if (usb_lookup(u3g_devs, uaa->vendor, uaa->product))
307 return UMATCH_VENDOR_PRODUCT;
308
309 return UMATCH_NONE;
310 }
311
312 static void
313 u3g_attach(device_t parent, device_t self, void *aux)
314 {
315 struct u3g_softc *sc = device_private(self);
316 struct usb_attach_arg *uaa = aux;
317 usbd_device_handle dev = uaa->device;
318 usbd_interface_handle iface;
319 usb_interface_descriptor_t *id;
320 usb_endpoint_descriptor_t *ed;
321 usbd_status error;
322 int i, n;
323 usb_config_descriptor_t *cdesc;
324
325 aprint_naive("\n");
326 aprint_normal("\n");
327
328 if (uaa->vendor == USB_VENDOR_NOVATEL2 &&
329 uaa->product == USB_PRODUCT_NOVATEL2_MC950D_DRIVER) {
330 /* About to disappear... */
331 sc->sc_pseudodev = true;
332 return;
333 }
334
335 sc->sc_dev = self;
336 #ifdef U3G_DEBUG
337 sc->sc_intr_number = -1;
338 sc->sc_intr_pipe = NULL;
339 #endif
340 /* Move the device into the configured state. */
341 error = usbd_set_config_index(dev, 0, 1);
342 if (error) {
343 aprint_error_dev(self, "failed to set configuration: %s\n",
344 usbd_errstr(error));
345 return;
346 }
347
348 /* get the config descriptor */
349 cdesc = usbd_get_config_descriptor(dev);
350
351 if (cdesc == NULL) {
352 aprint_error_dev(self, "failed to get configuration descriptor\n");
353 return;
354 }
355
356 if (uaa->vendor == USB_VENDOR_HUAWEI && cdesc->bNumInterface > 1) {
357 /* About to disappear... */
358 sc->sc_pseudodev = true;
359 return;
360 }
361
362 if (uaa->vendor == USB_VENDOR_SIERRA &&
363 uaa->product == USB_PRODUCT_SIERRA_INSTALLER) {
364 /* About to disappear... */
365 sc->sc_pseudodev = true;
366 return;
367 }
368
369 sc->sc_udev = dev;
370 sc->numports = (cdesc->bNumInterface <= U3G_MAXPORTS)?cdesc->bNumInterface:U3G_MAXPORTS;
371 for ( i = 0; i < sc->numports; i++ ) {
372 struct ucom_attach_args uca;
373
374 error = usbd_device2interface_handle(dev, i, &iface);
375 if (error) {
376 aprint_error_dev(self,
377 "failed to get interface, err=%s\n",
378 usbd_errstr(error));
379 return;
380 }
381 id = usbd_get_interface_descriptor(iface);
382
383 uca.info = "Generic 3G Serial Device";
384 uca.ibufsize = U3GBUFSZ;
385 uca.obufsize = U3GBUFSZ;
386 uca.ibufsizepad = U3GBUFSZ;
387 uca.portno = i;
388 uca.opkthdrlen = 0;
389 uca.device = dev;
390 uca.iface = iface;
391 uca.methods = &u3g_methods;
392 uca.arg = sc;
393
394 uca.bulkin = uca.bulkout = -1;
395 for (n = 0; n < id->bNumEndpoints; n++) {
396 ed = usbd_interface2endpoint_descriptor(iface, n);
397 if (ed == NULL) {
398 aprint_error_dev(self,
399 "could not read endpoint descriptor\n");
400 return;
401 }
402 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
403 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
404 uca.bulkin = ed->bEndpointAddress;
405 else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
406 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
407 uca.bulkout = ed->bEndpointAddress;
408 }
409 if (uca.bulkin == -1 || uca.bulkout == -1) {
410 aprint_error_dev(self, "missing endpoint\n");
411 return;
412 }
413
414 sc->sc_ucom[i] = config_found_sm_loc(self, "ucombus", NULL, &uca,
415 ucomprint, ucomsubmatch);
416 }
417
418 #ifdef U3G_DEBUG
419 if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) {
420 sc->sc_intr_buf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK);
421 error = usbd_open_pipe_intr(sc->sc_intr_iface,
422 sc->sc_intr_number,
423 USBD_SHORT_XFER_OK,
424 &sc->sc_intr_pipe,
425 sc,
426 sc->sc_intr_buf,
427 sc->sc_isize,
428 u3g_intr,
429 100);
430 if (error) {
431 aprint_error_dev(self,
432 "cannot open interrupt pipe (addr %d)\n",
433 sc->sc_intr_number);
434 return;
435 }
436 }
437 #endif
438
439
440 if (!pmf_device_register(self, NULL, NULL))
441 aprint_error_dev(self, "couldn't establish power handler\n");
442 }
443
444 static int
445 u3g_detach(device_t self, int flags)
446 {
447 struct u3g_softc *sc = device_private(self);
448 int rv = 0;
449 int i;
450
451 if (sc->sc_pseudodev)
452 return 0;
453
454 pmf_device_deregister(self);
455
456 for (i = 0; i < sc->numports; i++) {
457 if(sc->sc_ucom[i]) {
458 rv = config_detach(sc->sc_ucom[i], flags);
459 if(rv != 0) {
460 aprint_verbose_dev(self, "Can't deallocat port %d", i);
461 return rv;
462 }
463 }
464 }
465
466 #ifdef U3G_DEBUG
467 if (sc->sc_intr_pipe != NULL) {
468 int err = usbd_abort_pipe(sc->sc_intr_pipe);
469 if (err)
470 aprint_error_dev(self,
471 "abort interrupt pipe failed: %s\n",
472 usbd_errstr(err));
473 err = usbd_close_pipe(sc->sc_intr_pipe);
474 if (err)
475 aprint_error_dev(self,
476 "close interrupt pipe failed: %s\n",
477 usbd_errstr(err));
478 free(sc->sc_intr_buf, M_USBDEV);
479 sc->sc_intr_pipe = NULL;
480 }
481 #endif
482
483 return 0;
484 }
485
486 static void
487 u3g_childdet(device_t self, device_t child)
488 {
489 struct u3g_softc *sc = device_private(self);
490 int i;
491
492 for (i = 0; i < sc->numports; i++) {
493 if (sc->sc_ucom[i] == child)
494 sc->sc_ucom[i] = NULL;
495 }
496 }
497
498 static int
499 u3g_activate(device_t self, enum devact act)
500 {
501 struct u3g_softc *sc = device_private(self);
502 int i, rv = 0;
503
504 switch (act) {
505 case DVACT_ACTIVATE:
506 return (EOPNOTSUPP);
507 break;
508
509 case DVACT_DEACTIVATE:
510 for (i = 0; i < sc->numports; i++) {
511 if (sc->sc_ucom[i] && config_deactivate(sc->sc_ucom[i]))
512 rv = -1;
513 }
514 break;
515 }
516 return (rv);
517 }
518
519 CFATTACH_DECL2_NEW(u3g, sizeof(struct u3g_softc), u3g_match,
520 u3g_attach, u3g_detach, u3g_activate, NULL, u3g_childdet);
521