|
Lines 132-142
Link Here
|
| 132 |
#define UPLCOM_SET_CRTSCTS 0x41 |
132 |
#define UPLCOM_SET_CRTSCTS 0x41 |
| 133 |
#define UPLCOM_SET_CRTSCTS_PL2303X 0x61 |
133 |
#define UPLCOM_SET_CRTSCTS_PL2303X 0x61 |
| 134 |
#define RSAQ_STATUS_CTS 0x80 |
134 |
#define RSAQ_STATUS_CTS 0x80 |
|
|
135 |
#define RSAQ_STATUS_OVERRUN_ERROR 0x40 |
| 136 |
#define RSAQ_STATUS_PARITY_ERROR 0x20 |
| 137 |
#define RSAQ_STATUS_FRAME_ERROR 0x10 |
| 138 |
#define RSAQ_STATUS_RING 0x08 |
| 139 |
#define RSAQ_STATUS_BREAK_ERROR 0x04 |
| 135 |
#define RSAQ_STATUS_DSR 0x02 |
140 |
#define RSAQ_STATUS_DSR 0x02 |
| 136 |
#define RSAQ_STATUS_DCD 0x01 |
141 |
#define RSAQ_STATUS_DCD 0x01 |
| 137 |
|
142 |
|
| 138 |
#define TYPE_PL2303 0 |
143 |
#define TYPE_PL2303 0 |
| 139 |
#define TYPE_PL2303HX 1 |
144 |
#define TYPE_PL2303HX 1 |
|
|
145 |
#define TYPE_PL2303HXD 2 |
| 146 |
|
| 147 |
#define UPLCOM_STATE_INDEX 8 |
| 140 |
|
148 |
|
| 141 |
enum { |
149 |
enum { |
| 142 |
UPLCOM_BULK_DT_WR, |
150 |
UPLCOM_BULK_DT_WR, |
|
Lines 367-384
Link Here
|
| 367 |
|
375 |
|
| 368 |
sc->sc_udev = uaa->device; |
376 |
sc->sc_udev = uaa->device; |
| 369 |
|
377 |
|
| 370 |
/* Determine the chip type. This algorithm is taken from Linux. */ |
|
|
| 371 |
dd = usbd_get_device_descriptor(sc->sc_udev); |
378 |
dd = usbd_get_device_descriptor(sc->sc_udev); |
| 372 |
if (dd->bDeviceClass == 0x02) |
379 |
|
| 373 |
sc->sc_chiptype = TYPE_PL2303; |
380 |
switch (dd->bcdDevice[0]) { |
| 374 |
else if (dd->bMaxPacketSize == 0x40) |
381 |
case 3: |
| 375 |
sc->sc_chiptype = TYPE_PL2303HX; |
382 |
sc->sc_chiptype = TYPE_PL2303HX; |
| 376 |
else |
383 |
/* or TA, that is HX with external crystal */ |
| 377 |
sc->sc_chiptype = TYPE_PL2303; |
384 |
break; |
|
|
385 |
case 4: |
| 386 |
sc->sc_chiptype = TYPE_PL2303HXD; |
| 387 |
/* or EA, that is HXD with ESD protection */ |
| 388 |
/* or RA, that has internal voltage level converter that works only up to 1Mbaud (!) */ |
| 389 |
break; |
| 390 |
case 5: |
| 391 |
sc->sc_chiptype = TYPE_PL2303HXD; |
| 392 |
/* in fact it's TB, that is HXD with external crystal */ |
| 393 |
break; |
| 394 |
default: |
| 395 |
/* NOTE: I have no info about the bcdDevice for the base PL2303 (up to 1.2Mbaud, |
| 396 |
only fixed rates) and for PL2303SA (8-pin chip, up to 115200 baud */ |
| 397 |
/* Determine the chip type. This algorithm is taken from Linux. */ |
| 398 |
if (dd->bDeviceClass == 0x02) |
| 399 |
sc->sc_chiptype = TYPE_PL2303; |
| 400 |
else if (dd->bMaxPacketSize == 0x40) |
| 401 |
sc->sc_chiptype = TYPE_PL2303HX; |
| 402 |
else |
| 403 |
sc->sc_chiptype = TYPE_PL2303; |
| 404 |
break; |
| 405 |
} |
| 378 |
|
406 |
|
| 379 |
DPRINTF("chiptype: %s\n", |
407 |
switch (sc->sc_chiptype) { |
| 380 |
(sc->sc_chiptype == TYPE_PL2303HX) ? |
408 |
case TYPE_PL2303: |
| 381 |
"2303X" : "2303"); |
409 |
DPRINTF("chiptype: 2303\n"); |
|
|
410 |
break; |
| 411 |
case TYPE_PL2303HX: |
| 412 |
DPRINTF("chiptype: 2303HX/TA\n"); |
| 413 |
break; |
| 414 |
case TYPE_PL2303HXD: |
| 415 |
DPRINTF("chiptype: 2303HXD/TB/RA/EA\n"); |
| 416 |
break; |
| 417 |
default: |
| 418 |
DPRINTF("chiptype: unknown %d\n", sc->sc_chiptype); |
| 419 |
break; |
| 420 |
} |
| 382 |
|
421 |
|
| 383 |
/* |
422 |
/* |
| 384 |
* USB-RSAQ1 has two interface |
423 |
* USB-RSAQ1 has two interface |
|
Lines 427-439
Link Here
|
| 427 |
goto detach; |
466 |
goto detach; |
| 428 |
} |
467 |
} |
| 429 |
|
468 |
|
| 430 |
if (sc->sc_chiptype != TYPE_PL2303HX) { |
469 |
if (sc->sc_chiptype == TYPE_PL2303) { |
| 431 |
/* HX variants seem to lock up after a clear stall request. */ |
470 |
/* HX variants seem to lock up after a clear stall request. */ |
| 432 |
mtx_lock(&sc->sc_mtx); |
471 |
mtx_lock(&sc->sc_mtx); |
| 433 |
usbd_xfer_set_stall(sc->sc_xfer[UPLCOM_BULK_DT_WR]); |
472 |
usbd_xfer_set_stall(sc->sc_xfer[UPLCOM_BULK_DT_WR]); |
| 434 |
usbd_xfer_set_stall(sc->sc_xfer[UPLCOM_BULK_DT_RD]); |
473 |
usbd_xfer_set_stall(sc->sc_xfer[UPLCOM_BULK_DT_RD]); |
| 435 |
mtx_unlock(&sc->sc_mtx); |
474 |
mtx_unlock(&sc->sc_mtx); |
| 436 |
} else { |
475 |
} else { |
|
|
476 |
/* reset upstream data pipes */ |
| 437 |
if (uplcom_pl2303_do(sc->sc_udev, UT_WRITE_VENDOR_DEVICE, |
477 |
if (uplcom_pl2303_do(sc->sc_udev, UT_WRITE_VENDOR_DEVICE, |
| 438 |
UPLCOM_SET_REQUEST, 8, 0, 0) || |
478 |
UPLCOM_SET_REQUEST, 8, 0, 0) || |
| 439 |
uplcom_pl2303_do(sc->sc_udev, UT_WRITE_VENDOR_DEVICE, |
479 |
uplcom_pl2303_do(sc->sc_udev, UT_WRITE_VENDOR_DEVICE, |
|
Lines 552-558
Link Here
|
| 552 |
|| uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 1, 0, 0)) |
592 |
|| uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 1, 0, 0)) |
| 553 |
return (EIO); |
593 |
return (EIO); |
| 554 |
|
594 |
|
| 555 |
if (chiptype == TYPE_PL2303HX) |
595 |
if (chiptype != TYPE_PL2303) |
| 556 |
err = uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 2, 0x44, 0); |
596 |
err = uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 2, 0x44, 0); |
| 557 |
else |
597 |
else |
| 558 |
err = uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 2, 0x24, 0); |
598 |
err = uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 2, 0x24, 0); |
|
Lines 632-654
Link Here
|
| 632 |
&req, NULL, 0, 1000); |
672 |
&req, NULL, 0, 1000); |
| 633 |
} |
673 |
} |
| 634 |
|
674 |
|
|
|
675 |
/* |
| 676 |
* NOTE: These baud rates are officially supported, they can be written |
| 677 |
* directly into dwDTERate register. |
| 678 |
* |
| 679 |
* Free baudrate setting is not supported by the base PL2303, and on |
| 680 |
* other models it requires writing a divisor value to dwDTERate instead |
| 681 |
* of the raw baudrate. The formula for divisor calculation is not published |
| 682 |
* by the vendor, so it is speculative, though the official product homepage |
| 683 |
* refers to the Linux module source as a reference implementation. |
| 684 |
*/ |
| 635 |
static const uint32_t uplcom_rates[] = { |
685 |
static const uint32_t uplcom_rates[] = { |
| 636 |
75, 150, 300, 600, 1200, 1800, 2400, 3600, 4800, 7200, 9600, 14400, |
|
|
| 637 |
19200, 28800, 38400, 57600, 115200, |
| 638 |
/* |
686 |
/* |
| 639 |
* Higher speeds are probably possible. PL2303X supports up to |
687 |
* Basic 'standard' speed rates, supported by all models |
| 640 |
* 6Mb and can set any rate |
688 |
* NOTE: 900 and 56000 actually works as well |
|
|
689 |
*/ |
| 690 |
75, 150, 300, 600, 900, 1200, 1800, 2400, 3600, 4800, 7200, 9600, 14400, |
| 691 |
19200, 28800, 38400, 56000, 57600, 115200, |
| 692 |
/* |
| 693 |
* Advanced speed rates up to 6Mbs, supported by HX/TA and HXD/TB/EA/RA |
| 694 |
* NOTE: regardless of the spec, 256000 does not work |
| 695 |
*/ |
| 696 |
128000, 134400, 161280, 201600, 230400, 268800, 403200, 460800, 614400, |
| 697 |
806400, 921600, 1228800, 2457600, 3000000, 6000000, |
| 698 |
/* |
| 699 |
* Advanced speed rates up to 12, supported by HXD/TB/EA/RA |
| 641 |
*/ |
700 |
*/ |
| 642 |
230400, 460800, 614400, 921600, 1228800 |
701 |
12000000 |
| 643 |
}; |
702 |
}; |
| 644 |
|
703 |
|
| 645 |
#define N_UPLCOM_RATES nitems(uplcom_rates) |
704 |
#define N_UPLCOM_RATES nitems(uplcom_rates) |
| 646 |
|
705 |
|
| 647 |
static int |
706 |
static int |
|
|
707 |
uplcom_baud_supported(unsigned int speed) |
| 708 |
{ |
| 709 |
int i; |
| 710 |
for (i = 0; i < N_UPLCOM_RATES; i++) { |
| 711 |
if (uplcom_rates[i] == speed) |
| 712 |
return 1; |
| 713 |
} |
| 714 |
return 0; |
| 715 |
} |
| 716 |
|
| 717 |
static int |
| 648 |
uplcom_pre_param(struct ucom_softc *ucom, struct termios *t) |
718 |
uplcom_pre_param(struct ucom_softc *ucom, struct termios *t) |
| 649 |
{ |
719 |
{ |
| 650 |
struct uplcom_softc *sc = ucom->sc_parent; |
720 |
struct uplcom_softc *sc = ucom->sc_parent; |
| 651 |
uint8_t i; |
|
|
| 652 |
|
721 |
|
| 653 |
DPRINTF("\n"); |
722 |
DPRINTF("\n"); |
| 654 |
|
723 |
|
|
Lines 656-681
Link Here
|
| 656 |
* Check requested baud rate. |
725 |
* Check requested baud rate. |
| 657 |
* |
726 |
* |
| 658 |
* The PL2303 can only set specific baud rates, up to 1228800 baud. |
727 |
* The PL2303 can only set specific baud rates, up to 1228800 baud. |
| 659 |
* The PL2303X can set any baud rate up to 6Mb. |
728 |
* The PL2303HX can set any baud rate up to 6Mb. |
| 660 |
* The PL2303HX rev. D can set any baud rate up to 12Mb. |
729 |
* The PL2303HX rev. D can set any baud rate up to 12Mb. |
| 661 |
* |
730 |
* |
| 662 |
* XXX: We currently cannot identify the PL2303HX rev. D, so treat |
|
|
| 663 |
* it the same as the PL2303X. |
| 664 |
*/ |
731 |
*/ |
| 665 |
if (sc->sc_chiptype != TYPE_PL2303HX) { |
732 |
|
| 666 |
for (i = 0; i < N_UPLCOM_RATES; i++) { |
733 |
/* accept raw divisor data, if someone wants to do the math in user domain */ |
| 667 |
if (uplcom_rates[i] == t->c_ospeed) |
734 |
if (t->c_ospeed & 0x80000000) |
|
|
735 |
return 0; |
| 736 |
switch (sc->sc_chiptype) { |
| 737 |
case TYPE_PL2303HXD: |
| 738 |
if (t->c_ospeed <= 12000000) |
| 668 |
return (0); |
739 |
return (0); |
| 669 |
} |
740 |
break; |
| 670 |
} else { |
741 |
case TYPE_PL2303HX: |
| 671 |
if (t->c_ospeed <= 6000000) |
742 |
if (t->c_ospeed <= 6000000) |
| 672 |
return (0); |
743 |
return (0); |
|
|
744 |
break; |
| 745 |
default: |
| 746 |
if (uplcom_baud_supported(t->c_ospeed)) |
| 747 |
return (0); |
| 748 |
break; |
| 673 |
} |
749 |
} |
| 674 |
|
750 |
|
| 675 |
DPRINTF("uplcom_param: bad baud rate (%d)\n", t->c_ospeed); |
751 |
DPRINTF("uplcom_param: bad baud rate (%d)\n", t->c_ospeed); |
| 676 |
return (EIO); |
752 |
return (EIO); |
| 677 |
} |
753 |
} |
| 678 |
|
754 |
|
|
|
755 |
static unsigned int |
| 756 |
uplcom_encode_baud_rate_divisor(uint8_t *buf, unsigned int baud) |
| 757 |
{ |
| 758 |
unsigned int baseline, mantissa, exponent; |
| 759 |
|
| 760 |
/* Determine the baud rate divisor. This algorithm is taken from Linux. */ |
| 761 |
/* |
| 762 |
* Apparently the formula is: |
| 763 |
* baudrate = baseline / (mantissa * 4^exponent) |
| 764 |
* where |
| 765 |
* mantissa = buf[8:0] |
| 766 |
* exponent = buf[11:9] |
| 767 |
*/ |
| 768 |
if (baud == 0) |
| 769 |
baud = 1; |
| 770 |
baseline = 383385600; |
| 771 |
mantissa = baseline / baud; |
| 772 |
if (mantissa == 0) |
| 773 |
mantissa = 1; |
| 774 |
exponent = 0; |
| 775 |
while (mantissa >= 512) { |
| 776 |
if (exponent < 7) { |
| 777 |
mantissa >>= 2; /* divide by 4 */ |
| 778 |
exponent++; |
| 779 |
} else { |
| 780 |
/* Exponent is maxed. Trim mantissa and leave. This gives approx. 45.8 baud */ |
| 781 |
mantissa = 511; |
| 782 |
break; |
| 783 |
} |
| 784 |
} |
| 785 |
|
| 786 |
buf[3] = 0x80; |
| 787 |
buf[2] = 0; |
| 788 |
buf[1] = exponent << 1 | mantissa >> 8; |
| 789 |
buf[0] = mantissa & 0xff; |
| 790 |
|
| 791 |
/* Calculate and return the exact baud rate. */ |
| 792 |
baud = (baseline / mantissa) >> (exponent << 1); |
| 793 |
DPRINTF("real baud rate will be %u\n", baud); |
| 794 |
|
| 795 |
return baud; |
| 796 |
} |
| 679 |
static void |
797 |
static void |
| 680 |
uplcom_cfg_param(struct ucom_softc *ucom, struct termios *t) |
798 |
uplcom_cfg_param(struct ucom_softc *ucom, struct termios *t) |
| 681 |
{ |
799 |
{ |
|
Lines 687-696
Link Here
|
| 687 |
|
805 |
|
| 688 |
memset(&ls, 0, sizeof(ls)); |
806 |
memset(&ls, 0, sizeof(ls)); |
| 689 |
|
807 |
|
| 690 |
USETDW(ls.dwDTERate, t->c_ospeed); |
808 |
/* |
|
|
809 |
* NOTE: If unsupported baud rates are set directly, the PL2303* uses 9600 baud. |
| 810 |
*/ |
| 811 |
if ((t->c_ospeed & 0x80000000) || uplcom_baud_supported(t->c_ospeed)) |
| 812 |
USETDW(ls.dwDTERate, t->c_ospeed); |
| 813 |
else |
| 814 |
t->c_ospeed = uplcom_encode_baud_rate_divisor((uint8_t*)&ls.dwDTERate, t->c_ospeed); |
| 691 |
|
815 |
|
| 692 |
if (t->c_cflag & CSTOPB) { |
816 |
if (t->c_cflag & CSTOPB) { |
| 693 |
ls.bCharFormat = UCDC_STOP_BIT_2; |
817 |
if ((t->c_cflag & CSIZE) == CS5) { |
|
|
818 |
/* |
| 819 |
* NOTE: Comply with "real" UARTs / RS232: |
| 820 |
* use 1.5 instead of 2 stop bits with 5 data bits |
| 821 |
*/ |
| 822 |
ls.bCharFormat = UCDC_STOP_BIT_1_5; |
| 823 |
} else { |
| 824 |
ls.bCharFormat = UCDC_STOP_BIT_2; |
| 825 |
} |
| 694 |
} else { |
826 |
} else { |
| 695 |
ls.bCharFormat = UCDC_STOP_BIT_1; |
827 |
ls.bCharFormat = UCDC_STOP_BIT_1; |
| 696 |
} |
828 |
} |
|
Lines 720-726
Link Here
|
| 720 |
break; |
852 |
break; |
| 721 |
} |
853 |
} |
| 722 |
|
854 |
|
| 723 |
DPRINTF("rate=%d fmt=%d parity=%d bits=%d\n", |
855 |
DPRINTF("rate=0x%08x fmt=%d parity=%d bits=%d\n", |
| 724 |
UGETDW(ls.dwDTERate), ls.bCharFormat, |
856 |
UGETDW(ls.dwDTERate), ls.bCharFormat, |
| 725 |
ls.bParityType, ls.bDataBits); |
857 |
ls.bParityType, ls.bDataBits); |
| 726 |
|
858 |
|
|
Lines 741-747
Link Here
|
| 741 |
req.bmRequestType = UT_WRITE_VENDOR_DEVICE; |
873 |
req.bmRequestType = UT_WRITE_VENDOR_DEVICE; |
| 742 |
req.bRequest = UPLCOM_SET_REQUEST; |
874 |
req.bRequest = UPLCOM_SET_REQUEST; |
| 743 |
USETW(req.wValue, 0); |
875 |
USETW(req.wValue, 0); |
| 744 |
if (sc->sc_chiptype == TYPE_PL2303HX) |
876 |
if (sc->sc_chiptype != TYPE_PL2303) |
| 745 |
USETW(req.wIndex, UPLCOM_SET_CRTSCTS_PL2303X); |
877 |
USETW(req.wIndex, UPLCOM_SET_CRTSCTS_PL2303X); |
| 746 |
else |
878 |
else |
| 747 |
USETW(req.wIndex, UPLCOM_SET_CRTSCTS); |
879 |
USETW(req.wIndex, UPLCOM_SET_CRTSCTS); |
|
Lines 807-813
Link Here
|
| 807 |
|
939 |
|
| 808 |
DPRINTF("\n"); |
940 |
DPRINTF("\n"); |
| 809 |
|
941 |
|
| 810 |
/* XXX Note: sc_lsr is always zero */ |
|
|
| 811 |
*lsr = sc->sc_lsr; |
942 |
*lsr = sc->sc_lsr; |
| 812 |
*msr = sc->sc_msr; |
943 |
*msr = sc->sc_msr; |
| 813 |
} |
944 |
} |
|
Lines 832-849
Link Here
|
| 832 |
pc = usbd_xfer_get_frame(xfer, 0); |
963 |
pc = usbd_xfer_get_frame(xfer, 0); |
| 833 |
usbd_copy_out(pc, 0, buf, sizeof(buf)); |
964 |
usbd_copy_out(pc, 0, buf, sizeof(buf)); |
| 834 |
|
965 |
|
| 835 |
DPRINTF("status = 0x%02x\n", buf[8]); |
966 |
DPRINTF("status = 0x%02x\n", buf[UPLCOM_STATE_INDEX]); |
| 836 |
|
967 |
|
| 837 |
sc->sc_lsr = 0; |
968 |
sc->sc_lsr = 0; |
| 838 |
sc->sc_msr = 0; |
969 |
sc->sc_msr = 0; |
| 839 |
|
970 |
|
| 840 |
if (buf[8] & RSAQ_STATUS_CTS) { |
971 |
if (buf[UPLCOM_STATE_INDEX] & RSAQ_STATUS_CTS) { |
| 841 |
sc->sc_msr |= SER_CTS; |
972 |
sc->sc_msr |= SER_CTS; |
| 842 |
} |
973 |
} |
| 843 |
if (buf[8] & RSAQ_STATUS_DSR) { |
974 |
if (buf[UPLCOM_STATE_INDEX] & RSAQ_STATUS_OVERRUN_ERROR) { |
|
|
975 |
sc->sc_lsr |= ULSR_OE; |
| 976 |
} |
| 977 |
if (buf[UPLCOM_STATE_INDEX] & RSAQ_STATUS_PARITY_ERROR) { |
| 978 |
sc->sc_lsr |= ULSR_PE; |
| 979 |
} |
| 980 |
if (buf[UPLCOM_STATE_INDEX] & RSAQ_STATUS_FRAME_ERROR) { |
| 981 |
sc->sc_lsr |= ULSR_FE; |
| 982 |
} |
| 983 |
if (buf[UPLCOM_STATE_INDEX] & RSAQ_STATUS_RING) { |
| 984 |
sc->sc_msr |= SER_RI; |
| 985 |
} |
| 986 |
if (buf[UPLCOM_STATE_INDEX] & RSAQ_STATUS_BREAK_ERROR) { |
| 987 |
sc->sc_lsr |= ULSR_BI; |
| 988 |
} |
| 989 |
if (buf[UPLCOM_STATE_INDEX] & RSAQ_STATUS_DSR) { |
| 844 |
sc->sc_msr |= SER_DSR; |
990 |
sc->sc_msr |= SER_DSR; |
| 845 |
} |
991 |
} |
| 846 |
if (buf[8] & RSAQ_STATUS_DCD) { |
992 |
if (buf[UPLCOM_STATE_INDEX] & RSAQ_STATUS_DCD) { |
| 847 |
sc->sc_msr |= SER_DCD; |
993 |
sc->sc_msr |= SER_DCD; |
| 848 |
} |
994 |
} |
| 849 |
ucom_status_change(&sc->sc_ucom); |
995 |
ucom_status_change(&sc->sc_ucom); |