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