1 /* 2 * Copyright (c) 2008 AnyWi Technologies 3 * Author: Andrea Guzzo <aguzzo@anywi.com> 4 * * based on uark.c 1.1 2006/08/14 08:30:22 jsg * 5 * * parts from ubsa.c 183348 2008-09-25 12:00:56Z phk * 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 * 19 * $FreeBSD$ 20 */ 21 22 #include <sys/param.h> 23 #include <sys/systm.h> 24 #include <sys/kernel.h> 25 #include <sys/malloc.h> 26 #include <sys/module.h> 27 #include <sys/bus.h> 28 #include <sys/ioccom.h> 29 #include <sys/fcntl.h> 30 #include <sys/conf.h> 31 #include <sys/tty.h> 32 #include <sys/file.h> 33 #include <sys/selinfo.h> 34 35 #include <dev/usb/usb.h> 36 #include <dev/usb/usbdi.h> 37 #include <dev/usb/usbdivar.h> 38 #include <dev/usb/usbdi_util.h> 39 40 #include <dev/usb/ucomvar.h> 41 42 #include "usbdevs.h" 43 44 #define U3GBUFSZ 1024 45 #define U3G_MAXPORTS 4 46 47 struct u3g_softc { 48 device_t sc_ucom[U3G_MAXPORTS]; 49 device_t sc_dev; 50 usbd_device_handle sc_udev; 51 u_char sc_msr; 52 u_char sc_lsr; 53 u_char numports; 54 55 usbd_interface_handle sc_intr_iface; /* interrupt interface */ 56 #ifdef U3G_DEBUG 57 int sc_intr_number; /* interrupt number */ 58 usbd_pipe_handle sc_intr_pipe; /* interrupt pipe */ 59 u_char *sc_intr_buf; /* interrupt buffer */ 60 #endif 61 int sc_isize; 62 bool sc_pseudodev; 63 }; 64 65 struct ucom_methods u3g_methods = { 66 NULL, 67 NULL, 68 NULL, 69 NULL, 70 NULL, 71 NULL, 72 NULL, 73 NULL, 74 }; 75 76 static const struct usb_devno u3g_devs[] = { 77 /* OEM: Option N.V. */ 78 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_QUADPLUSUMTS }, 79 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_HSDPA }, 80 { USB_VENDOR_OPTIONNV, USB_PRODUCT_OPTIONNV_GTMAXHSUPA }, 81 /* OEM: Qualcomm, Inc. */ 82 { USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_CDMA_MSM }, 83 /* OEM: Huawei */ 84 { USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_MOBILE }, 85 { USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E220 }, 86 /* OEM: Novatel */ 87 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_MERLINV620 }, 88 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_ES620 }, 89 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_MC950D }, 90 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U720 }, 91 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U727 }, 92 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_MERLINU740 }, 93 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U740_2 }, 94 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_U870 }, 95 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_MERLINV620 }, 96 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_S720 }, 97 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_V740 }, 98 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_X950D }, 99 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_XU870 }, 100 { USB_VENDOR_DELL, USB_PRODUCT_DELL_W5500 }, 101 #if 0 102 { USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_MC950D_DRIVER }, 103 #endif 104 /* OEM: Merlin */ 105 { USB_VENDOR_MERLIN, USB_PRODUCT_MERLIN_V620 }, 106 107 /* OEM: Sierra Wireless: */ 108 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD580 }, 109 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD595 }, 110 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC595U }, 111 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC597E }, 112 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_C597 }, 113 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880 }, 114 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880E }, 115 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880U }, 116 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881 }, 117 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881E }, 118 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881U }, 119 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_EM5625 }, 120 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720 }, 121 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720_2 }, 122 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5725 }, 123 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MINI5725 }, 124 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD875 }, 125 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755 }, 126 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_2 }, 127 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_3 }, 128 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8765 }, 129 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC875U }, 130 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8775_2 }, 131 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8780 }, 132 { USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8781 }, 133 }; 134 135 #ifdef U3G_DEBUG 136 static void 137 u3g_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) 138 { 139 struct u3g_softc *sc = (struct u3g_softc *)priv; 140 aprint_normal_dev(sc->sc_dev, "INTERRUPT CALLBACK\n"); 141 } 142 #endif 143 144 static int 145 u3g_novatel_reinit(struct usb_attach_arg *uaa) 146 { 147 unsigned char cmd[31]; 148 usbd_interface_handle iface; 149 usb_interface_descriptor_t *id; 150 usb_endpoint_descriptor_t *ed; 151 usbd_pipe_handle pipe; 152 usbd_xfer_handle xfer; 153 int err, i; 154 155 memset(cmd, 0, sizeof(cmd)); 156 /* Byte 0..3: Command Block Wrapper (CBW) signature */ 157 cmd[0] = 0x55; 158 cmd[1] = 0x53; 159 cmd[2] = 0x42; 160 cmd[3] = 0x43; 161 /* 4..7: CBW Tag, has to unique, but only a single transfer used. */ 162 cmd[4] = 0x01; 163 /* 8..11: CBW Transfer Length, no data here */ 164 /* 12: CBW Flag: output, so 0 */ 165 /* 13: CBW Lun: 0 */ 166 /* 14: CBW Length */ 167 cmd[14] = 0x06; 168 /* Rest is the SCSI payload */ 169 /* 0: SCSI START/STOP opcode */ 170 cmd[15] = 0x1b; 171 /* 1..3 unused */ 172 /* 4 Load/Eject command */ 173 cmd[19] = 0x02; 174 /* 5: unused */ 175 176 177 /* Move the device into the configured state. */ 178 err = usbd_set_config_index(uaa->device, 0, 0); 179 if (err) { 180 aprint_error("u3g: failed to set configuration index\n"); 181 return UMATCH_NONE; 182 } 183 184 err = usbd_device2interface_handle(uaa->device, 0, &iface); 185 if (err != 0) { 186 aprint_error("u3g: failed to get interface\n"); 187 return UMATCH_NONE; 188 } 189 190 id = usbd_get_interface_descriptor(iface); 191 ed = NULL; 192 for (i = 0 ; i < id->bNumEndpoints ; i++) { 193 ed = usbd_interface2endpoint_descriptor(iface, i); 194 if (ed == NULL) 195 continue; 196 if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_OUT) 197 continue; 198 if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK) 199 break; 200 } 201 202 if (i == id->bNumEndpoints) 203 return UMATCH_NONE; 204 205 err = usbd_open_pipe(iface, ed->bEndpointAddress, USBD_EXCLUSIVE_USE, 206 &pipe); 207 if (err != 0) { 208 aprint_error("u3g: failed to open bulk transfer pipe %d\n", 209 ed->bEndpointAddress); 210 return UMATCH_NONE; 211 } 212 213 xfer = usbd_alloc_xfer(uaa->device); 214 if (xfer != NULL) { 215 usbd_setup_xfer(xfer, pipe, NULL, cmd, sizeof(cmd), 216 USBD_SYNCHRONOUS, USBD_DEFAULT_TIMEOUT, NULL); 217 218 err = usbd_transfer(xfer); 219 if (err) 220 aprint_error("u3g: transfer failed\n"); 221 usbd_free_xfer(xfer); 222 } else { 223 aprint_error("u3g: failed to allocate xfer\n"); 224 err = USBD_NOMEM; 225 } 226 227 usbd_abort_pipe(pipe); 228 usbd_close_pipe(pipe); 229 230 return (err == USBD_NORMAL_COMPLETION ? UMATCH_HIGHEST : UMATCH_NONE); 231 } 232 233 static int 234 u3g_huawei_reinit(usbd_device_handle dev) 235 { 236 /* The Huawei device presents itself as a umass device with Windows 237 * drivers on it. After installation of the driver, it reinits into a 238 * 3G serial device. 239 */ 240 usb_device_request_t req; 241 usb_config_descriptor_t *cdesc; 242 243 /* Get the config descriptor */ 244 cdesc = usbd_get_config_descriptor(dev); 245 if (cdesc == NULL) 246 return (UMATCH_NONE); 247 248 /* One iface means umass mode, more than 1 (4 usually) means 3G mode */ 249 if (cdesc->bNumInterface > 1) 250 return (UMATCH_VENDOR_PRODUCT); 251 252 req.bmRequestType = UT_WRITE_DEVICE; 253 req.bRequest = UR_SET_FEATURE; 254 USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP); 255 USETW(req.wIndex, UHF_PORT_SUSPEND); 256 USETW(req.wLength, 0); 257 258 (void) usbd_do_request(dev, &req, 0); 259 260 261 return (UMATCH_HIGHEST); /* Match to prevent umass from attaching */ 262 } 263 264 static int 265 u3g_sierra_reinit(usbd_device_handle dev) 266 { 267 /* Some Sierra devices presents themselves as a umass device with 268 * Windows drivers on it. After installation of the driver, it 269 * reinits into a * 3G serial device. 270 */ 271 usb_device_request_t req; 272 usb_config_descriptor_t *cdesc; 273 274 /* Get the config descriptor */ 275 cdesc = usbd_get_config_descriptor(dev); 276 if (cdesc == NULL) 277 return (UMATCH_NONE); 278 279 req.bmRequestType = UT_VENDOR; 280 req.bRequest = UR_SET_INTERFACE; 281 USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP); 282 USETW(req.wIndex, UHF_PORT_CONNECTION); 283 USETW(req.wLength, 0); 284 285 (void) usbd_do_request(dev, &req, 0); 286 287 return (UMATCH_HIGHEST); /* Match to prevent umass from attaching */ 288 } 289 290 static int 291 u3g_match(device_t parent, cfdata_t match, void *aux) 292 { 293 struct usb_attach_arg *uaa = aux; 294 295 if (uaa->vendor == USB_VENDOR_HUAWEI) 296 return u3g_huawei_reinit(uaa->device); 297 298 if (uaa->vendor == USB_VENDOR_NOVATEL2 && 299 uaa->product == USB_PRODUCT_NOVATEL2_MC950D_DRIVER) 300 return u3g_novatel_reinit(uaa); 301 302 if (uaa->vendor == USB_VENDOR_SIERRA && 303 uaa->product == USB_PRODUCT_SIERRA_INSTALLER) 304 return u3g_sierra_reinit(uaa->device); 305 306 if (usb_lookup(u3g_devs, uaa->vendor, uaa->product)) 307 return UMATCH_VENDOR_PRODUCT; 308 309 return UMATCH_NONE; 310 } 311 312 static void 313 u3g_attach(device_t parent, device_t self, void *aux) 314 { 315 struct u3g_softc *sc = device_private(self); 316 struct usb_attach_arg *uaa = aux; 317 usbd_device_handle dev = uaa->device; 318 usbd_interface_handle iface; 319 usb_interface_descriptor_t *id; 320 usb_endpoint_descriptor_t *ed; 321 usbd_status error; 322 int i, n; 323 usb_config_descriptor_t *cdesc; 324 325 aprint_naive("\n"); 326 aprint_normal("\n"); 327 328 if (uaa->vendor == USB_VENDOR_NOVATEL2 && 329 uaa->product == USB_PRODUCT_NOVATEL2_MC950D_DRIVER) { 330 /* About to disappear... */ 331 sc->sc_pseudodev = true; 332 return; 333 } 334 335 sc->sc_dev = self; 336 #ifdef U3G_DEBUG 337 sc->sc_intr_number = -1; 338 sc->sc_intr_pipe = NULL; 339 #endif 340 /* Move the device into the configured state. */ 341 error = usbd_set_config_index(dev, 0, 1); 342 if (error) { 343 aprint_error_dev(self, "failed to set configuration: %s\n", 344 usbd_errstr(error)); 345 return; 346 } 347 348 /* get the config descriptor */ 349 cdesc = usbd_get_config_descriptor(dev); 350 351 if (cdesc == NULL) { 352 aprint_error_dev(self, "failed to get configuration descriptor\n"); 353 return; 354 } 355 356 if (uaa->vendor == USB_VENDOR_HUAWEI && cdesc->bNumInterface > 1) { 357 /* About to disappear... */ 358 sc->sc_pseudodev = true; 359 return; 360 } 361 362 if (uaa->vendor == USB_VENDOR_SIERRA && 363 uaa->product == USB_PRODUCT_SIERRA_INSTALLER) { 364 /* About to disappear... */ 365 sc->sc_pseudodev = true; 366 return; 367 } 368 369 sc->sc_udev = dev; 370 sc->numports = (cdesc->bNumInterface <= U3G_MAXPORTS)?cdesc->bNumInterface:U3G_MAXPORTS; 371 for ( i = 0; i < sc->numports; i++ ) { 372 struct ucom_attach_args uca; 373 374 error = usbd_device2interface_handle(dev, i, &iface); 375 if (error) { 376 aprint_error_dev(self, 377 "failed to get interface, err=%s\n", 378 usbd_errstr(error)); 379 return; 380 } 381 id = usbd_get_interface_descriptor(iface); 382 383 uca.info = "Generic 3G Serial Device"; 384 uca.ibufsize = U3GBUFSZ; 385 uca.obufsize = U3GBUFSZ; 386 uca.ibufsizepad = U3GBUFSZ; 387 uca.portno = i; 388 uca.opkthdrlen = 0; 389 uca.device = dev; 390 uca.iface = iface; 391 uca.methods = &u3g_methods; 392 uca.arg = sc; 393 394 uca.bulkin = uca.bulkout = -1; 395 for (n = 0; n < id->bNumEndpoints; n++) { 396 ed = usbd_interface2endpoint_descriptor(iface, n); 397 if (ed == NULL) { 398 aprint_error_dev(self, 399 "could not read endpoint descriptor\n"); 400 return; 401 } 402 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 403 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) 404 uca.bulkin = ed->bEndpointAddress; 405 else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 406 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) 407 uca.bulkout = ed->bEndpointAddress; 408 } 409 if (uca.bulkin == -1 || uca.bulkout == -1) { 410 aprint_error_dev(self, "missing endpoint\n"); 411 return; 412 } 413 414 sc->sc_ucom[i] = config_found_sm_loc(self, "ucombus", NULL, &uca, 415 ucomprint, ucomsubmatch); 416 } 417 418 #ifdef U3G_DEBUG 419 if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) { 420 sc->sc_intr_buf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK); 421 error = usbd_open_pipe_intr(sc->sc_intr_iface, 422 sc->sc_intr_number, 423 USBD_SHORT_XFER_OK, 424 &sc->sc_intr_pipe, 425 sc, 426 sc->sc_intr_buf, 427 sc->sc_isize, 428 u3g_intr, 429 100); 430 if (error) { 431 aprint_error_dev(self, 432 "cannot open interrupt pipe (addr %d)\n", 433 sc->sc_intr_number); 434 return; 435 } 436 } 437 #endif 438 439 440 if (!pmf_device_register(self, NULL, NULL)) 441 aprint_error_dev(self, "couldn't establish power handler\n"); 442 } 443 444 static int 445 u3g_detach(device_t self, int flags) 446 { 447 struct u3g_softc *sc = device_private(self); 448 int rv = 0; 449 int i; 450 451 if (sc->sc_pseudodev) 452 return 0; 453 454 pmf_device_deregister(self); 455 456 for (i = 0; i < sc->numports; i++) { 457 if(sc->sc_ucom[i]) { 458 rv = config_detach(sc->sc_ucom[i], flags); 459 if(rv != 0) { 460 aprint_verbose_dev(self, "Can't deallocat port %d", i); 461 return rv; 462 } 463 } 464 } 465 466 #ifdef U3G_DEBUG 467 if (sc->sc_intr_pipe != NULL) { 468 int err = usbd_abort_pipe(sc->sc_intr_pipe); 469 if (err) 470 aprint_error_dev(self, 471 "abort interrupt pipe failed: %s\n", 472 usbd_errstr(err)); 473 err = usbd_close_pipe(sc->sc_intr_pipe); 474 if (err) 475 aprint_error_dev(self, 476 "close interrupt pipe failed: %s\n", 477 usbd_errstr(err)); 478 free(sc->sc_intr_buf, M_USBDEV); 479 sc->sc_intr_pipe = NULL; 480 } 481 #endif 482 483 return 0; 484 } 485 486 static void 487 u3g_childdet(device_t self, device_t child) 488 { 489 struct u3g_softc *sc = device_private(self); 490 int i; 491 492 for (i = 0; i < sc->numports; i++) { 493 if (sc->sc_ucom[i] == child) 494 sc->sc_ucom[i] = NULL; 495 } 496 } 497 498 static int 499 u3g_activate(device_t self, enum devact act) 500 { 501 struct u3g_softc *sc = device_private(self); 502 int i, rv = 0; 503 504 switch (act) { 505 case DVACT_ACTIVATE: 506 return (EOPNOTSUPP); 507 break; 508 509 case DVACT_DEACTIVATE: 510 for (i = 0; i < sc->numports; i++) { 511 if (sc->sc_ucom[i] && config_deactivate(sc->sc_ucom[i])) 512 rv = -1; 513 } 514 break; 515 } 516 return (rv); 517 } 518 519 CFATTACH_DECL2_NEW(u3g, sizeof(struct u3g_softc), u3g_match, 520 u3g_attach, u3g_detach, u3g_activate, NULL, u3g_childdet); 521