242 .type = UE_CONTROL, 243 .endpoint = 0x00, /* Control pipe */ 244 .direction = UE_DIR_ANY, 245 .mh.bufsize = sizeof(struct usb2_device_request), 246 .mh.callback = &uplcom_intr_clear_stall_callback, 247 .mh.timeout = 1000, /* 1 second */ 248 .mh.interval = 50, /* 50ms */ 249 .if_index = 1, 250 }, 251}; 252 253struct usb2_com_callback uplcom_callback = { 254 .usb2_com_cfg_get_status = &uplcom_cfg_get_status, 255 .usb2_com_cfg_set_dtr = &uplcom_cfg_set_dtr, 256 .usb2_com_cfg_set_rts = &uplcom_cfg_set_rts, 257 .usb2_com_cfg_set_break = &uplcom_cfg_set_break, 258 .usb2_com_cfg_param = &uplcom_cfg_param, 259 .usb2_com_pre_param = &uplcom_pre_param, 260 .usb2_com_start_read = &uplcom_start_read, 261 .usb2_com_stop_read = &uplcom_stop_read, 262 .usb2_com_start_write = &uplcom_start_write, 263 .usb2_com_stop_write = &uplcom_stop_write, 264}; 265 266#define USB_UPL(v,p,rl,rh,t) \ 267 USB_VENDOR(v), USB_PRODUCT(p), USB_DEV_BCD_GTEQ(rl), \ 268 USB_DEV_BCD_LTEQ(rh), USB_DRIVER_INFO(t) 269 270static const struct usb2_device_id uplcom_devs[] = { 271 /* Belkin F5U257 */ 272 {USB_UPL(USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U257, 0, 0xFFFF, TYPE_PL2303X)}, 273 /* I/O DATA USB-RSAQ */ 274 {USB_UPL(USB_VENDOR_IODATA, USB_PRODUCT_IODATA_USBRSAQ, 0, 0xFFFF, TYPE_PL2303)}, 275 /* I/O DATA USB-RSAQ2 */ 276 {USB_UPL(USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_RSAQ2, 0, 0xFFFF, TYPE_PL2303)}, 277 /* I/O DATA USB-RSAQ3 */ 278 {USB_UPL(USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_RSAQ3, 0, 0xFFFF, TYPE_PL2303X)}, 279 /* PLANEX USB-RS232 URS-03 */ 280 {USB_UPL(USB_VENDOR_ATEN, USB_PRODUCT_ATEN_UC232A, 0, 0xFFFF, TYPE_PL2303)}, 281 /* TrendNet TU-S9 */ 282 {USB_UPL(USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2303, 0x0400, 0xFFFF, TYPE_PL2303X)}, 283 /* ST Lab USB-SERIAL-4 */ 284 {USB_UPL(USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2303, 0x0300, 0x03FF, TYPE_PL2303X)}, 285 /* IOGEAR/ATEN UC-232A (also ST Lab USB-SERIAL-1) */ 286 {USB_UPL(USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2303, 0, 0x02FF, TYPE_PL2303)}, 287 /* TDK USB-PHS Adapter UHA6400 */ 288 {USB_UPL(USB_VENDOR_TDK, USB_PRODUCT_TDK_UHA6400, 0, 0xFFFF, TYPE_PL2303)}, 289 /* RATOC REX-USB60 */ 290 {USB_UPL(USB_VENDOR_RATOC, USB_PRODUCT_RATOC_REXUSB60, 0, 0xFFFF, TYPE_PL2303)}, 291 /* ELECOM UC-SGT */ 292 {USB_UPL(USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_UCSGT, 0, 0xFFFF, TYPE_PL2303)}, 293 {USB_UPL(USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_UCSGT0, 0, 0xFFFF, TYPE_PL2303)}, 294 /* Sagem USB-Serial Controller */ 295 {USB_UPL(USB_VENDOR_SAGEM, USB_PRODUCT_SAGEM_USBSERIAL, 0, 0xFFFF, TYPE_PL2303X)}, 296 /* Sony Ericsson USB Cable */ 297 {USB_UPL(USB_VENDOR_SONYERICSSON, USB_PRODUCT_SONYERICSSON_DCU10, 0, 0xFFFF, TYPE_PL2303)}, 298 /* SOURCENEXT KeikaiDenwa 8 */ 299 {USB_UPL(USB_VENDOR_SOURCENEXT, USB_PRODUCT_SOURCENEXT_KEIKAI8, 0, 0xFFFF, TYPE_PL2303)}, 300 /* SOURCENEXT KeikaiDenwa 8 with charger */ 301 {USB_UPL(USB_VENDOR_SOURCENEXT, USB_PRODUCT_SOURCENEXT_KEIKAI8_CHG, 0, 0, TYPE_PL2303)}, 302 /* HAL Corporation Crossam2+USB */ 303 {USB_UPL(USB_VENDOR_HAL, USB_PRODUCT_HAL_IMR001, 0, 0xFFFF, TYPE_PL2303)}, 304 /* Sitecom USB to Serial */ 305 {USB_UPL(USB_VENDOR_SITECOM, USB_PRODUCT_SITECOM_SERIAL, 0, 0xFFFF, TYPE_PL2303)}, 306 /* Tripp-Lite U209-000-R */ 307 {USB_UPL(USB_VENDOR_TRIPPLITE, USB_PRODUCT_TRIPPLITE_U209, 0, 0xFFFF, TYPE_PL2303X)}, 308 {USB_UPL(USB_VENDOR_RADIOSHACK, USB_PRODUCT_RADIOSHACK_USBCABLE, 0, 0xFFFF, TYPE_PL2303)}, 309 /* Prolific Pharos */ 310 {USB_UPL(USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PHAROS, 0, 0xFFFF, TYPE_PL2303)}, 311 /* Willcom W-SIM */ 312 {USB_UPL(USB_VENDOR_PROLIFIC2, USB_PRODUCT_PROLIFIC2_WSIM, 0, 0xFFFF, TYPE_PL2303X)}, 313}; 314 315static device_method_t uplcom_methods[] = { 316 DEVMETHOD(device_probe, uplcom_probe), 317 DEVMETHOD(device_attach, uplcom_attach), 318 DEVMETHOD(device_detach, uplcom_detach), 319 {0, 0} 320}; 321 322static devclass_t uplcom_devclass; 323 324static driver_t uplcom_driver = { 325 .name = "uplcom", 326 .methods = uplcom_methods, 327 .size = sizeof(struct uplcom_softc), 328}; 329 330DRIVER_MODULE(uplcom, ushub, uplcom_driver, uplcom_devclass, NULL, 0); 331MODULE_DEPEND(uplcom, usb2_serial, 1, 1, 1); 332MODULE_DEPEND(uplcom, usb2_core, 1, 1, 1); 333MODULE_VERSION(uplcom, UPLCOM_MODVER); 334 335static int 336uplcom_probe(device_t dev) 337{ 338 struct usb2_attach_arg *uaa = device_get_ivars(dev); 339 340 DPRINTFN(11, "\n"); 341 342 if (uaa->usb2_mode != USB_MODE_HOST) { 343 return (ENXIO); 344 } 345 if (uaa->info.bConfigIndex != UPLCOM_CONFIG_INDEX) { 346 return (ENXIO); 347 } 348 if (uaa->info.bIfaceIndex != UPLCOM_IFACE_INDEX) { 349 return (ENXIO); 350 } 351 return (usb2_lookup_id_by_uaa(uplcom_devs, sizeof(uplcom_devs), uaa)); 352} 353 354static int 355uplcom_attach(device_t dev) 356{ 357 struct usb2_attach_arg *uaa = device_get_ivars(dev); 358 struct uplcom_softc *sc = device_get_softc(dev); 359 struct usb2_interface *iface; 360 struct usb2_interface_descriptor *id; 361 int error; 362 363 DPRINTFN(11, "\n"); 364 365 if (sc == NULL) { 366 return (ENOMEM); 367 } 368 device_set_usb2_desc(dev); 369 370 DPRINTF("sc = %p\n", sc); 371 372 sc->sc_chiptype = USB_GET_DRIVER_INFO(uaa); 373 sc->sc_udev = uaa->device; 374 375 DPRINTF("chiptype: %s\n", 376 (sc->sc_chiptype == TYPE_PL2303X) ? 377 "2303X" : "2303"); 378 379 /* 380 * USB-RSAQ1 has two interface 381 * 382 * USB-RSAQ1 | USB-RSAQ2 383 * -----------------+----------------- 384 * Interface 0 |Interface 0 385 * Interrupt(0x81) | Interrupt(0x81) 386 * -----------------+ BulkIN(0x02) 387 * Interface 1 | BulkOUT(0x83) 388 * BulkIN(0x02) | 389 * BulkOUT(0x83) | 390 */ 391 392 sc->sc_ctrl_iface_no = uaa->info.bIfaceNum; 393 sc->sc_iface_index[1] = UPLCOM_IFACE_INDEX; 394 395 iface = usb2_get_iface(uaa->device, UPLCOM_SECOND_IFACE_INDEX); 396 if (iface) { 397 id = usb2_get_interface_descriptor(iface); 398 if (id == NULL) { 399 device_printf(dev, "no interface descriptor (2)!\n"); 400 goto detach; 401 } 402 sc->sc_data_iface_no = id->bInterfaceNumber; 403 sc->sc_iface_index[0] = UPLCOM_SECOND_IFACE_INDEX; 404 usb2_set_parent_iface(uaa->device, 405 UPLCOM_SECOND_IFACE_INDEX, uaa->info.bIfaceIndex); 406 } else { 407 sc->sc_data_iface_no = sc->sc_ctrl_iface_no; 408 sc->sc_iface_index[0] = UPLCOM_IFACE_INDEX; 409 } 410 411 error = usb2_transfer_setup(uaa->device, 412 sc->sc_iface_index, sc->sc_xfer, uplcom_config_data, 413 UPLCOM_N_TRANSFER, sc, &Giant); 414 if (error) { 415 DPRINTF("one or more missing USB endpoints, " 416 "error=%s\n", usb2_errstr(error)); 417 goto detach; 418 } 419 error = uplcom_reset(sc, uaa->device); 420 if (error) { 421 device_printf(dev, "reset failed, error=%s\n", 422 usb2_errstr(error)); 423 goto detach; 424 } 425 /* clear stall at first run */ 426 sc->sc_flag |= (UPLCOM_FLAG_READ_STALL | 427 UPLCOM_FLAG_WRITE_STALL); 428 429 error = usb2_com_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, 430 &uplcom_callback, &Giant); 431 if (error) { 432 goto detach; 433 } 434 /* 435 * do the initialization during attach so that the system does not 436 * sleep during open: 437 */ 438 if (sc->sc_chiptype == TYPE_PL2303X) { 439 if (uplcom_pl2303x_init(uaa->device)) { 440 device_printf(dev, "init failed!\n"); 441 goto detach; 442 } 443 } 444 return (0); 445 446detach: 447 uplcom_detach(dev); 448 return (ENXIO); 449} 450 451static int 452uplcom_detach(device_t dev) 453{ 454 struct uplcom_softc *sc = device_get_softc(dev); 455 456 DPRINTF("sc=%p\n", sc); 457 458 usb2_com_detach(&sc->sc_super_ucom, &sc->sc_ucom, 1); 459 460 usb2_transfer_unsetup(sc->sc_xfer, UPLCOM_N_TRANSFER); 461 462 return (0); 463} 464 465static usb2_error_t 466uplcom_reset(struct uplcom_softc *sc, struct usb2_device *udev) 467{ 468 struct usb2_device_request req; 469 470 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 471 req.bRequest = UPLCOM_SET_REQUEST; 472 USETW(req.wValue, 0); 473 req.wIndex[0] = sc->sc_data_iface_no; 474 req.wIndex[1] = 0; 475 USETW(req.wLength, 0); 476 477 return (usb2_do_request(udev, &Giant, &req, NULL)); 478} 479 480struct pl2303x_init { 481 uint8_t req_type; 482 uint8_t request; 483 uint16_t value; 484 uint16_t index; 485 uint16_t length; 486}; 487 488static const struct pl2303x_init pl2303x[] = { 489 {UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 1}, 490 {UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x0404, 0, 0}, 491 {UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 1}, 492 {UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8383, 0, 1}, 493 {UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 1}, 494 {UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x0404, 1, 0}, 495 {UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 1}, 496 {UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8383, 0, 1}, 497 {UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0, 1, 0}, 498 {UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 1, 0, 0}, 499 {UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 2, 0x44, 0}, 500 {UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 8, 0, 0}, 501 {UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 9, 0, 0}, 502}; 503 504#define N_PL2302X_INIT (sizeof(pl2303x)/sizeof(pl2303x[0])) 505 506static int 507uplcom_pl2303x_init(struct usb2_device *udev) 508{ 509 struct usb2_device_request req; 510 usb2_error_t err; 511 uint8_t buf[4]; 512 uint8_t i; 513 514 for (i = 0; i != N_PL2302X_INIT; i++) { 515 req.bmRequestType = pl2303x[i].req_type; 516 req.bRequest = pl2303x[i].request; 517 USETW(req.wValue, pl2303x[i].value); 518 USETW(req.wIndex, pl2303x[i].index); 519 USETW(req.wLength, pl2303x[i].length); 520 521 err = usb2_do_request(udev, &Giant, &req, buf); 522 if (err) { 523 DPRINTF("error=%s\n", usb2_errstr(err)); 524 return (EIO); 525 } 526 } 527 return (0); 528} 529 530static void 531uplcom_cfg_set_dtr(struct usb2_com_softc *ucom, uint8_t onoff) 532{ 533 struct uplcom_softc *sc = ucom->sc_parent; 534 struct usb2_device_request req; 535 536 DPRINTF("onoff = %d\n", onoff); 537 538 if (onoff) 539 sc->sc_line |= UCDC_LINE_DTR; 540 else 541 sc->sc_line &= ~UCDC_LINE_DTR; 542 543 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 544 req.bRequest = UCDC_SET_CONTROL_LINE_STATE; 545 USETW(req.wValue, sc->sc_line); 546 req.wIndex[0] = sc->sc_data_iface_no; 547 req.wIndex[1] = 0; 548 USETW(req.wLength, 0); 549 550 uplcom_cfg_do_request(sc, &req, NULL); 551} 552 553static void 554uplcom_cfg_set_rts(struct usb2_com_softc *ucom, uint8_t onoff) 555{ 556 struct uplcom_softc *sc = ucom->sc_parent; 557 struct usb2_device_request req; 558 559 DPRINTF("onoff = %d\n", onoff); 560 561 if (onoff) 562 sc->sc_line |= UCDC_LINE_RTS; 563 else 564 sc->sc_line &= ~UCDC_LINE_RTS; 565 566 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 567 req.bRequest = UCDC_SET_CONTROL_LINE_STATE; 568 USETW(req.wValue, sc->sc_line); 569 req.wIndex[0] = sc->sc_data_iface_no; 570 req.wIndex[1] = 0; 571 USETW(req.wLength, 0); 572 573 uplcom_cfg_do_request(sc, &req, NULL); 574} 575 576static void 577uplcom_cfg_set_break(struct usb2_com_softc *ucom, uint8_t onoff) 578{ 579 struct uplcom_softc *sc = ucom->sc_parent; 580 struct usb2_device_request req; 581 uint16_t temp; 582 583 DPRINTF("onoff = %d\n", onoff); 584 585 temp = (onoff ? UCDC_BREAK_ON : UCDC_BREAK_OFF); 586 587 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 588 req.bRequest = UCDC_SEND_BREAK; 589 USETW(req.wValue, temp); 590 req.wIndex[0] = sc->sc_data_iface_no; 591 req.wIndex[1] = 0; 592 USETW(req.wLength, 0); 593 594 uplcom_cfg_do_request(sc, &req, NULL); 595} 596 597static const int32_t uplcom_rates[] = { 598 75, 150, 300, 600, 1200, 1800, 2400, 3600, 4800, 7200, 9600, 14400, 599 19200, 28800, 38400, 57600, 115200, 600 /* 601 * Higher speeds are probably possible. PL2303X supports up to 602 * 6Mb and can set any rate 603 */ 604 230400, 460800, 614400, 921600, 1228800 605}; 606 607#define N_UPLCOM_RATES (sizeof(uplcom_rates)/sizeof(uplcom_rates[0])) 608 609static int 610uplcom_pre_param(struct usb2_com_softc *ucom, struct termios *t) 611{ 612 uint8_t i; 613 614 DPRINTF("\n"); 615 616 /* check requested baud rate */ 617 618 for (i = 0;; i++) { 619 620 if (i != N_UPLCOM_RATES) { 621 if (uplcom_rates[i] == t->c_ospeed) { 622 break; 623 } 624 } else { 625 DPRINTF("invalid baud rate (%d)\n", t->c_ospeed); 626 return (EIO); 627 } 628 } 629 630 return (0); 631} 632 633static void 634uplcom_cfg_param(struct usb2_com_softc *ucom, struct termios *t) 635{ 636 struct uplcom_softc *sc = ucom->sc_parent; 637 struct usb2_cdc_line_state ls; 638 struct usb2_device_request req; 639 640 DPRINTF("sc = %p\n", sc); 641 642 bzero(&ls, sizeof(ls)); 643 644 USETDW(ls.dwDTERate, t->c_ospeed); 645 646 if (t->c_cflag & CSTOPB) { 647 ls.bCharFormat = UCDC_STOP_BIT_2; 648 } else { 649 ls.bCharFormat = UCDC_STOP_BIT_1; 650 } 651 652 if (t->c_cflag & PARENB) { 653 if (t->c_cflag & PARODD) { 654 ls.bParityType = UCDC_PARITY_ODD; 655 } else { 656 ls.bParityType = UCDC_PARITY_EVEN; 657 } 658 } else { 659 ls.bParityType = UCDC_PARITY_NONE; 660 } 661 662 switch (t->c_cflag & CSIZE) { 663 case CS5: 664 ls.bDataBits = 5; 665 break; 666 case CS6: 667 ls.bDataBits = 6; 668 break; 669 case CS7: 670 ls.bDataBits = 7; 671 break; 672 case CS8: 673 ls.bDataBits = 8; 674 break; 675 } 676 677 DPRINTF("rate=%d fmt=%d parity=%d bits=%d\n", 678 UGETDW(ls.dwDTERate), ls.bCharFormat, 679 ls.bParityType, ls.bDataBits); 680 681 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 682 req.bRequest = UCDC_SET_LINE_CODING; 683 USETW(req.wValue, 0); 684 req.wIndex[0] = sc->sc_data_iface_no; 685 req.wIndex[1] = 0; 686 USETW(req.wLength, UCDC_LINE_STATE_LENGTH); 687 688 uplcom_cfg_do_request(sc, &req, &ls); 689 690 if (t->c_cflag & CRTSCTS) { 691 692 DPRINTF("crtscts = on\n"); 693 694 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 695 req.bRequest = UPLCOM_SET_REQUEST; 696 USETW(req.wValue, 0); 697 if (sc->sc_chiptype == TYPE_PL2303X) 698 USETW(req.wIndex, UPLCOM_SET_CRTSCTS_PL2303X); 699 else 700 USETW(req.wIndex, UPLCOM_SET_CRTSCTS); 701 USETW(req.wLength, 0); 702 703 uplcom_cfg_do_request(sc, &req, NULL); 704 } else { 705 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 706 req.bRequest = UPLCOM_SET_REQUEST; 707 USETW(req.wValue, 0); 708 USETW(req.wIndex, 0); 709 USETW(req.wLength, 0); 710 uplcom_cfg_do_request(sc, &req, NULL); 711 } 712} 713 714static void 715uplcom_start_read(struct usb2_com_softc *ucom) 716{ 717 struct uplcom_softc *sc = ucom->sc_parent; 718 719 /* start interrupt endpoint */
| 251 .type = UE_CONTROL, 252 .endpoint = 0x00, /* Control pipe */ 253 .direction = UE_DIR_ANY, 254 .mh.bufsize = sizeof(struct usb2_device_request), 255 .mh.callback = &uplcom_intr_clear_stall_callback, 256 .mh.timeout = 1000, /* 1 second */ 257 .mh.interval = 50, /* 50ms */ 258 .if_index = 1, 259 }, 260}; 261 262struct usb2_com_callback uplcom_callback = { 263 .usb2_com_cfg_get_status = &uplcom_cfg_get_status, 264 .usb2_com_cfg_set_dtr = &uplcom_cfg_set_dtr, 265 .usb2_com_cfg_set_rts = &uplcom_cfg_set_rts, 266 .usb2_com_cfg_set_break = &uplcom_cfg_set_break, 267 .usb2_com_cfg_param = &uplcom_cfg_param, 268 .usb2_com_pre_param = &uplcom_pre_param, 269 .usb2_com_start_read = &uplcom_start_read, 270 .usb2_com_stop_read = &uplcom_stop_read, 271 .usb2_com_start_write = &uplcom_start_write, 272 .usb2_com_stop_write = &uplcom_stop_write, 273}; 274 275#define USB_UPL(v,p,rl,rh,t) \ 276 USB_VENDOR(v), USB_PRODUCT(p), USB_DEV_BCD_GTEQ(rl), \ 277 USB_DEV_BCD_LTEQ(rh), USB_DRIVER_INFO(t) 278 279static const struct usb2_device_id uplcom_devs[] = { 280 /* Belkin F5U257 */ 281 {USB_UPL(USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U257, 0, 0xFFFF, TYPE_PL2303X)}, 282 /* I/O DATA USB-RSAQ */ 283 {USB_UPL(USB_VENDOR_IODATA, USB_PRODUCT_IODATA_USBRSAQ, 0, 0xFFFF, TYPE_PL2303)}, 284 /* I/O DATA USB-RSAQ2 */ 285 {USB_UPL(USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_RSAQ2, 0, 0xFFFF, TYPE_PL2303)}, 286 /* I/O DATA USB-RSAQ3 */ 287 {USB_UPL(USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_RSAQ3, 0, 0xFFFF, TYPE_PL2303X)}, 288 /* PLANEX USB-RS232 URS-03 */ 289 {USB_UPL(USB_VENDOR_ATEN, USB_PRODUCT_ATEN_UC232A, 0, 0xFFFF, TYPE_PL2303)}, 290 /* TrendNet TU-S9 */ 291 {USB_UPL(USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2303, 0x0400, 0xFFFF, TYPE_PL2303X)}, 292 /* ST Lab USB-SERIAL-4 */ 293 {USB_UPL(USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2303, 0x0300, 0x03FF, TYPE_PL2303X)}, 294 /* IOGEAR/ATEN UC-232A (also ST Lab USB-SERIAL-1) */ 295 {USB_UPL(USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2303, 0, 0x02FF, TYPE_PL2303)}, 296 /* TDK USB-PHS Adapter UHA6400 */ 297 {USB_UPL(USB_VENDOR_TDK, USB_PRODUCT_TDK_UHA6400, 0, 0xFFFF, TYPE_PL2303)}, 298 /* RATOC REX-USB60 */ 299 {USB_UPL(USB_VENDOR_RATOC, USB_PRODUCT_RATOC_REXUSB60, 0, 0xFFFF, TYPE_PL2303)}, 300 /* ELECOM UC-SGT */ 301 {USB_UPL(USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_UCSGT, 0, 0xFFFF, TYPE_PL2303)}, 302 {USB_UPL(USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_UCSGT0, 0, 0xFFFF, TYPE_PL2303)}, 303 /* Sagem USB-Serial Controller */ 304 {USB_UPL(USB_VENDOR_SAGEM, USB_PRODUCT_SAGEM_USBSERIAL, 0, 0xFFFF, TYPE_PL2303X)}, 305 /* Sony Ericsson USB Cable */ 306 {USB_UPL(USB_VENDOR_SONYERICSSON, USB_PRODUCT_SONYERICSSON_DCU10, 0, 0xFFFF, TYPE_PL2303)}, 307 /* SOURCENEXT KeikaiDenwa 8 */ 308 {USB_UPL(USB_VENDOR_SOURCENEXT, USB_PRODUCT_SOURCENEXT_KEIKAI8, 0, 0xFFFF, TYPE_PL2303)}, 309 /* SOURCENEXT KeikaiDenwa 8 with charger */ 310 {USB_UPL(USB_VENDOR_SOURCENEXT, USB_PRODUCT_SOURCENEXT_KEIKAI8_CHG, 0, 0, TYPE_PL2303)}, 311 /* HAL Corporation Crossam2+USB */ 312 {USB_UPL(USB_VENDOR_HAL, USB_PRODUCT_HAL_IMR001, 0, 0xFFFF, TYPE_PL2303)}, 313 /* Sitecom USB to Serial */ 314 {USB_UPL(USB_VENDOR_SITECOM, USB_PRODUCT_SITECOM_SERIAL, 0, 0xFFFF, TYPE_PL2303)}, 315 /* Tripp-Lite U209-000-R */ 316 {USB_UPL(USB_VENDOR_TRIPPLITE, USB_PRODUCT_TRIPPLITE_U209, 0, 0xFFFF, TYPE_PL2303X)}, 317 {USB_UPL(USB_VENDOR_RADIOSHACK, USB_PRODUCT_RADIOSHACK_USBCABLE, 0, 0xFFFF, TYPE_PL2303)}, 318 /* Prolific Pharos */ 319 {USB_UPL(USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PHAROS, 0, 0xFFFF, TYPE_PL2303)}, 320 /* Willcom W-SIM */ 321 {USB_UPL(USB_VENDOR_PROLIFIC2, USB_PRODUCT_PROLIFIC2_WSIM, 0, 0xFFFF, TYPE_PL2303X)}, 322}; 323 324static device_method_t uplcom_methods[] = { 325 DEVMETHOD(device_probe, uplcom_probe), 326 DEVMETHOD(device_attach, uplcom_attach), 327 DEVMETHOD(device_detach, uplcom_detach), 328 {0, 0} 329}; 330 331static devclass_t uplcom_devclass; 332 333static driver_t uplcom_driver = { 334 .name = "uplcom", 335 .methods = uplcom_methods, 336 .size = sizeof(struct uplcom_softc), 337}; 338 339DRIVER_MODULE(uplcom, ushub, uplcom_driver, uplcom_devclass, NULL, 0); 340MODULE_DEPEND(uplcom, usb2_serial, 1, 1, 1); 341MODULE_DEPEND(uplcom, usb2_core, 1, 1, 1); 342MODULE_VERSION(uplcom, UPLCOM_MODVER); 343 344static int 345uplcom_probe(device_t dev) 346{ 347 struct usb2_attach_arg *uaa = device_get_ivars(dev); 348 349 DPRINTFN(11, "\n"); 350 351 if (uaa->usb2_mode != USB_MODE_HOST) { 352 return (ENXIO); 353 } 354 if (uaa->info.bConfigIndex != UPLCOM_CONFIG_INDEX) { 355 return (ENXIO); 356 } 357 if (uaa->info.bIfaceIndex != UPLCOM_IFACE_INDEX) { 358 return (ENXIO); 359 } 360 return (usb2_lookup_id_by_uaa(uplcom_devs, sizeof(uplcom_devs), uaa)); 361} 362 363static int 364uplcom_attach(device_t dev) 365{ 366 struct usb2_attach_arg *uaa = device_get_ivars(dev); 367 struct uplcom_softc *sc = device_get_softc(dev); 368 struct usb2_interface *iface; 369 struct usb2_interface_descriptor *id; 370 int error; 371 372 DPRINTFN(11, "\n"); 373 374 if (sc == NULL) { 375 return (ENOMEM); 376 } 377 device_set_usb2_desc(dev); 378 379 DPRINTF("sc = %p\n", sc); 380 381 sc->sc_chiptype = USB_GET_DRIVER_INFO(uaa); 382 sc->sc_udev = uaa->device; 383 384 DPRINTF("chiptype: %s\n", 385 (sc->sc_chiptype == TYPE_PL2303X) ? 386 "2303X" : "2303"); 387 388 /* 389 * USB-RSAQ1 has two interface 390 * 391 * USB-RSAQ1 | USB-RSAQ2 392 * -----------------+----------------- 393 * Interface 0 |Interface 0 394 * Interrupt(0x81) | Interrupt(0x81) 395 * -----------------+ BulkIN(0x02) 396 * Interface 1 | BulkOUT(0x83) 397 * BulkIN(0x02) | 398 * BulkOUT(0x83) | 399 */ 400 401 sc->sc_ctrl_iface_no = uaa->info.bIfaceNum; 402 sc->sc_iface_index[1] = UPLCOM_IFACE_INDEX; 403 404 iface = usb2_get_iface(uaa->device, UPLCOM_SECOND_IFACE_INDEX); 405 if (iface) { 406 id = usb2_get_interface_descriptor(iface); 407 if (id == NULL) { 408 device_printf(dev, "no interface descriptor (2)!\n"); 409 goto detach; 410 } 411 sc->sc_data_iface_no = id->bInterfaceNumber; 412 sc->sc_iface_index[0] = UPLCOM_SECOND_IFACE_INDEX; 413 usb2_set_parent_iface(uaa->device, 414 UPLCOM_SECOND_IFACE_INDEX, uaa->info.bIfaceIndex); 415 } else { 416 sc->sc_data_iface_no = sc->sc_ctrl_iface_no; 417 sc->sc_iface_index[0] = UPLCOM_IFACE_INDEX; 418 } 419 420 error = usb2_transfer_setup(uaa->device, 421 sc->sc_iface_index, sc->sc_xfer, uplcom_config_data, 422 UPLCOM_N_TRANSFER, sc, &Giant); 423 if (error) { 424 DPRINTF("one or more missing USB endpoints, " 425 "error=%s\n", usb2_errstr(error)); 426 goto detach; 427 } 428 error = uplcom_reset(sc, uaa->device); 429 if (error) { 430 device_printf(dev, "reset failed, error=%s\n", 431 usb2_errstr(error)); 432 goto detach; 433 } 434 /* clear stall at first run */ 435 sc->sc_flag |= (UPLCOM_FLAG_READ_STALL | 436 UPLCOM_FLAG_WRITE_STALL); 437 438 error = usb2_com_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, 439 &uplcom_callback, &Giant); 440 if (error) { 441 goto detach; 442 } 443 /* 444 * do the initialization during attach so that the system does not 445 * sleep during open: 446 */ 447 if (sc->sc_chiptype == TYPE_PL2303X) { 448 if (uplcom_pl2303x_init(uaa->device)) { 449 device_printf(dev, "init failed!\n"); 450 goto detach; 451 } 452 } 453 return (0); 454 455detach: 456 uplcom_detach(dev); 457 return (ENXIO); 458} 459 460static int 461uplcom_detach(device_t dev) 462{ 463 struct uplcom_softc *sc = device_get_softc(dev); 464 465 DPRINTF("sc=%p\n", sc); 466 467 usb2_com_detach(&sc->sc_super_ucom, &sc->sc_ucom, 1); 468 469 usb2_transfer_unsetup(sc->sc_xfer, UPLCOM_N_TRANSFER); 470 471 return (0); 472} 473 474static usb2_error_t 475uplcom_reset(struct uplcom_softc *sc, struct usb2_device *udev) 476{ 477 struct usb2_device_request req; 478 479 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 480 req.bRequest = UPLCOM_SET_REQUEST; 481 USETW(req.wValue, 0); 482 req.wIndex[0] = sc->sc_data_iface_no; 483 req.wIndex[1] = 0; 484 USETW(req.wLength, 0); 485 486 return (usb2_do_request(udev, &Giant, &req, NULL)); 487} 488 489struct pl2303x_init { 490 uint8_t req_type; 491 uint8_t request; 492 uint16_t value; 493 uint16_t index; 494 uint16_t length; 495}; 496 497static const struct pl2303x_init pl2303x[] = { 498 {UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 1}, 499 {UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x0404, 0, 0}, 500 {UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 1}, 501 {UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8383, 0, 1}, 502 {UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 1}, 503 {UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x0404, 1, 0}, 504 {UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 1}, 505 {UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8383, 0, 1}, 506 {UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0, 1, 0}, 507 {UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 1, 0, 0}, 508 {UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 2, 0x44, 0}, 509 {UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 8, 0, 0}, 510 {UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 9, 0, 0}, 511}; 512 513#define N_PL2302X_INIT (sizeof(pl2303x)/sizeof(pl2303x[0])) 514 515static int 516uplcom_pl2303x_init(struct usb2_device *udev) 517{ 518 struct usb2_device_request req; 519 usb2_error_t err; 520 uint8_t buf[4]; 521 uint8_t i; 522 523 for (i = 0; i != N_PL2302X_INIT; i++) { 524 req.bmRequestType = pl2303x[i].req_type; 525 req.bRequest = pl2303x[i].request; 526 USETW(req.wValue, pl2303x[i].value); 527 USETW(req.wIndex, pl2303x[i].index); 528 USETW(req.wLength, pl2303x[i].length); 529 530 err = usb2_do_request(udev, &Giant, &req, buf); 531 if (err) { 532 DPRINTF("error=%s\n", usb2_errstr(err)); 533 return (EIO); 534 } 535 } 536 return (0); 537} 538 539static void 540uplcom_cfg_set_dtr(struct usb2_com_softc *ucom, uint8_t onoff) 541{ 542 struct uplcom_softc *sc = ucom->sc_parent; 543 struct usb2_device_request req; 544 545 DPRINTF("onoff = %d\n", onoff); 546 547 if (onoff) 548 sc->sc_line |= UCDC_LINE_DTR; 549 else 550 sc->sc_line &= ~UCDC_LINE_DTR; 551 552 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 553 req.bRequest = UCDC_SET_CONTROL_LINE_STATE; 554 USETW(req.wValue, sc->sc_line); 555 req.wIndex[0] = sc->sc_data_iface_no; 556 req.wIndex[1] = 0; 557 USETW(req.wLength, 0); 558 559 uplcom_cfg_do_request(sc, &req, NULL); 560} 561 562static void 563uplcom_cfg_set_rts(struct usb2_com_softc *ucom, uint8_t onoff) 564{ 565 struct uplcom_softc *sc = ucom->sc_parent; 566 struct usb2_device_request req; 567 568 DPRINTF("onoff = %d\n", onoff); 569 570 if (onoff) 571 sc->sc_line |= UCDC_LINE_RTS; 572 else 573 sc->sc_line &= ~UCDC_LINE_RTS; 574 575 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 576 req.bRequest = UCDC_SET_CONTROL_LINE_STATE; 577 USETW(req.wValue, sc->sc_line); 578 req.wIndex[0] = sc->sc_data_iface_no; 579 req.wIndex[1] = 0; 580 USETW(req.wLength, 0); 581 582 uplcom_cfg_do_request(sc, &req, NULL); 583} 584 585static void 586uplcom_cfg_set_break(struct usb2_com_softc *ucom, uint8_t onoff) 587{ 588 struct uplcom_softc *sc = ucom->sc_parent; 589 struct usb2_device_request req; 590 uint16_t temp; 591 592 DPRINTF("onoff = %d\n", onoff); 593 594 temp = (onoff ? UCDC_BREAK_ON : UCDC_BREAK_OFF); 595 596 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 597 req.bRequest = UCDC_SEND_BREAK; 598 USETW(req.wValue, temp); 599 req.wIndex[0] = sc->sc_data_iface_no; 600 req.wIndex[1] = 0; 601 USETW(req.wLength, 0); 602 603 uplcom_cfg_do_request(sc, &req, NULL); 604} 605 606static const int32_t uplcom_rates[] = { 607 75, 150, 300, 600, 1200, 1800, 2400, 3600, 4800, 7200, 9600, 14400, 608 19200, 28800, 38400, 57600, 115200, 609 /* 610 * Higher speeds are probably possible. PL2303X supports up to 611 * 6Mb and can set any rate 612 */ 613 230400, 460800, 614400, 921600, 1228800 614}; 615 616#define N_UPLCOM_RATES (sizeof(uplcom_rates)/sizeof(uplcom_rates[0])) 617 618static int 619uplcom_pre_param(struct usb2_com_softc *ucom, struct termios *t) 620{ 621 uint8_t i; 622 623 DPRINTF("\n"); 624 625 /* check requested baud rate */ 626 627 for (i = 0;; i++) { 628 629 if (i != N_UPLCOM_RATES) { 630 if (uplcom_rates[i] == t->c_ospeed) { 631 break; 632 } 633 } else { 634 DPRINTF("invalid baud rate (%d)\n", t->c_ospeed); 635 return (EIO); 636 } 637 } 638 639 return (0); 640} 641 642static void 643uplcom_cfg_param(struct usb2_com_softc *ucom, struct termios *t) 644{ 645 struct uplcom_softc *sc = ucom->sc_parent; 646 struct usb2_cdc_line_state ls; 647 struct usb2_device_request req; 648 649 DPRINTF("sc = %p\n", sc); 650 651 bzero(&ls, sizeof(ls)); 652 653 USETDW(ls.dwDTERate, t->c_ospeed); 654 655 if (t->c_cflag & CSTOPB) { 656 ls.bCharFormat = UCDC_STOP_BIT_2; 657 } else { 658 ls.bCharFormat = UCDC_STOP_BIT_1; 659 } 660 661 if (t->c_cflag & PARENB) { 662 if (t->c_cflag & PARODD) { 663 ls.bParityType = UCDC_PARITY_ODD; 664 } else { 665 ls.bParityType = UCDC_PARITY_EVEN; 666 } 667 } else { 668 ls.bParityType = UCDC_PARITY_NONE; 669 } 670 671 switch (t->c_cflag & CSIZE) { 672 case CS5: 673 ls.bDataBits = 5; 674 break; 675 case CS6: 676 ls.bDataBits = 6; 677 break; 678 case CS7: 679 ls.bDataBits = 7; 680 break; 681 case CS8: 682 ls.bDataBits = 8; 683 break; 684 } 685 686 DPRINTF("rate=%d fmt=%d parity=%d bits=%d\n", 687 UGETDW(ls.dwDTERate), ls.bCharFormat, 688 ls.bParityType, ls.bDataBits); 689 690 req.bmRequestType = UT_WRITE_CLASS_INTERFACE; 691 req.bRequest = UCDC_SET_LINE_CODING; 692 USETW(req.wValue, 0); 693 req.wIndex[0] = sc->sc_data_iface_no; 694 req.wIndex[1] = 0; 695 USETW(req.wLength, UCDC_LINE_STATE_LENGTH); 696 697 uplcom_cfg_do_request(sc, &req, &ls); 698 699 if (t->c_cflag & CRTSCTS) { 700 701 DPRINTF("crtscts = on\n"); 702 703 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 704 req.bRequest = UPLCOM_SET_REQUEST; 705 USETW(req.wValue, 0); 706 if (sc->sc_chiptype == TYPE_PL2303X) 707 USETW(req.wIndex, UPLCOM_SET_CRTSCTS_PL2303X); 708 else 709 USETW(req.wIndex, UPLCOM_SET_CRTSCTS); 710 USETW(req.wLength, 0); 711 712 uplcom_cfg_do_request(sc, &req, NULL); 713 } else { 714 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 715 req.bRequest = UPLCOM_SET_REQUEST; 716 USETW(req.wValue, 0); 717 USETW(req.wIndex, 0); 718 USETW(req.wLength, 0); 719 uplcom_cfg_do_request(sc, &req, NULL); 720 } 721} 722 723static void 724uplcom_start_read(struct usb2_com_softc *ucom) 725{ 726 struct uplcom_softc *sc = ucom->sc_parent; 727 728 /* start interrupt endpoint */
|