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