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