u3g.c revision 1.20.2.5 1 /* $NetBSD: u3g.c,v 1.20.2.5 2014/05/22 11:40:36 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.5 2014/05/22 11:40:36 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 { USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E171 },
195 /* OEM: Merlin */
196 { USB_VENDOR_MERLIN, USB_PRODUCT_MERLIN_V620 },
197 /* OEM: Novatel */
198 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_ES620 },
199 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_EU8X0D },
200 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_MC950D },
201 #if 0
202 /* These are matched in u3ginit_match() */
203 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_MC950D_DRIVER },
204 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U760_DRIVER },
205 #endif
206 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_MERLINU740 },
207 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_MERLINV620 },
208 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_S720 },
209 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U720 },
210 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U727 },
211 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U740_2 },
212 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U760 },
213 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U870 },
214 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_V740 },
215 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_X950D },
216 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_XU870 },
217 /* OEM: Option N.V. */
218 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_QUADPLUSUMTS },
219 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_HSDPA },
220 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_GTMAXHSUPA },
221 /* OEM: Qualcomm, Inc. */
222 { USB_VENDOR_QUALCOMM, USB_PRODUCT_QUALCOMM_NTT_DOCOMO_L02C_MODEM },
223
224 /* OEM: Sierra Wireless: */
225 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC595U },
226 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC597E },
227 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC875U },
228 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880 },
229 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880E },
230 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880U },
231 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881 },
232 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881E },
233 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881U },
234 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD580 },
235 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD595 },
236 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD875 },
237 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_C597 },
238 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_EM5625 },
239 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720 },
240 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720_2 },
241 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5725 },
242 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755 },
243 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_2 },
244 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_3 },
245 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8765 },
246 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8775_2 },
247 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8780 },
248 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8781 },
249 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MINI5725 },
250 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_USB305 },
251 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_250U },
252 /* Toshiba */
253 { USB_VENDOR_TOSHIBA, USB_PRODUCT_TOSHIBA_HSDPA_MODEM_EU870DT1 },
254
255 /* ZTE */
256 { USB_VENDOR_ZTE, USB_PRODUCT_ZTE_MF622 },
257 { USB_VENDOR_ZTE, USB_PRODUCT_ZTE_MF626 },
258 { USB_VENDOR_ZTE, USB_PRODUCT_ZTE_MF628 },
259 { USB_VENDOR_ZTE, USB_PRODUCT_ZTE_MF820D },
260
261 /* 4G Systems */
262 { USB_VENDOR_4GSYSTEMS, USB_PRODUCT_4GSYSTEMS_XSSTICK_P14 },
263 { USB_VENDOR_4GSYSTEMS, USB_PRODUCT_4GSYSTEMS_XSSTICK_W14 },
264 };
265
266 static int
267 send_bulkmsg(usbd_device_handle dev, void *cmd, size_t cmdlen)
268 {
269 usbd_interface_handle iface;
270 usb_interface_descriptor_t *id;
271 usb_endpoint_descriptor_t *ed;
272 usbd_pipe_handle pipe;
273 usbd_xfer_handle xfer;
274 int err, i;
275
276 /* Move the device into the configured state. */
277 err = usbd_set_config_index(dev, 0, 0);
278 if (err) {
279 aprint_error("u3ginit: failed to set config index\n");
280 return UMATCH_NONE;
281 }
282
283 err = usbd_device2interface_handle(dev, 0, &iface);
284 if (err != 0) {
285 aprint_error("u3ginit: failed to get interface\n");
286 return UMATCH_NONE;
287 }
288
289 id = usbd_get_interface_descriptor(iface);
290 ed = NULL;
291 for (i = 0 ; i < id->bNumEndpoints ; i++) {
292 ed = usbd_interface2endpoint_descriptor(iface, i);
293 if (ed == NULL)
294 continue;
295 if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_OUT)
296 continue;
297 if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK)
298 break;
299 }
300
301 if (i == id->bNumEndpoints)
302 return UMATCH_NONE;
303
304 err = usbd_open_pipe(iface, ed->bEndpointAddress,
305 USBD_EXCLUSIVE_USE, &pipe);
306 if (err != 0) {
307 aprint_error("u3ginit: failed to open bulk transfer pipe %d\n",
308 ed->bEndpointAddress);
309 return UMATCH_NONE;
310 }
311
312 xfer = usbd_alloc_xfer(dev);
313 if (xfer != NULL) {
314 usbd_setup_xfer(xfer, pipe, NULL, cmd, cmdlen,
315 USBD_SYNCHRONOUS, USBD_DEFAULT_TIMEOUT, NULL);
316
317 err = usbd_transfer(xfer);
318
319 #if 0 /* XXXpooka: at least my huawei "fails" this always, but still detaches */
320 if (err)
321 aprint_error("u3ginit: transfer failed\n");
322 #else
323 err = 0;
324 #endif
325 usbd_free_xfer(xfer);
326 } else {
327 aprint_error("u3ginit: failed to allocate xfer\n");
328 err = USBD_NOMEM;
329 }
330
331 usbd_abort_pipe(pipe);
332 usbd_close_pipe(pipe);
333
334 return (err == USBD_NORMAL_COMPLETION ? UMATCH_HIGHEST : UMATCH_NONE);
335 }
336
337 static int
338 u3g_bulk_scsi_eject(usbd_device_handle dev)
339 {
340 unsigned char cmd[31];
341
342 memset(cmd, 0, sizeof(cmd));
343 /* Byte 0..3: Command Block Wrapper (CBW) signature */
344 cmd[0] = 0x55;
345 cmd[1] = 0x53;
346 cmd[2] = 0x42;
347 cmd[3] = 0x43;
348 /* 4..7: CBW Tag, has to unique, but only a single transfer used. */
349 cmd[4] = 0x01;
350 /* 8..11: CBW Transfer Length, no data here */
351 /* 12: CBW Flag: output, so 0 */
352 /* 13: CBW Lun: 0 */
353 /* 14: CBW Length */
354 cmd[14] = 0x06;
355
356 /* Rest is the SCSI payload */
357
358 /* 0: SCSI START/STOP opcode */
359 cmd[15] = 0x1b;
360 /* 1..3 unused */
361 /* 4 Load/Eject command */
362 cmd[19] = 0x02;
363 /* 5: unused */
364
365 return send_bulkmsg(dev, cmd, sizeof(cmd));
366 }
367
368 static int
369 u3g_bulk_ata_eject(usbd_device_handle dev)
370 {
371 unsigned char cmd[31];
372
373 memset(cmd, 0, sizeof(cmd));
374 /* Byte 0..3: Command Block Wrapper (CBW) signature */
375 cmd[0] = 0x55;
376 cmd[1] = 0x53;
377 cmd[2] = 0x42;
378 cmd[3] = 0x43;
379 /* 4..7: CBW Tag, has to unique, but only a single transfer used. */
380 cmd[4] = 0x01;
381 /* 8..11: CBW Transfer Length, no data here */
382 /* 12: CBW Flag: output, so 0 */
383 /* 13: CBW Lun: 0 */
384 /* 14: CBW Length */
385 cmd[14] = 0x06;
386
387 /* Rest is the SCSI payload */
388
389 /* 0: ATA pass-through */
390 cmd[15] = 0x85;
391 /* 1..3 unused */
392 /* 4 XXX What is this command? */
393 cmd[19] = 0x24;
394 /* 5: unused */
395
396 return send_bulkmsg(dev, cmd, sizeof(cmd));
397 }
398
399 static int
400 u3g_huawei_reinit(usbd_device_handle dev)
401 {
402 /*
403 * The Huawei device presents itself as a umass device with Windows
404 * drivers on it. After installation of the driver, it reinits into a
405 * 3G serial device.
406 */
407 usb_device_request_t req;
408 usb_config_descriptor_t *cdesc;
409
410 /* Get the config descriptor */
411 cdesc = usbd_get_config_descriptor(dev);
412 if (cdesc == NULL) {
413 usb_device_descriptor_t dd;
414
415 if (usbd_get_device_desc(dev, &dd) != 0)
416 return (UMATCH_NONE);
417
418 if (dd.bNumConfigurations != 1)
419 return (UMATCH_NONE);
420
421 if (usbd_set_config_index(dev, 0, 1) != 0)
422 return (UMATCH_NONE);
423
424 cdesc = usbd_get_config_descriptor(dev);
425
426 if (cdesc == NULL)
427 return (UMATCH_NONE);
428 }
429
430 /*
431 * One iface means umass mode, more than 1 (4 usually) means 3G mode.
432 *
433 * XXX: We should check the first interface's device class just to be
434 * sure. If it's a mass storage device, then we can be fairly certain
435 * it needs a mode-switch.
436 */
437 if (cdesc->bNumInterface > 1)
438 return (UMATCH_NONE);
439
440 req.bmRequestType = UT_WRITE_DEVICE;
441 req.bRequest = UR_SET_FEATURE;
442 USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP);
443 USETW(req.wIndex, UHF_PORT_SUSPEND);
444 USETW(req.wLength, 0);
445
446 (void) usbd_do_request(dev, &req, 0);
447
448 return (UMATCH_HIGHEST); /* Prevent umass from attaching */
449 }
450
451 static int
452 u3g_huawei_k3765_reinit(usbd_device_handle dev)
453 {
454 unsigned char cmd[31];
455
456 /* magic string adapted from some webpage */
457 memset(cmd, 0, sizeof(cmd));
458 cmd[0] = 0x55;
459 cmd[1] = 0x53;
460 cmd[2] = 0x42;
461 cmd[3] = 0x43;
462 cmd[15]= 0x11;
463 cmd[16]= 0x06;
464
465 return send_bulkmsg(dev, cmd, sizeof(cmd));
466 }
467
468 static int
469 u3g_huawei_e171_reinit(usbd_device_handle dev)
470 {
471 unsigned char cmd[31];
472
473 /* magic string adapted from some webpage */
474 memset(cmd, 0, sizeof(cmd));
475 cmd[0] = 0x55;
476 cmd[1] = 0x53;
477 cmd[2] = 0x42;
478 cmd[3] = 0x43;
479 cmd[15]= 0x11;
480 cmd[16]= 0x06;
481 cmd[17]= 0x20;
482 cmd[20]= 0x01;
483
484 return send_bulkmsg(dev, cmd, sizeof(cmd));
485 }
486
487 static int
488 u3g_sierra_reinit(usbd_device_handle dev)
489 {
490 /* Some Sierra devices presents themselves as a umass device with
491 * Windows drivers on it. After installation of the driver, it
492 * reinits into a * 3G serial device.
493 */
494 usb_device_request_t req;
495
496 req.bmRequestType = UT_VENDOR;
497 req.bRequest = UR_SET_INTERFACE;
498 USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP);
499 USETW(req.wIndex, UHF_PORT_CONNECTION);
500 USETW(req.wLength, 0);
501
502 (void) usbd_do_request(dev, &req, 0);
503
504 return (UMATCH_HIGHEST); /* Match to prevent umass from attaching */
505 }
506
507 static int
508 u3g_4gsystems_reinit(usbd_device_handle dev)
509 {
510 /* magic string adapted from usb_modeswitch database */
511 static unsigned char cmd[31] = {
512 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78, 0x80, 0x00,
513 0x00, 0x00, 0x80, 0x00, 0x06, 0x06, 0xf5, 0x04, 0x02, 0x52,
514 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
515 0x00
516 };
517
518 return send_bulkmsg(dev, cmd, sizeof(cmd));
519 }
520
521 /*
522 * First personality:
523 *
524 * Claim the entire device if a mode-switch is required.
525 */
526
527 static int
528 u3ginit_match(device_t parent, cfdata_t match, void *aux)
529 {
530 struct usb_attach_arg *uaa = aux;
531
532 /*
533 * Huawei changes product when it is configured as a modem.
534 */
535 switch (uaa->vendor) {
536 case USB_VENDOR_HUAWEI:
537 if (uaa->product == USB_PRODUCT_HUAWEI_K3765)
538 return UMATCH_NONE;
539
540 switch (uaa->product) {
541 case USB_PRODUCT_HUAWEI_E1750INIT:
542 case USB_PRODUCT_HUAWEI_K3765INIT:
543 return u3g_huawei_k3765_reinit(uaa->device);
544 break;
545 case USB_PRODUCT_HUAWEI_E171INIT:
546 return u3g_huawei_e171_reinit(uaa->device);
547 break;
548 default:
549 return u3g_huawei_reinit(uaa->device);
550 break;
551 }
552 break;
553
554 case USB_VENDOR_NOVATEL2:
555 switch (uaa->product){
556 case USB_PRODUCT_NOVATEL2_MC950D_DRIVER:
557 case USB_PRODUCT_NOVATEL2_U760_DRIVER:
558 return u3g_bulk_scsi_eject(uaa->device);
559 break;
560 default:
561 break;
562 }
563 break;
564
565 case USB_VENDOR_SIERRA:
566 if (uaa->product == USB_PRODUCT_SIERRA_INSTALLER)
567 return u3g_sierra_reinit(uaa->device);
568 break;
569
570 case USB_VENDOR_QUALCOMM:
571 if (uaa->product == USB_PRODUCT_QUALCOMM_NTT_DOCOMO_L02C_STORAGE)
572 return u3g_bulk_scsi_eject(uaa->device);
573 break;
574
575 case USB_VENDOR_ZTE:
576 switch (uaa->product){
577 case USB_PRODUCT_ZTE_INSTALLER:
578 case USB_PRODUCT_ZTE_MF820D_INSTALLER:
579 (void)u3g_bulk_ata_eject(uaa->device);
580 (void)u3g_bulk_scsi_eject(uaa->device);
581 return UMATCH_HIGHEST;
582 default:
583 break;
584 }
585 break;
586
587 case USB_VENDOR_4GSYSTEMS:
588 if (uaa->product == USB_PRODUCT_4GSYSTEMS_XSSTICK_P14_INSTALLER)
589 return u3g_4gsystems_reinit(uaa->device);
590 break;
591
592 default:
593 break;
594 }
595
596 return UMATCH_NONE;
597 }
598
599 static void
600 u3ginit_attach(device_t parent, device_t self, void *aux)
601 {
602 struct usb_attach_arg *uaa = aux;
603
604 aprint_naive("\n");
605 aprint_normal(": Switching to 3G mode\n");
606
607 if (uaa->vendor == USB_VENDOR_NOVATEL2) {
608 switch (uaa->product) {
609 case USB_PRODUCT_NOVATEL2_MC950D_DRIVER:
610 case USB_PRODUCT_NOVATEL2_U760_DRIVER:
611 /* About to disappear... */
612 return;
613 break;
614 default:
615 break;
616 }
617 }
618
619 /* Move the device into the configured state. */
620 (void) usbd_set_config_index(uaa->device, 0, 1);
621 }
622
623 static int
624 u3ginit_detach(device_t self, int flags)
625 {
626
627 return (0);
628 }
629
630
631 /*
632 * Second personality:
633 *
634 * Claim only those interfaces required for 3G modem operation.
635 */
636
637 static int
638 u3g_match(device_t parent, cfdata_t match, void *aux)
639 {
640 struct usbif_attach_arg *uaa = aux;
641 usbd_interface_handle iface;
642 usb_interface_descriptor_t *id;
643 usbd_status error;
644
645 if (!usb_lookup(u3g_devs, uaa->vendor, uaa->product))
646 return (UMATCH_NONE);
647
648 error = usbd_device2interface_handle(uaa->device, uaa->ifaceno, &iface);
649 if (error) {
650 printf("u3g_match: failed to get interface, err=%s\n",
651 usbd_errstr(error));
652 return (UMATCH_NONE);
653 }
654
655 id = usbd_get_interface_descriptor(iface);
656 if (id == NULL) {
657 printf("u3g_match: failed to get interface descriptor\n");
658 return (UMATCH_NONE);
659 }
660
661 /*
662 * Huawei modems use the vendor-specific class for all interfaces,
663 * both tty and CDC NCM, which we should avoid attaching to.
664 */
665 if (uaa->vendor == USB_VENDOR_HUAWEI && id->bInterfaceSubClass == 2 &&
666 (id->bInterfaceProtocol & 0xf) == 6) /* 0x16, 0x46, 0x76 */
667 return (UMATCH_NONE);
668
669 /*
670 * 3G modems generally report vendor-specific class
671 *
672 * XXX: this may be too generalised.
673 */
674 return ((id->bInterfaceClass == UICLASS_VENDOR) ?
675 UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
676 }
677
678 static void
679 u3g_attach(device_t parent, device_t self, void *aux)
680 {
681 struct u3g_softc *sc = device_private(self);
682 struct usbif_attach_arg *uaa = aux;
683 usbd_device_handle dev = uaa->device;
684 usbd_interface_handle iface;
685 usb_interface_descriptor_t *id;
686 usb_endpoint_descriptor_t *ed;
687 struct ucom_attach_args uca;
688 usbd_status error;
689 int n, intr_address, intr_size;
690
691 aprint_naive("\n");
692 aprint_normal("\n");
693
694 sc->sc_dev = self;
695 sc->sc_dying = false;
696 sc->sc_udev = dev;
697
698 error = usbd_device2interface_handle(dev, uaa->ifaceno, &iface);
699 if (error) {
700 aprint_error_dev(self, "failed to get interface, err=%s\n",
701 usbd_errstr(error));
702 return;
703 }
704
705 id = usbd_get_interface_descriptor(iface);
706
707 uca.info = "3G Modem";
708 uca.ibufsize = U3G_BUFF_SIZE;
709 uca.obufsize = U3G_BUFF_SIZE;
710 uca.ibufsizepad = U3G_BUFF_SIZE;
711 uca.opkthdrlen = 0;
712 uca.device = dev;
713 uca.iface = iface;
714 uca.methods = &u3g_methods;
715 uca.arg = sc;
716 uca.portno = -1;
717 uca.bulkin = uca.bulkout = -1;
718
719
720 sc->sc_ifaceno = uaa->ifaceno;
721 intr_address = -1;
722 intr_size = 0;
723
724 for (n = 0; n < id->bNumEndpoints; n++) {
725 ed = usbd_interface2endpoint_descriptor(iface, n);
726 if (ed == NULL) {
727 aprint_error_dev(self, "no endpoint descriptor "
728 "for %d (interface: %d)\n", n, sc->sc_ifaceno);
729 sc->sc_dying = true;
730 return;
731 }
732
733 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
734 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
735 intr_address = ed->bEndpointAddress;
736 intr_size = UGETW(ed->wMaxPacketSize);
737 } else
738 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
739 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
740 uca.bulkin = ed->bEndpointAddress;
741 } else
742 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
743 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
744 uca.bulkout = ed->bEndpointAddress;
745 }
746 if (uca.bulkin != -1 && uca.bulkout != -1) {
747 struct u3g_com *com;
748 if (sc->sc_ncom == __arraycount(sc->sc_com)) {
749 aprint_error_dev(self, "Need to configure "
750 "more than %zu ttys", sc->sc_ncom);
751 continue;
752 }
753 uca.portno = sc->sc_ncom++;
754 com = &sc->sc_com[uca.portno];
755 com->c_outpins = 0;
756 com->c_msr = UMSR_DSR | UMSR_CTS | UMSR_DCD;
757 com->c_open = false;
758 com->c_purging = false;
759 com->c_dev = config_found_sm_loc(self, "ucombus",
760 NULL, &uca, ucomprint, ucomsubmatch);
761 uca.bulkin = -1;
762 uca.bulkout = -1;
763 }
764 }
765
766 if (sc->sc_ncom == 0) {
767 aprint_error_dev(self, "Missing bulk in/out for interface %d\n",
768 sc->sc_ifaceno);
769 sc->sc_dying = true;
770 return;
771 }
772
773 /*
774 * If the interface has an interrupt pipe, open it immediately so
775 * that we can track input pin state changes regardless of whether
776 * the tty(4) device is open or not.
777 */
778 if (intr_address != -1) {
779 sc->sc_intr_buff = malloc(intr_size, M_USBDEV, M_WAITOK);
780 error = usbd_open_pipe_intr(iface, intr_address,
781 USBD_SHORT_XFER_OK, &sc->sc_intr_pipe, sc, sc->sc_intr_buff,
782 intr_size, u3g_intr, 100);
783 if (error) {
784 aprint_error_dev(self, "cannot open interrupt pipe "
785 "(addr %d)\n", intr_address);
786 return;
787 }
788 } else {
789 sc->sc_intr_pipe = NULL;
790 sc->sc_intr_buff = NULL;
791 }
792
793 if (!pmf_device_register(self, NULL, NULL))
794 aprint_error_dev(self, "couldn't establish power handler\n");
795 }
796
797 static int
798 u3g_detach(device_t self, int flags)
799 {
800 struct u3g_softc *sc = device_private(self);
801 int rv;
802
803 if (sc->sc_dying)
804 return 0;
805
806 pmf_device_deregister(self);
807
808 for (size_t i = 0; i < sc->sc_ncom; i++)
809 if (sc->sc_com[i].c_dev != NULL) {
810 rv = config_detach(sc->sc_com[i].c_dev, flags);
811 if (rv != 0) {
812 aprint_verbose_dev(self, "Can't deallocate "
813 "port (%d)", rv);
814 }
815 }
816
817 if (sc->sc_intr_pipe != NULL) {
818 (void) usbd_abort_pipe(sc->sc_intr_pipe);
819 (void) usbd_close_pipe(sc->sc_intr_pipe);
820 sc->sc_intr_pipe = NULL;
821 }
822 if (sc->sc_intr_buff != NULL) {
823 free(sc->sc_intr_buff, M_USBDEV);
824 sc->sc_intr_buff = NULL;
825 }
826
827 return (0);
828 }
829
830 static void
831 u3g_childdet(device_t self, device_t child)
832 {
833 struct u3g_softc *sc = device_private(self);
834
835 for (size_t i = 0; i < sc->sc_ncom; i++)
836 if (sc->sc_com[i].c_dev == child)
837 sc->sc_com[i].c_dev = NULL;
838 }
839
840 static int
841 u3g_activate(device_t self, enum devact act)
842 {
843 struct u3g_softc *sc = device_private(self);
844 int rv = 0;
845
846 switch (act) {
847 case DVACT_DEACTIVATE:
848 for (size_t i = 0; i < sc->sc_ncom; i++)
849 if (sc->sc_com[i].c_dev != NULL &&
850 config_deactivate(sc->sc_com[i].c_dev) && rv == 0)
851 rv = -1;
852 else
853 rv = 0;
854 break;
855
856 default:
857 break;
858 }
859
860 return rv;
861 }
862
863 static void
864 u3g_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
865 {
866 struct u3g_softc *sc = (struct u3g_softc *)priv;
867 u_char *buf;
868 int portno = 0; /* XXX */
869 struct u3g_com *com = &sc->sc_com[portno];
870
871 if (sc->sc_dying)
872 return;
873
874 if (status != USBD_NORMAL_COMPLETION) {
875 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
876 return;
877 usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
878 return;
879 }
880
881 buf = sc->sc_intr_buff;
882 if (buf[0] == 0xa1 && buf[1] == 0x20) {
883 u_char msr;
884
885 msr = com->c_msr & ~(UMSR_DCD | UMSR_DSR | UMSR_RI);
886
887 if (buf[8] & U3G_INPIN_DCD)
888 msr |= UMSR_DCD;
889
890 if (buf[8] & U3G_INPIN_DSR)
891 msr |= UMSR_DSR;
892
893 if (buf[8] & U3G_INPIN_RI)
894 msr |= UMSR_RI;
895
896 if (msr != com->c_msr) {
897 com->c_msr = msr;
898 if (com->c_open)
899 ucom_status_change(device_private(com->c_dev));
900 }
901 }
902 }
903
904 /*ARGSUSED*/
905 static void
906 u3g_get_status(void *arg, int portno, u_char *lsr, u_char *msr)
907 {
908 struct u3g_softc *sc = arg;
909
910 if (lsr != NULL)
911 *lsr = 0; /* LSR isn't supported */
912 if (msr != NULL)
913 *msr = sc->sc_com[portno].c_msr;
914 }
915
916 /*ARGSUSED*/
917 static void
918 u3g_set(void *arg, int portno, int reg, int onoff)
919 {
920 struct u3g_softc *sc = arg;
921 usb_device_request_t req;
922 uint16_t mask, new_state;
923 usbd_status err;
924 struct u3g_com *com = &sc->sc_com[portno];
925
926 if (sc->sc_dying)
927 return;
928
929 switch (reg) {
930 case UCOM_SET_DTR:
931 mask = U3G_OUTPIN_DTR;
932 break;
933 case UCOM_SET_RTS:
934 mask = U3G_OUTPIN_RTS;
935 break;
936 default:
937 return;
938 }
939
940 new_state = com->c_outpins & ~mask;
941 if (onoff)
942 new_state |= mask;
943
944 if (new_state == com->c_outpins)
945 return;
946
947 com->c_outpins = new_state;
948
949 req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
950 req.bRequest = U3G_SET_PIN;
951 USETW(req.wValue, new_state);
952 USETW(req.wIndex, sc->sc_ifaceno);
953 USETW(req.wLength, 0);
954
955 err = usbd_do_request(sc->sc_udev, &req, 0);
956 if (err == USBD_STALLED)
957 usbd_clear_endpoint_stall(sc->sc_udev->default_pipe);
958 }
959
960 /*ARGSUSED*/
961 static int
962 u3g_open(void *arg, int portno)
963 {
964 struct u3g_softc *sc = arg;
965 usb_device_request_t req;
966 usb_endpoint_descriptor_t *ed;
967 usb_interface_descriptor_t *id;
968 usbd_interface_handle ih;
969 usbd_status err;
970 struct u3g_com *com = &sc->sc_com[portno];
971 int i, nin;
972
973 if (sc->sc_dying)
974 return (0);
975
976 err = usbd_device2interface_handle(sc->sc_udev, sc->sc_ifaceno, &ih);
977 if (err)
978 return (EIO);
979
980 id = usbd_get_interface_descriptor(ih);
981
982 for (nin = i = 0; i < id->bNumEndpoints; i++) {
983 ed = usbd_interface2endpoint_descriptor(ih, i);
984 if (ed == NULL)
985 return (EIO);
986
987 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
988 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK &&
989 nin++ == portno) {
990 /* Issue ENDPOINT_HALT request */
991 req.bmRequestType = UT_WRITE_ENDPOINT;
992 req.bRequest = UR_CLEAR_FEATURE;
993 USETW(req.wValue, UF_ENDPOINT_HALT);
994 USETW(req.wIndex, ed->bEndpointAddress);
995 USETW(req.wLength, 0);
996 err = usbd_do_request(sc->sc_udev, &req, 0);
997 if (err)
998 return (EIO);
999 }
1000 }
1001
1002 com->c_open = true;
1003 com->c_purging = true;
1004 getmicrotime(&com->c_purge_start);
1005
1006 return (0);
1007 }
1008
1009 /*ARGSUSED*/
1010 static void
1011 u3g_close(void *arg, int portno)
1012 {
1013 struct u3g_softc *sc = arg;
1014 struct u3g_com *com = &sc->sc_com[portno];
1015
1016 com->c_open = false;
1017 }
1018
1019 /*ARGSUSED*/
1020 static void
1021 u3g_read(void *arg, int portno, u_char **cpp, uint32_t *ccp)
1022 {
1023 struct u3g_softc *sc = arg;
1024 struct timeval curr_tv, diff_tv;
1025 struct u3g_com *com = &sc->sc_com[portno];
1026
1027 /*
1028 * If we're not purging input data following first open, do nothing.
1029 */
1030 if (com->c_purging == false)
1031 return;
1032
1033 /*
1034 * Otherwise check if the purge timeout has expired
1035 */
1036 getmicrotime(&curr_tv);
1037 timersub(&curr_tv, &com->c_purge_start, &diff_tv);
1038
1039 if (diff_tv.tv_sec >= U3G_PURGE_SECS) {
1040 /* Timeout expired. */
1041 com->c_purging = false;
1042 } else {
1043 /* Still purging. Adjust the caller's byte count. */
1044 *ccp = 0;
1045 }
1046 }
1047
1048 /*ARGSUSED*/
1049 static void
1050 u3g_write(void *arg, int portno, u_char *to, u_char *from, u_int32_t *count)
1051 {
1052 struct u3g_softc *sc = arg;
1053 struct u3g_com *com = &sc->sc_com[portno];
1054
1055 /*
1056 * Stop purging as soon as the first data is written to the device.
1057 */
1058 com->c_purging = false;
1059 memcpy(to, from, *count);
1060 }
1061