Home | History | Annotate | Line # | Download | only in usb
u3g.c revision 1.30
      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 (at) 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