u3g.c revision 1.20.2.4 1 /* $NetBSD: u3g.c,v 1.20.2.4 2013/01/16 05:33:34 yamt Exp $ */
2
3 /*-
4 * Copyright (c) 2009 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 /*
32 * Copyright (c) 2008 AnyWi Technologies
33 * Author: Andrea Guzzo <aguzzo (at) anywi.com>
34 * * based on uark.c 1.1 2006/08/14 08:30:22 jsg *
35 * * parts from ubsa.c 183348 2008-09-25 12:00:56Z phk *
36 *
37 * Permission to use, copy, modify, and distribute this software for any
38 * purpose with or without fee is hereby granted, provided that the above
39 * copyright notice and this permission notice appear in all copies.
40 *
41 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
42 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
43 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
44 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
45 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
46 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
47 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
48 *
49 * $FreeBSD$
50 */
51
52 #include <sys/cdefs.h>
53 __KERNEL_RCSID(0, "$NetBSD: u3g.c,v 1.20.2.4 2013/01/16 05:33:34 yamt Exp $");
54
55 #include <sys/param.h>
56 #include <sys/systm.h>
57 #include <sys/kernel.h>
58 #include <sys/malloc.h>
59 #include <sys/bus.h>
60 #include <sys/conf.h>
61 #include <sys/tty.h>
62
63 #include <dev/usb/usb.h>
64 #include <dev/usb/usbdi.h>
65 #include <dev/usb/usbdivar.h>
66 #include <dev/usb/usbdi_util.h>
67
68 #include <dev/usb/ucomvar.h>
69
70 #include "usbdevs.h"
71
72 /*
73 * We read/write data from/to the device in 4KB chunks to maximise
74 * performance.
75 */
76 #define U3G_BUFF_SIZE 4096
77
78 /*
79 * Some 3G devices (the Huawei E160/E220 springs to mind here) buffer up
80 * data internally even when the USB pipes are closed. So on first open,
81 * we can receive a large chunk of stale data.
82 *
83 * This causes a real problem because the default TTYDEF_LFLAG (applied
84 * on first open) has the ECHO flag set, resulting in all the stale data
85 * being echoed straight back to the device by the tty(4) layer. Some
86 * devices (again, the Huawei E160/E220 for example) react to this spew
87 * by going catatonic.
88 *
89 * All this happens before the application gets a chance to disable ECHO.
90 *
91 * We work around this by ignoring all data received from the device for
92 * a period of two seconds, or until the application starts sending data -
93 * whichever comes first.
94 */
95 #define U3G_PURGE_SECS 2
96
97 /*
98 * Define bits for the virtual modem control pins.
99 * The input pin states are reported via the interrupt pipe on some devices.
100 */
101 #define U3G_OUTPIN_DTR (1u << 0)
102 #define U3G_OUTPIN_RTS (1u << 1)
103 #define U3G_INPIN_DCD (1u << 0)
104 #define U3G_INPIN_DSR (1u << 1)
105 #define U3G_INPIN_RI (1u << 3)
106
107 /*
108 * USB request to set the output pin status
109 */
110 #define U3G_SET_PIN 0x22
111
112 struct u3g_softc {
113 device_t sc_dev;
114 usbd_device_handle sc_udev;
115 bool sc_dying; /* We're going away */
116 int sc_ifaceno; /* Device interface number */
117
118 struct u3g_com {
119 device_t c_dev; /* Child ucom(4) handle */
120
121 bool c_open; /* Device is in use */
122 bool c_purging; /* Purging stale data */
123 struct timeval c_purge_start; /* Control duration of purge */
124
125 u_char c_msr; /* Emulated 'msr' */
126 uint16_t c_outpins; /* Output pin state */
127 } sc_com[10];
128 size_t sc_ncom;
129
130 usbd_pipe_handle sc_intr_pipe; /* Interrupt pipe */
131 u_char *sc_intr_buff; /* Interrupt buffer */
132 };
133
134 /*
135 * The device driver has two personalities. The first uses the 'usbdevif'
136 * interface attribute so that a match will claim the entire USB device
137 * for itself. This is used for when a device needs to be mode-switched
138 * and ensures any other interfaces present cannot be claimed by other
139 * drivers while the mode-switch is in progress.
140 *
141 * The second personality uses the 'usbifif' interface attribute so that
142 * it can claim the 3G modem interfaces for itself, leaving others (such
143 * as the mass storage interfaces on some devices) for other drivers.
144 */
145 static int u3ginit_match(device_t, cfdata_t, void *);
146 static void u3ginit_attach(device_t, device_t, void *);
147 static int u3ginit_detach(device_t, int);
148
149 CFATTACH_DECL2_NEW(u3ginit, 0, u3ginit_match,
150 u3ginit_attach, u3ginit_detach, NULL, NULL, NULL);
151
152
153 static int u3g_match(device_t, cfdata_t, void *);
154 static void u3g_attach(device_t, device_t, void *);
155 static int u3g_detach(device_t, int);
156 static int u3g_activate(device_t, enum devact);
157 static void u3g_childdet(device_t, device_t);
158
159 CFATTACH_DECL2_NEW(u3g, sizeof(struct u3g_softc), u3g_match,
160 u3g_attach, u3g_detach, u3g_activate, NULL, u3g_childdet);
161
162
163 static void u3g_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
164 static void u3g_get_status(void *, int, u_char *, u_char *);
165 static void u3g_set(void *, int, int, int);
166 static int u3g_open(void *, int);
167 static void u3g_close(void *, int);
168 static void u3g_read(void *, int, u_char **, uint32_t *);
169 static void u3g_write(void *, int, u_char *, u_char *, u_int32_t *);
170
171 struct ucom_methods u3g_methods = {
172 u3g_get_status,
173 u3g_set,
174 NULL,
175 NULL,
176 u3g_open,
177 u3g_close,
178 u3g_read,
179 u3g_write,
180 };
181
182 /*
183 * Allegedly supported devices
184 */
185 static const struct usb_devno u3g_devs[] = {
186 { USB_VENDOR_DELL, USB_PRODUCT_DELL_W5500 },
187 /* OEM: Huawei */
188 { USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1750 },
189 { USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1820 },
190 { USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E220 },
191 { USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_EM770W },
192 { USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_K3765 },
193 { USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_MOBILE },
194 /* OEM: Merlin */
195 { USB_VENDOR_MERLIN, USB_PRODUCT_MERLIN_V620 },
196 /* OEM: Novatel */
197 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_ES620 },
198 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_EU8X0D },
199 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_MC950D },
200 #if 0
201 /* These are matched in u3ginit_match() */
202 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_MC950D_DRIVER },
203 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U760_DRIVER },
204 #endif
205 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_MERLINU740 },
206 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_MERLINV620 },
207 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_S720 },
208 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U720 },
209 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U727 },
210 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U740_2 },
211 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U760 },
212 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U870 },
213 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_V740 },
214 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_X950D },
215 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_XU870 },
216 /* OEM: Option N.V. */
217 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_QUADPLUSUMTS },
218 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_HSDPA },
219 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_GTMAXHSUPA },
220 /* OEM: Qualcomm, Inc. */
221 { USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_CDMA_MSM },
222 { USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_ZTE_MF626 },
223 { USB_VENDOR_QUALCOMM, USB_PRODUCT_QUALCOMM_NTT_DOCOMO_L02C_MODEM },
224
225 /* OEM: Sierra Wireless: */
226 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC595U },
227 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC597E },
228 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC875U },
229 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880 },
230 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880E },
231 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880U },
232 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881 },
233 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881E },
234 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881U },
235 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD580 },
236 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD595 },
237 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD875 },
238 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_C597 },
239 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_EM5625 },
240 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720 },
241 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720_2 },
242 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5725 },
243 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755 },
244 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_2 },
245 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_3 },
246 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8765 },
247 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8775_2 },
248 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8780 },
249 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8781 },
250 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MINI5725 },
251 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_USB305 },
252 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_250U },
253 /* Toshiba */
254 { USB_VENDOR_TOSHIBA, USB_PRODUCT_TOSHIBA_HSDPA_MODEM_EU870DT1 },
255
256 /* 4G Systems */
257 { USB_VENDOR_4GSYSTEMS, USB_PRODUCT_4GSYSTEMS_XSSTICK_P14 },
258 };
259
260 static int
261 send_bulkmsg(usbd_device_handle dev, void *cmd, size_t cmdlen)
262 {
263 usbd_interface_handle iface;
264 usb_interface_descriptor_t *id;
265 usb_endpoint_descriptor_t *ed;
266 usbd_pipe_handle pipe;
267 usbd_xfer_handle xfer;
268 int err, i;
269
270 /* Move the device into the configured state. */
271 err = usbd_set_config_index(dev, 0, 0);
272 if (err) {
273 aprint_error("u3g: failed to set configuration index\n");
274 return UMATCH_NONE;
275 }
276
277 err = usbd_device2interface_handle(dev, 0, &iface);
278 if (err != 0) {
279 aprint_error("u3ginit: failed to get interface\n");
280 return UMATCH_NONE;
281 }
282
283 id = usbd_get_interface_descriptor(iface);
284 ed = NULL;
285 for (i = 0 ; i < id->bNumEndpoints ; i++) {
286 ed = usbd_interface2endpoint_descriptor(iface, i);
287 if (ed == NULL)
288 continue;
289 if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_OUT)
290 continue;
291 if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK)
292 break;
293 }
294
295 if (i == id->bNumEndpoints)
296 return UMATCH_NONE;
297
298 err = usbd_open_pipe(iface, ed->bEndpointAddress,
299 USBD_EXCLUSIVE_USE, &pipe);
300 if (err != 0) {
301 aprint_error("u3ginit: failed to open bulk transfer pipe %d\n",
302 ed->bEndpointAddress);
303 return UMATCH_NONE;
304 }
305
306 xfer = usbd_alloc_xfer(dev);
307 if (xfer != NULL) {
308 usbd_setup_xfer(xfer, pipe, NULL, cmd, cmdlen,
309 USBD_SYNCHRONOUS, USBD_DEFAULT_TIMEOUT, NULL);
310
311 err = usbd_transfer(xfer);
312
313 #if 0 /* XXXpooka: at least my huawei "fails" this always, but still detaches */
314 if (err)
315 aprint_error("u3ginit: transfer failed\n");
316 #else
317 err = 0;
318 #endif
319 usbd_free_xfer(xfer);
320 } else {
321 aprint_error("u3ginit: failed to allocate xfer\n");
322 err = USBD_NOMEM;
323 }
324
325 usbd_abort_pipe(pipe);
326 usbd_close_pipe(pipe);
327
328 return (err == USBD_NORMAL_COMPLETION ? UMATCH_HIGHEST : UMATCH_NONE);
329 }
330
331 static int
332 u3g_novatel_reinit(usbd_device_handle dev)
333 {
334 unsigned char cmd[31];
335
336 memset(cmd, 0, sizeof(cmd));
337 /* Byte 0..3: Command Block Wrapper (CBW) signature */
338 cmd[0] = 0x55;
339 cmd[1] = 0x53;
340 cmd[2] = 0x42;
341 cmd[3] = 0x43;
342 /* 4..7: CBW Tag, has to unique, but only a single transfer used. */
343 cmd[4] = 0x01;
344 /* 8..11: CBW Transfer Length, no data here */
345 /* 12: CBW Flag: output, so 0 */
346 /* 13: CBW Lun: 0 */
347 /* 14: CBW Length */
348 cmd[14] = 0x06;
349 /* Rest is the SCSI payload */
350 /* 0: SCSI START/STOP opcode */
351 cmd[15] = 0x1b;
352 /* 1..3 unused */
353 /* 4 Load/Eject command */
354 cmd[19] = 0x02;
355 /* 5: unused */
356
357 return send_bulkmsg(dev, cmd, sizeof(cmd));
358 }
359
360 static int
361 u3g_huawei_reinit(usbd_device_handle dev)
362 {
363 /*
364 * The Huawei device presents itself as a umass device with Windows
365 * drivers on it. After installation of the driver, it reinits into a
366 * 3G serial device.
367 */
368 usb_device_request_t req;
369 usb_config_descriptor_t *cdesc;
370
371 /* Get the config descriptor */
372 cdesc = usbd_get_config_descriptor(dev);
373 if (cdesc == NULL) {
374 usb_device_descriptor_t dd;
375
376 if (usbd_get_device_desc(dev, &dd) != 0)
377 return (UMATCH_NONE);
378
379 if (dd.bNumConfigurations != 1)
380 return (UMATCH_NONE);
381
382 if (usbd_set_config_index(dev, 0, 1) != 0)
383 return (UMATCH_NONE);
384
385 cdesc = usbd_get_config_descriptor(dev);
386
387 if (cdesc == NULL)
388 return (UMATCH_NONE);
389 }
390
391 /*
392 * One iface means umass mode, more than 1 (4 usually) means 3G mode.
393 *
394 * XXX: We should check the first interface's device class just to be
395 * sure. If it's a mass storage device, then we can be fairly certain
396 * it needs a mode-switch.
397 */
398 if (cdesc->bNumInterface > 1)
399 return (UMATCH_NONE);
400
401 req.bmRequestType = UT_WRITE_DEVICE;
402 req.bRequest = UR_SET_FEATURE;
403 USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP);
404 USETW(req.wIndex, UHF_PORT_SUSPEND);
405 USETW(req.wLength, 0);
406
407 (void) usbd_do_request(dev, &req, 0);
408
409 return (UMATCH_HIGHEST); /* Prevent umass from attaching */
410 }
411
412 static int
413 u3g_huawei_k3765_reinit(usbd_device_handle dev)
414 {
415 unsigned char cmd[31];
416
417 /* magic string adapted from some webpage */
418 memset(cmd, 0, sizeof(cmd));
419 cmd[0] = 0x55;
420 cmd[1] = 0x53;
421 cmd[2] = 0x42;
422 cmd[3] = 0x43;
423 cmd[15]= 0x11;
424 cmd[16]= 0x06;
425
426 return send_bulkmsg(dev, cmd, sizeof(cmd));
427 }
428
429 static int
430 u3g_sierra_reinit(usbd_device_handle dev)
431 {
432 /* Some Sierra devices presents themselves as a umass device with
433 * Windows drivers on it. After installation of the driver, it
434 * reinits into a * 3G serial device.
435 */
436 usb_device_request_t req;
437
438 req.bmRequestType = UT_VENDOR;
439 req.bRequest = UR_SET_INTERFACE;
440 USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP);
441 USETW(req.wIndex, UHF_PORT_CONNECTION);
442 USETW(req.wLength, 0);
443
444 (void) usbd_do_request(dev, &req, 0);
445
446 return (UMATCH_HIGHEST); /* Match to prevent umass from attaching */
447 }
448
449 static int
450 u3g_4gsystems_reinit(usbd_device_handle dev)
451 {
452 /* magic string adapted from usb_modeswitch database */
453 static unsigned char cmd[31] = {
454 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78, 0x80, 0x00,
455 0x00, 0x00, 0x80, 0x00, 0x06, 0x06, 0xf5, 0x04, 0x02, 0x52,
456 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
457 0x00
458 };
459
460 return send_bulkmsg(dev, cmd, sizeof(cmd));
461 }
462
463 /*
464 * First personality:
465 *
466 * Claim the entire device if a mode-switch is required.
467 */
468
469 static int
470 u3ginit_match(device_t parent, cfdata_t match, void *aux)
471 {
472 struct usb_attach_arg *uaa = aux;
473
474 /*
475 * Huawei changes product when it is configured as a modem.
476 */
477 switch (uaa->vendor) {
478 case USB_VENDOR_HUAWEI:
479 if (uaa->product == USB_PRODUCT_HUAWEI_K3765)
480 return UMATCH_NONE;
481
482 switch (uaa->product) {
483 case USB_PRODUCT_HUAWEI_E1750INIT:
484 case USB_PRODUCT_HUAWEI_K3765INIT:
485 return u3g_huawei_k3765_reinit(uaa->device);
486 break;
487 default:
488 return u3g_huawei_reinit(uaa->device);
489 break;
490 }
491 break;
492
493 case USB_VENDOR_NOVATEL2:
494 switch (uaa->product){
495 case USB_PRODUCT_NOVATEL2_MC950D_DRIVER:
496 case USB_PRODUCT_NOVATEL2_U760_DRIVER:
497 return u3g_novatel_reinit(uaa->device);
498 break;
499 default:
500 break;
501 }
502 break;
503
504 case USB_VENDOR_SIERRA:
505 if (uaa->product == USB_PRODUCT_SIERRA_INSTALLER)
506 return u3g_sierra_reinit(uaa->device);
507 break;
508
509 case USB_VENDOR_QUALCOMMINC:
510 if (uaa->product == USB_PRODUCT_QUALCOMMINC_ZTE_STOR)
511 return u3g_novatel_reinit(uaa->device);
512 break;
513
514 case USB_VENDOR_QUALCOMM:
515 if (uaa->product == USB_PRODUCT_QUALCOMM_NTT_DOCOMO_L02C_STORAGE)
516 return u3g_novatel_reinit(uaa->device);
517 break;
518
519 case USB_VENDOR_4GSYSTEMS:
520 if (uaa->product == USB_PRODUCT_4GSYSTEMS_XSSTICK_P14_INSTALLER)
521 return u3g_4gsystems_reinit(uaa->device);
522 break;
523
524 default:
525 break;
526 }
527
528 return UMATCH_NONE;
529 }
530
531 static void
532 u3ginit_attach(device_t parent, device_t self, void *aux)
533 {
534 struct usb_attach_arg *uaa = aux;
535
536 aprint_naive("\n");
537 aprint_normal(": Switching to 3G mode\n");
538
539 if (uaa->vendor == USB_VENDOR_NOVATEL2) {
540 switch (uaa->product) {
541 case USB_PRODUCT_NOVATEL2_MC950D_DRIVER:
542 case USB_PRODUCT_NOVATEL2_U760_DRIVER:
543 /* About to disappear... */
544 return;
545 break;
546 default:
547 break;
548 }
549 }
550
551 /* Move the device into the configured state. */
552 (void) usbd_set_config_index(uaa->device, 0, 1);
553 }
554
555 static int
556 u3ginit_detach(device_t self, int flags)
557 {
558
559 return (0);
560 }
561
562
563 /*
564 * Second personality:
565 *
566 * Claim only those interfaces required for 3G modem operation.
567 */
568
569 static int
570 u3g_match(device_t parent, cfdata_t match, void *aux)
571 {
572 struct usbif_attach_arg *uaa = aux;
573 usbd_interface_handle iface;
574 usb_interface_descriptor_t *id;
575 usbd_status error;
576
577 if (!usb_lookup(u3g_devs, uaa->vendor, uaa->product))
578 return (UMATCH_NONE);
579
580 error = usbd_device2interface_handle(uaa->device, uaa->ifaceno, &iface);
581 if (error) {
582 printf("u3g_match: failed to get interface, err=%s\n",
583 usbd_errstr(error));
584 return (UMATCH_NONE);
585 }
586
587 id = usbd_get_interface_descriptor(iface);
588 if (id == NULL) {
589 printf("u3g_match: failed to get interface descriptor\n");
590 return (UMATCH_NONE);
591 }
592
593 /*
594 * 3G modems generally report vendor-specific class
595 *
596 * XXX: this may be too generalised.
597 */
598 return ((id->bInterfaceClass == UICLASS_VENDOR) ?
599 UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
600 }
601
602 static void
603 u3g_attach(device_t parent, device_t self, void *aux)
604 {
605 struct u3g_softc *sc = device_private(self);
606 struct usbif_attach_arg *uaa = aux;
607 usbd_device_handle dev = uaa->device;
608 usbd_interface_handle iface;
609 usb_interface_descriptor_t *id;
610 usb_endpoint_descriptor_t *ed;
611 struct ucom_attach_args uca;
612 usbd_status error;
613 int n, intr_address, intr_size;
614
615 aprint_naive("\n");
616 aprint_normal("\n");
617
618 sc->sc_dev = self;
619 sc->sc_dying = false;
620 sc->sc_udev = dev;
621
622 error = usbd_device2interface_handle(dev, uaa->ifaceno, &iface);
623 if (error) {
624 aprint_error_dev(self, "failed to get interface, err=%s\n",
625 usbd_errstr(error));
626 return;
627 }
628
629 id = usbd_get_interface_descriptor(iface);
630
631 uca.info = "3G Modem";
632 uca.ibufsize = U3G_BUFF_SIZE;
633 uca.obufsize = U3G_BUFF_SIZE;
634 uca.ibufsizepad = U3G_BUFF_SIZE;
635 uca.opkthdrlen = 0;
636 uca.device = dev;
637 uca.iface = iface;
638 uca.methods = &u3g_methods;
639 uca.arg = sc;
640 uca.portno = -1;
641 uca.bulkin = uca.bulkout = -1;
642
643
644 sc->sc_ifaceno = uaa->ifaceno;
645 intr_address = -1;
646 intr_size = 0;
647
648 for (n = 0; n < id->bNumEndpoints; n++) {
649 ed = usbd_interface2endpoint_descriptor(iface, n);
650 if (ed == NULL) {
651 aprint_error_dev(self, "no endpoint descriptor "
652 "for %d (interface: %d)\n", n, sc->sc_ifaceno);
653 sc->sc_dying = true;
654 return;
655 }
656
657 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
658 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
659 intr_address = ed->bEndpointAddress;
660 intr_size = UGETW(ed->wMaxPacketSize);
661 } else
662 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
663 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
664 uca.bulkin = ed->bEndpointAddress;
665 } else
666 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
667 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
668 uca.bulkout = ed->bEndpointAddress;
669 }
670 if (uca.bulkin != -1 && uca.bulkout != -1) {
671 struct u3g_com *com;
672 if (sc->sc_ncom == __arraycount(sc->sc_com)) {
673 aprint_error_dev(self, "Need to configure "
674 "more than %zu ttys", sc->sc_ncom);
675 continue;
676 }
677 uca.portno = sc->sc_ncom++;
678 com = &sc->sc_com[uca.portno];
679 com->c_outpins = 0;
680 com->c_msr = UMSR_DSR | UMSR_CTS | UMSR_DCD;
681 com->c_open = false;
682 com->c_purging = false;
683 com->c_dev = config_found_sm_loc(self, "ucombus",
684 NULL, &uca, ucomprint, ucomsubmatch);
685 uca.bulkin = -1;
686 uca.bulkout = -1;
687 }
688 }
689
690 if (sc->sc_ncom == 0) {
691 aprint_error_dev(self, "Missing bulk in/out for interface %d\n",
692 sc->sc_ifaceno);
693 sc->sc_dying = true;
694 return;
695 }
696
697 /*
698 * If the interface has an interrupt pipe, open it immediately so
699 * that we can track input pin state changes regardless of whether
700 * the tty(4) device is open or not.
701 */
702 if (intr_address != -1) {
703 sc->sc_intr_buff = malloc(intr_size, M_USBDEV, M_WAITOK);
704 error = usbd_open_pipe_intr(iface, intr_address,
705 USBD_SHORT_XFER_OK, &sc->sc_intr_pipe, sc, sc->sc_intr_buff,
706 intr_size, u3g_intr, 100);
707 if (error) {
708 aprint_error_dev(self, "cannot open interrupt pipe "
709 "(addr %d)\n", intr_address);
710 return;
711 }
712 } else {
713 sc->sc_intr_pipe = NULL;
714 sc->sc_intr_buff = NULL;
715 }
716
717 if (!pmf_device_register(self, NULL, NULL))
718 aprint_error_dev(self, "couldn't establish power handler\n");
719 }
720
721 static int
722 u3g_detach(device_t self, int flags)
723 {
724 struct u3g_softc *sc = device_private(self);
725 int rv;
726
727 if (sc->sc_dying)
728 return 0;
729
730 pmf_device_deregister(self);
731
732 for (size_t i = 0; i < sc->sc_ncom; i++)
733 if (sc->sc_com[i].c_dev != NULL) {
734 rv = config_detach(sc->sc_com[i].c_dev, flags);
735 if (rv != 0) {
736 aprint_verbose_dev(self, "Can't deallocate "
737 "port (%d)", rv);
738 }
739 }
740
741 if (sc->sc_intr_pipe != NULL) {
742 (void) usbd_abort_pipe(sc->sc_intr_pipe);
743 (void) usbd_close_pipe(sc->sc_intr_pipe);
744 sc->sc_intr_pipe = NULL;
745 }
746 if (sc->sc_intr_buff != NULL) {
747 free(sc->sc_intr_buff, M_USBDEV);
748 sc->sc_intr_buff = NULL;
749 }
750
751 return (0);
752 }
753
754 static void
755 u3g_childdet(device_t self, device_t child)
756 {
757 struct u3g_softc *sc = device_private(self);
758
759 for (size_t i = 0; i < sc->sc_ncom; i++)
760 if (sc->sc_com[i].c_dev == child)
761 sc->sc_com[i].c_dev = NULL;
762 }
763
764 static int
765 u3g_activate(device_t self, enum devact act)
766 {
767 struct u3g_softc *sc = device_private(self);
768 int rv = 0;
769
770 switch (act) {
771 case DVACT_DEACTIVATE:
772 for (size_t i = 0; i < sc->sc_ncom; i++)
773 if (sc->sc_com[i].c_dev != NULL &&
774 config_deactivate(sc->sc_com[i].c_dev) && rv == 0)
775 rv = -1;
776 else
777 rv = 0;
778 break;
779
780 default:
781 break;
782 }
783
784 return rv;
785 }
786
787 static void
788 u3g_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
789 {
790 struct u3g_softc *sc = (struct u3g_softc *)priv;
791 u_char *buf;
792 int portno = 0; /* XXX */
793 struct u3g_com *com = &sc->sc_com[portno];
794
795 if (sc->sc_dying)
796 return;
797
798 if (status != USBD_NORMAL_COMPLETION) {
799 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
800 return;
801 usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
802 return;
803 }
804
805 buf = sc->sc_intr_buff;
806 if (buf[0] == 0xa1 && buf[1] == 0x20) {
807 u_char msr;
808
809 msr = com->c_msr & ~(UMSR_DCD | UMSR_DSR | UMSR_RI);
810
811 if (buf[8] & U3G_INPIN_DCD)
812 msr |= UMSR_DCD;
813
814 if (buf[8] & U3G_INPIN_DSR)
815 msr |= UMSR_DSR;
816
817 if (buf[8] & U3G_INPIN_RI)
818 msr |= UMSR_RI;
819
820 if (msr != com->c_msr) {
821 com->c_msr = msr;
822 if (com->c_open)
823 ucom_status_change(device_private(com->c_dev));
824 }
825 }
826 }
827
828 /*ARGSUSED*/
829 static void
830 u3g_get_status(void *arg, int portno, u_char *lsr, u_char *msr)
831 {
832 struct u3g_softc *sc = arg;
833
834 if (lsr != NULL)
835 *lsr = 0; /* LSR isn't supported */
836 if (msr != NULL)
837 *msr = sc->sc_com[portno].c_msr;
838 }
839
840 /*ARGSUSED*/
841 static void
842 u3g_set(void *arg, int portno, int reg, int onoff)
843 {
844 struct u3g_softc *sc = arg;
845 usb_device_request_t req;
846 uint16_t mask, new_state;
847 usbd_status err;
848 struct u3g_com *com = &sc->sc_com[portno];
849
850 if (sc->sc_dying)
851 return;
852
853 switch (reg) {
854 case UCOM_SET_DTR:
855 mask = U3G_OUTPIN_DTR;
856 break;
857 case UCOM_SET_RTS:
858 mask = U3G_OUTPIN_RTS;
859 break;
860 default:
861 return;
862 }
863
864 new_state = com->c_outpins & ~mask;
865 if (onoff)
866 new_state |= mask;
867
868 if (new_state == com->c_outpins)
869 return;
870
871 com->c_outpins = new_state;
872
873 req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
874 req.bRequest = U3G_SET_PIN;
875 USETW(req.wValue, new_state);
876 USETW(req.wIndex, sc->sc_ifaceno);
877 USETW(req.wLength, 0);
878
879 err = usbd_do_request(sc->sc_udev, &req, 0);
880 if (err == USBD_STALLED)
881 usbd_clear_endpoint_stall(sc->sc_udev->default_pipe);
882 }
883
884 /*ARGSUSED*/
885 static int
886 u3g_open(void *arg, int portno)
887 {
888 struct u3g_softc *sc = arg;
889 usb_device_request_t req;
890 usb_endpoint_descriptor_t *ed;
891 usb_interface_descriptor_t *id;
892 usbd_interface_handle ih;
893 usbd_status err;
894 struct u3g_com *com = &sc->sc_com[portno];
895 int i, nin;
896
897 if (sc->sc_dying)
898 return (0);
899
900 err = usbd_device2interface_handle(sc->sc_udev, sc->sc_ifaceno, &ih);
901 if (err)
902 return (EIO);
903
904 id = usbd_get_interface_descriptor(ih);
905
906 for (nin = i = 0; i < id->bNumEndpoints; i++) {
907 ed = usbd_interface2endpoint_descriptor(ih, i);
908 if (ed == NULL)
909 return (EIO);
910
911 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
912 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK &&
913 nin++ == portno) {
914 /* Issue ENDPOINT_HALT request */
915 req.bmRequestType = UT_WRITE_ENDPOINT;
916 req.bRequest = UR_CLEAR_FEATURE;
917 USETW(req.wValue, UF_ENDPOINT_HALT);
918 USETW(req.wIndex, ed->bEndpointAddress);
919 USETW(req.wLength, 0);
920 err = usbd_do_request(sc->sc_udev, &req, 0);
921 if (err)
922 return (EIO);
923 }
924 }
925
926 com->c_open = true;
927 com->c_purging = true;
928 getmicrotime(&com->c_purge_start);
929
930 return (0);
931 }
932
933 /*ARGSUSED*/
934 static void
935 u3g_close(void *arg, int portno)
936 {
937 struct u3g_softc *sc = arg;
938 struct u3g_com *com = &sc->sc_com[portno];
939
940 com->c_open = false;
941 }
942
943 /*ARGSUSED*/
944 static void
945 u3g_read(void *arg, int portno, u_char **cpp, uint32_t *ccp)
946 {
947 struct u3g_softc *sc = arg;
948 struct timeval curr_tv, diff_tv;
949 struct u3g_com *com = &sc->sc_com[portno];
950
951 /*
952 * If we're not purging input data following first open, do nothing.
953 */
954 if (com->c_purging == false)
955 return;
956
957 /*
958 * Otherwise check if the purge timeout has expired
959 */
960 getmicrotime(&curr_tv);
961 timersub(&curr_tv, &com->c_purge_start, &diff_tv);
962
963 if (diff_tv.tv_sec >= U3G_PURGE_SECS) {
964 /* Timeout expired. */
965 com->c_purging = false;
966 } else {
967 /* Still purging. Adjust the caller's byte count. */
968 *ccp = 0;
969 }
970 }
971
972 /*ARGSUSED*/
973 static void
974 u3g_write(void *arg, int portno, u_char *to, u_char *from, u_int32_t *count)
975 {
976 struct u3g_softc *sc = arg;
977 struct u3g_com *com = &sc->sc_com[portno];
978
979 /*
980 * Stop purging as soon as the first data is written to the device.
981 */
982 com->c_purging = false;
983 memcpy(to, from, *count);
984 }
985