xref: /netbsd-src/sys/dev/usb/u3g.c (revision 7788a0781fe6ff2cce37368b4578a7ade0850cb1)
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@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