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); |