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