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