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