Lines Matching +full:usb +full:- +full:to +full:- +full:serial
4 /*-
5 * SPDX-License-Identifier: BSD-2-Clause
7 * Copyright (c) 2001-2003, 2005 Shunsuke Akiyama <akiyama@jp.FreeBSD.org>.
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 /*-
36 * This code is derived from software contributed to The NetBSD Foundation
50 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
62 * This driver supports several USB-to-RS232 serial adapters driven by
63 * Prolific PL-2303, PL-2303X and probably PL-2303HX USB-to-RS232
71 * PL-2303HX is probably programmed the same as PL-2303X.
73 * There are several differences between PL-2303 and PL-2303(H)X.
74 * PL-2303(H)X can do higher bitrate in bulk mode, has _probably_
99 #include <dev/usb/usb.h>
100 #include <dev/usb/usbdi.h>
101 #include <dev/usb/usbdi_util.h>
102 #include <dev/usb/usb_cdc.h>
106 #include <dev/usb/usb_debug.h>
107 #include <dev/usb/usb_process.h>
109 #include <dev/usb/serial/usb_serial.h>
115 "USB uplcom");
262 UPLCOM_DEV(ADLINK, ND6530), /* ADLINK ND-6530 USB-Serial */
264 UPLCOM_DEV(ALCOR, AU9720), /* Alcor AU9720 USB 2.0-RS232 */
265 UPLCOM_DEV(ANCHOR, SERIAL), /* Anchor Serial adapter */
266 UPLCOM_DEV(ATEN, UC232A), /* PLANEX USB-RS232 URS-03 */
267 UPLCOM_DEV(ATEN, UC232B), /* Prolific USB-RS232 Controller D */
268 UPLCOM_DEV(BELKIN, F5U257), /* Belkin F5U257 USB to Serial */
269 UPLCOM_DEV(COREGA, CGUSBRS232R), /* Corega CG-USBRS232R */
272 UPLCOM_DEV(ELECOM, UCSGT), /* ELECOM UC-SGT Serial Adapter */
273 UPLCOM_DEV(ELECOM, UCSGT0), /* ELECOM UC-SGT Serial Adapter */
274 UPLCOM_DEV(HAL, IMR001), /* HAL Corporation Crossam2+USB */
276 UPLCOM_DEV(IODATA, USBRSAQ), /* I/O DATA USB-RSAQ */
277 UPLCOM_DEV(IODATA, USBRSAQ5), /* I/O DATA USB-RSAQ5 */
282 UPLCOM_DEV(MOBILEACTION, MA620), /* Mobile Action MA-620 Infrared Adapter */
283 UPLCOM_DEV(NETINDEX, WS002IN), /* Willcom W-S002IN */
284 UPLCOM_DEV(NOKIA2, CA42), /* Nokia CA-42 cable */
285 UPLCOM_DEV(OTI, DKU5), /* OTI DKU-5 cable */
286 UPLCOM_DEV(PANASONIC, TYTP50P6S), /* Panasonic TY-TP50P6-S flat screen */
287 UPLCOM_DEV(PLX, CA42), /* PLX CA-42 clone cable */
289 UPLCOM_DEV(PROLIFIC, ALDIGA_AL11U), /* AlDiga AL-11U modem */
290 UPLCOM_DEV(PROLIFIC, DCU11), /* DCU-11 Phone Cable */
302 UPLCOM_DEV(PROLIFIC, RSAQ2), /* I/O DATA USB-RSAQ2 */
303 UPLCOM_DEV(PROLIFIC, RSAQ3), /* I/O DATA USB-RSAQ3 */
306 UPLCOM_DEV(RADIOSHACK, USBCABLE), /* Radio Shack USB Adapter */
307 UPLCOM_DEV(RATOC, REXUSB60), /* RATOC REX-USB60 */
308 UPLCOM_DEV(SAGEM, USBSERIAL), /* Sagem USB-Serial Controller */
310 UPLCOM_DEV(SANWA, KB_USB2), /* Sanwa KB-USB2 Multimeter cable */
315 UPLCOM_DEV(SITECOM, SERIAL), /* Sitecom USB to Serial */
316 UPLCOM_DEV(SMART, PL2303), /* SMART Technologies USB to Serial */
319 UPLCOM_DEV(SONYERICSSON, DCU10), /* Sony Ericsson DCU-10 Cable */
322 UPLCOM_DEV(SPEEDDRAGON, MS3303H), /* Speed Dragon USB-Serial */
323 UPLCOM_DEV(SYNTECH, CPT8001C), /* Syntech CPT-8001C Barcode scanner */
324 UPLCOM_DEV(TDK, UHA6400), /* TDK USB-PHS Adapter UHA6400 */
325 UPLCOM_DEV(TDK, UPA9664), /* TDK USB-PHS Adapter UPA9664 */
326 UPLCOM_DEV(TRIPPLITE, U209), /* Tripp-Lite U209-000-R USB to Serial */
327 UPLCOM_DEV(YCCABLE, PL2303), /* YC Cable USB-Serial */
346 MODULE_DEPEND(uplcom, usb, 1, 1, 1);
357 if (uaa->usb_mode != USB_MODE_HOST) { in uplcom_probe()
360 if (uaa->info.bConfigIndex != UPLCOM_CONFIG_INDEX) { in uplcom_probe()
363 if (uaa->info.bIfaceIndex != UPLCOM_IFACE_INDEX) { in uplcom_probe()
386 mtx_init(&sc->sc_mtx, "uplcom", NULL, MTX_DEF); in uplcom_attach()
387 ucom_ref(&sc->sc_super_ucom); in uplcom_attach()
391 sc->sc_udev = uaa->device; in uplcom_attach()
393 dd = usbd_get_device_descriptor(sc->sc_udev); in uplcom_attach()
395 switch (UGETW(dd->bcdDevice)) { in uplcom_attach()
397 sc->sc_chiptype = TYPE_PL2303HX; in uplcom_attach()
401 sc->sc_chiptype = TYPE_PL2303HXD; in uplcom_attach()
403 /* or RA, that has internal voltage level converter that works only up to 1Mbaud (!) */ in uplcom_attach()
406 sc->sc_chiptype = TYPE_PL2303HXD; in uplcom_attach()
410 /* NOTE: I have no info about the bcdDevice for the base PL2303 (up to 1.2Mbaud, in uplcom_attach()
411 only fixed rates) and for PL2303SA (8-pin chip, up to 115200 baud */ in uplcom_attach()
413 if (dd->bDeviceClass == 0x02) in uplcom_attach()
414 sc->sc_chiptype = TYPE_PL2303; in uplcom_attach()
415 else if (dd->bMaxPacketSize == 0x40) in uplcom_attach()
416 sc->sc_chiptype = TYPE_PL2303HX; in uplcom_attach()
418 sc->sc_chiptype = TYPE_PL2303; in uplcom_attach()
425 * UPLCOM_SET_REQUEST to the new chip raises an error. Thus, PL2303HX in uplcom_attach()
426 * and PL2303HXN can be distinguished by issuing an old-style request in uplcom_attach()
427 * (on a status register) to the new chip and checking the error. in uplcom_attach()
429 if (sc->sc_chiptype == TYPE_PL2303HX) { in uplcom_attach()
433 req.wIndex[0] = sc->sc_data_iface_no; in uplcom_attach()
436 err = usbd_do_request(sc->sc_udev, NULL, &req, buf); in uplcom_attach()
438 sc->sc_chiptype = TYPE_PL2303HXN; in uplcom_attach()
441 switch (sc->sc_chiptype) { in uplcom_attach()
455 DPRINTF("chiptype: unknown %d\n", sc->sc_chiptype); in uplcom_attach()
460 * USB-RSAQ1 has two interface in uplcom_attach()
462 * USB-RSAQ1 | USB-RSAQ2 in uplcom_attach()
463 * -----------------+----------------- in uplcom_attach()
466 * -----------------+ BulkIN(0x02) in uplcom_attach()
472 sc->sc_ctrl_iface_no = uaa->info.bIfaceNum; in uplcom_attach()
473 sc->sc_iface_index[1] = UPLCOM_IFACE_INDEX; in uplcom_attach()
475 iface = usbd_get_iface(uaa->device, UPLCOM_SECOND_IFACE_INDEX); in uplcom_attach()
482 sc->sc_data_iface_no = id->bInterfaceNumber; in uplcom_attach()
483 sc->sc_iface_index[0] = UPLCOM_SECOND_IFACE_INDEX; in uplcom_attach()
484 usbd_set_parent_iface(uaa->device, in uplcom_attach()
485 UPLCOM_SECOND_IFACE_INDEX, uaa->info.bIfaceIndex); in uplcom_attach()
487 sc->sc_data_iface_no = sc->sc_ctrl_iface_no; in uplcom_attach()
488 sc->sc_iface_index[0] = UPLCOM_IFACE_INDEX; in uplcom_attach()
491 error = usbd_transfer_setup(uaa->device, in uplcom_attach()
492 sc->sc_iface_index, sc->sc_xfer, uplcom_config_data, in uplcom_attach()
493 UPLCOM_N_TRANSFER, sc, &sc->sc_mtx); in uplcom_attach()
495 DPRINTF("one or more missing USB endpoints, " in uplcom_attach()
499 error = uplcom_reset(sc, uaa->device); in uplcom_attach()
506 if (sc->sc_chiptype == TYPE_PL2303) { in uplcom_attach()
507 /* HX variants seem to lock up after a clear stall request. */ in uplcom_attach()
508 mtx_lock(&sc->sc_mtx); in uplcom_attach()
509 usbd_xfer_set_stall(sc->sc_xfer[UPLCOM_BULK_DT_WR]); in uplcom_attach()
510 usbd_xfer_set_stall(sc->sc_xfer[UPLCOM_BULK_DT_RD]); in uplcom_attach()
511 mtx_unlock(&sc->sc_mtx); in uplcom_attach()
512 } else if (sc->sc_chiptype == TYPE_PL2303HX || in uplcom_attach()
513 sc->sc_chiptype == TYPE_PL2303HXD) { in uplcom_attach()
515 if (uplcom_pl2303_do(sc->sc_udev, UT_WRITE_VENDOR_DEVICE, in uplcom_attach()
517 uplcom_pl2303_do(sc->sc_udev, UT_WRITE_VENDOR_DEVICE, in uplcom_attach()
521 } else if (sc->sc_chiptype == TYPE_PL2303HXN) { in uplcom_attach()
523 if (uplcom_pl2303_do(sc->sc_udev, UT_WRITE_VENDOR_DEVICE, in uplcom_attach()
529 error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, in uplcom_attach()
530 &uplcom_callback, &sc->sc_mtx); in uplcom_attach()
538 if (uplcom_pl2303_init(uaa->device, sc->sc_chiptype)) { in uplcom_attach()
542 ucom_set_pnpinfo_usb(&sc->sc_super_ucom, dev); in uplcom_attach()
558 ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom); in uplcom_detach()
559 usbd_transfer_unsetup(sc->sc_xfer, UPLCOM_N_TRANSFER); in uplcom_detach()
573 if (ucom_unref(&sc->sc_super_ucom)) { in uplcom_free_softc()
574 mtx_destroy(&sc->sc_mtx); in uplcom_free_softc()
582 uplcom_free_softc(ucom->sc_parent); in uplcom_free()
590 if (sc->sc_chiptype == TYPE_PL2303HXN) { in uplcom_reset()
598 req.wIndex[0] = sc->sc_data_iface_no; in uplcom_reset()
662 struct uplcom_softc *sc = ucom->sc_parent; in uplcom_cfg_set_dtr()
668 sc->sc_line |= UCDC_LINE_DTR; in uplcom_cfg_set_dtr()
670 sc->sc_line &= ~UCDC_LINE_DTR; in uplcom_cfg_set_dtr()
674 USETW(req.wValue, sc->sc_line); in uplcom_cfg_set_dtr()
675 req.wIndex[0] = sc->sc_data_iface_no; in uplcom_cfg_set_dtr()
679 ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, in uplcom_cfg_set_dtr()
686 struct uplcom_softc *sc = ucom->sc_parent; in uplcom_cfg_set_rts()
692 sc->sc_line |= UCDC_LINE_RTS; in uplcom_cfg_set_rts()
694 sc->sc_line &= ~UCDC_LINE_RTS; in uplcom_cfg_set_rts()
698 USETW(req.wValue, sc->sc_line); in uplcom_cfg_set_rts()
699 req.wIndex[0] = sc->sc_data_iface_no; in uplcom_cfg_set_rts()
703 ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, in uplcom_cfg_set_rts()
710 struct uplcom_softc *sc = ucom->sc_parent; in uplcom_cfg_set_break()
721 req.wIndex[0] = sc->sc_data_iface_no; in uplcom_cfg_set_break()
725 ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, in uplcom_cfg_set_break()
734 * other models it requires writing a divisor value to dwDTERate instead
737 * refers to the Linux module source as a reference implementation.
747 * Advanced speed rates up to 6Mbs, supported by HX/TA and HXD/TB/EA/RA
753 * Advanced speed rates up to 12, supported by HXD/TB/EA/RA
774 struct uplcom_softc *sc = ucom->sc_parent; in uplcom_pre_param()
781 * The PL2303 can only set specific baud rates, up to 1228800 baud. in uplcom_pre_param()
782 * The PL2303HX can set any baud rate up to 6Mb. in uplcom_pre_param()
783 * The PL2303HX rev. D and PL2303HXN can set any baud rate up to 12Mb. in uplcom_pre_param()
787 /* accept raw divisor data, if someone wants to do the math in user domain */ in uplcom_pre_param()
788 if (t->c_ospeed & 0x80000000) in uplcom_pre_param()
790 switch (sc->sc_chiptype) { in uplcom_pre_param()
792 if (t->c_ospeed <= 12000000) in uplcom_pre_param()
796 if (t->c_ospeed <= 12000000) in uplcom_pre_param()
800 if (t->c_ospeed <= 6000000) in uplcom_pre_param()
804 if (uplcom_baud_supported(t->c_ospeed)) in uplcom_pre_param()
809 DPRINTF("uplcom_param: bad baud rate (%d)\n", t->c_ospeed); in uplcom_pre_param()
858 struct uplcom_softc *sc = ucom->sc_parent; in uplcom_cfg_param()
869 if ((t->c_ospeed & 0x80000000) || uplcom_baud_supported(t->c_ospeed)) in uplcom_cfg_param()
870 USETDW(ls.dwDTERate, t->c_ospeed); in uplcom_cfg_param()
872 t->c_ospeed = uplcom_encode_baud_rate_divisor((uint8_t*)&ls.dwDTERate, t->c_ospeed); in uplcom_cfg_param()
874 if (t->c_cflag & CSTOPB) { in uplcom_cfg_param()
875 if ((t->c_cflag & CSIZE) == CS5) { in uplcom_cfg_param()
888 if (t->c_cflag & PARENB) { in uplcom_cfg_param()
889 if (t->c_cflag & PARODD) { in uplcom_cfg_param()
898 switch (t->c_cflag & CSIZE) { in uplcom_cfg_param()
920 req.wIndex[0] = sc->sc_data_iface_no; in uplcom_cfg_param()
924 ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, in uplcom_cfg_param()
927 if (t->c_cflag & CRTSCTS) { in uplcom_cfg_param()
931 if (sc->sc_chiptype == TYPE_PL2303HXN) { in uplcom_cfg_param()
938 if (sc->sc_chiptype != TYPE_PL2303) in uplcom_cfg_param()
945 ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, in uplcom_cfg_param()
949 if (sc->sc_chiptype == TYPE_PL2303HXN) { in uplcom_cfg_param()
960 ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, in uplcom_cfg_param()
968 struct uplcom_softc *sc = ucom->sc_parent; in uplcom_start_read()
971 usbd_transfer_start(sc->sc_xfer[UPLCOM_INTR_DT_RD]); in uplcom_start_read()
974 usbd_transfer_start(sc->sc_xfer[UPLCOM_BULK_DT_RD]); in uplcom_start_read()
980 struct uplcom_softc *sc = ucom->sc_parent; in uplcom_stop_read()
983 usbd_transfer_stop(sc->sc_xfer[UPLCOM_INTR_DT_RD]); in uplcom_stop_read()
986 usbd_transfer_stop(sc->sc_xfer[UPLCOM_BULK_DT_RD]); in uplcom_stop_read()
992 struct uplcom_softc *sc = ucom->sc_parent; in uplcom_start_write()
994 usbd_transfer_start(sc->sc_xfer[UPLCOM_BULK_DT_WR]); in uplcom_start_write()
1000 struct uplcom_softc *sc = ucom->sc_parent; in uplcom_stop_write()
1002 usbd_transfer_stop(sc->sc_xfer[UPLCOM_BULK_DT_WR]); in uplcom_stop_write()
1008 struct uplcom_softc *sc = ucom->sc_parent; in uplcom_cfg_get_status()
1012 *lsr = sc->sc_lsr; in uplcom_cfg_get_status()
1013 *msr = sc->sc_msr; in uplcom_cfg_get_status()
1037 sc->sc_lsr = 0; in uplcom_intr_callback()
1038 sc->sc_msr = 0; in uplcom_intr_callback()
1041 sc->sc_msr |= SER_CTS; in uplcom_intr_callback()
1044 sc->sc_lsr |= ULSR_OE; in uplcom_intr_callback()
1047 sc->sc_lsr |= ULSR_PE; in uplcom_intr_callback()
1050 sc->sc_lsr |= ULSR_FE; in uplcom_intr_callback()
1053 sc->sc_msr |= SER_RI; in uplcom_intr_callback()
1056 sc->sc_lsr |= ULSR_BI; in uplcom_intr_callback()
1059 sc->sc_msr |= SER_DSR; in uplcom_intr_callback()
1062 sc->sc_msr |= SER_DCD; in uplcom_intr_callback()
1064 ucom_status_change(&sc->sc_ucom); in uplcom_intr_callback()
1074 /* try to clear stall first */ in uplcom_intr_callback()
1094 if (ucom_get_data(&sc->sc_ucom, pc, 0, in uplcom_write_callback()
1105 /* try to clear stall first */ in uplcom_write_callback()
1125 ucom_put_data(&sc->sc_ucom, pc, 0, actlen); in uplcom_read_callback()
1135 /* try to clear stall first */ in uplcom_read_callback()
1146 struct uplcom_softc *sc = ucom->sc_parent; in uplcom_poll()
1147 usbd_transfer_poll(sc->sc_xfer, UPLCOM_N_TRANSFER); in uplcom_poll()