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