Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/usb/serial/uplcom.c
Context not available. | |||||
#define UPLCOM_BULK_BUF_SIZE 1024 /* bytes */ | #define UPLCOM_BULK_BUF_SIZE 1024 /* bytes */ | ||||
#define UPLCOM_SET_REQUEST 0x01 | #define UPLCOM_SET_REQUEST 0x01 | ||||
#define UPLCOM_SET_REQUEST_PL2303HXN 0x80 | |||||
#define UPLCOM_SET_CRTSCTS 0x41 | #define UPLCOM_SET_CRTSCTS 0x41 | ||||
#define UPLCOM_SET_CRTSCTS_PL2303X 0x61 | #define UPLCOM_SET_CRTSCTS_PL2303X 0x61 | ||||
#define UPLCOM_SET_CRTSCTS_PL2303HXN 0xFA | |||||
#define UPLCOM_CRTSCTS_REG_PL2303HXN 0x0A | |||||
#define UPLCOM_STATUS_REG_PL2303HX 0x8080 | |||||
#define RSAQ_STATUS_CTS 0x80 | #define RSAQ_STATUS_CTS 0x80 | ||||
#define RSAQ_STATUS_OVERRUN_ERROR 0x40 | #define RSAQ_STATUS_OVERRUN_ERROR 0x40 | ||||
#define RSAQ_STATUS_PARITY_ERROR 0x20 | #define RSAQ_STATUS_PARITY_ERROR 0x20 | ||||
Context not available. | |||||
#define TYPE_PL2303 0 | #define TYPE_PL2303 0 | ||||
#define TYPE_PL2303HX 1 | #define TYPE_PL2303HX 1 | ||||
#define TYPE_PL2303HXD 2 | #define TYPE_PL2303HXD 2 | ||||
#define TYPE_PL2303HXN 3 | |||||
#define UPLCOM_STATE_INDEX 8 | #define UPLCOM_STATE_INDEX 8 | ||||
Context not available. | |||||
UPLCOM_DEV(PROLIFIC, MOTOROLA), /* Motorola cable */ | UPLCOM_DEV(PROLIFIC, MOTOROLA), /* Motorola cable */ | ||||
UPLCOM_DEV(PROLIFIC, PHAROS), /* Prolific Pharos */ | UPLCOM_DEV(PROLIFIC, PHAROS), /* Prolific Pharos */ | ||||
UPLCOM_DEV(PROLIFIC, PL2303), /* Generic adapter */ | UPLCOM_DEV(PROLIFIC, PL2303), /* Generic adapter */ | ||||
UPLCOM_DEV(PROLIFIC, PL2303GC), /* Generic adapter (PL2303HXN, type GC) */ | |||||
UPLCOM_DEV(PROLIFIC, PL2303GB), /* Generic adapter (PL2303HXN, type GB) */ | |||||
UPLCOM_DEV(PROLIFIC, PL2303GT), /* Generic adapter (PL2303HXN, type GT) */ | |||||
UPLCOM_DEV(PROLIFIC, PL2303GL), /* Generic adapter (PL2303HXN, type GL) */ | |||||
UPLCOM_DEV(PROLIFIC, PL2303GE), /* Generic adapter (PL2303HXN, type GE) */ | |||||
UPLCOM_DEV(PROLIFIC, PL2303GS), /* Generic adapter (PL2303HXN, type GS) */ | |||||
UPLCOM_DEV(PROLIFIC, RSAQ2), /* I/O DATA USB-RSAQ2 */ | UPLCOM_DEV(PROLIFIC, RSAQ2), /* I/O DATA USB-RSAQ2 */ | ||||
UPLCOM_DEV(PROLIFIC, RSAQ3), /* I/O DATA USB-RSAQ3 */ | UPLCOM_DEV(PROLIFIC, RSAQ3), /* I/O DATA USB-RSAQ3 */ | ||||
UPLCOM_DEV(PROLIFIC, UIC_MSR206), /* UIC MSR206 Card Reader */ | UPLCOM_DEV(PROLIFIC, UIC_MSR206), /* UIC MSR206 Card Reader */ | ||||
Context not available. | |||||
struct usb_device_descriptor *dd; | struct usb_device_descriptor *dd; | ||||
int error; | int error; | ||||
struct usb_device_request req; | |||||
usb_error_t err; | |||||
uint8_t buf[4]; | |||||
DPRINTFN(11, "\n"); | DPRINTFN(11, "\n"); | ||||
device_set_usb_desc(dev); | device_set_usb_desc(dev); | ||||
Context not available. | |||||
break; | break; | ||||
} | } | ||||
/* | |||||
* The new chip revision PL2303HXN is only compatible with the new | |||||
* UPLCOM_SET_REQUEST_PL2303HXN command. Issuing the old command | |||||
* UPLCOM_SET_REQUEST to the new chip raises an error. Thus, PL2303HX | |||||
* and PL2303HXN can be distinguished by issuing an old-style request | |||||
* (on a status register) to the new chip and checking the error. | |||||
*/ | |||||
if (sc->sc_chiptype == TYPE_PL2303HX) { | |||||
req.bmRequestType = UT_READ_VENDOR_DEVICE; | |||||
req.bRequest = UPLCOM_SET_REQUEST; | |||||
USETW(req.wValue, UPLCOM_STATUS_REG_PL2303HX); | |||||
req.wIndex[0] = sc->sc_data_iface_no; | |||||
req.wIndex[1] = 0; | |||||
USETW(req.wLength, 1); | |||||
err = usbd_do_request(sc->sc_udev, NULL, &req, buf); | |||||
if (err) | |||||
sc->sc_chiptype = TYPE_PL2303HXN; | |||||
} | |||||
switch (sc->sc_chiptype) { | switch (sc->sc_chiptype) { | ||||
case TYPE_PL2303: | case TYPE_PL2303: | ||||
DPRINTF("chiptype: 2303\n"); | DPRINTF("chiptype: 2303\n"); | ||||
Context not available. | |||||
case TYPE_PL2303HX: | case TYPE_PL2303HX: | ||||
DPRINTF("chiptype: 2303HX/TA\n"); | DPRINTF("chiptype: 2303HX/TA\n"); | ||||
break; | break; | ||||
case TYPE_PL2303HXN: | |||||
DPRINTF("chiptype: 2303HXN\n"); | |||||
break; | |||||
case TYPE_PL2303HXD: | case TYPE_PL2303HXD: | ||||
DPRINTF("chiptype: 2303HXD/TB/RA/EA\n"); | DPRINTF("chiptype: 2303HXD/TB/RA/EA\n"); | ||||
break; | break; | ||||
Context not available. | |||||
usbd_xfer_set_stall(sc->sc_xfer[UPLCOM_BULK_DT_WR]); | usbd_xfer_set_stall(sc->sc_xfer[UPLCOM_BULK_DT_WR]); | ||||
usbd_xfer_set_stall(sc->sc_xfer[UPLCOM_BULK_DT_RD]); | usbd_xfer_set_stall(sc->sc_xfer[UPLCOM_BULK_DT_RD]); | ||||
mtx_unlock(&sc->sc_mtx); | mtx_unlock(&sc->sc_mtx); | ||||
} else { | } else if (sc->sc_chiptype == TYPE_PL2303HX || | ||||
sc->sc_chiptype == TYPE_PL2303HXD) { | |||||
/* reset upstream data pipes */ | /* reset upstream data pipes */ | ||||
if (uplcom_pl2303_do(sc->sc_udev, UT_WRITE_VENDOR_DEVICE, | if (uplcom_pl2303_do(sc->sc_udev, UT_WRITE_VENDOR_DEVICE, | ||||
UPLCOM_SET_REQUEST, 8, 0, 0) || | UPLCOM_SET_REQUEST, 8, 0, 0) || | ||||
Context not available. | |||||
UPLCOM_SET_REQUEST, 9, 0, 0)) { | UPLCOM_SET_REQUEST, 9, 0, 0)) { | ||||
goto detach; | goto detach; | ||||
} | } | ||||
} else if (sc->sc_chiptype == TYPE_PL2303HXN) { | |||||
/* reset upstream data pipes */ | |||||
if (uplcom_pl2303_do(sc->sc_udev, UT_WRITE_VENDOR_DEVICE, | |||||
UPLCOM_SET_REQUEST_PL2303HXN, 0x07, 0x03, 0)) { | |||||
goto detach; | |||||
} | |||||
} | } | ||||
error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, | error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc, | ||||
Context not available. | |||||
{ | { | ||||
struct usb_device_request req; | struct usb_device_request req; | ||||
if (sc->sc_chiptype == TYPE_PL2303HXN) { | |||||
/* PL2303HXN doesn't need this reset sequence */ | |||||
return (0); | |||||
} | |||||
req.bmRequestType = UT_WRITE_VENDOR_DEVICE; | req.bmRequestType = UT_WRITE_VENDOR_DEVICE; | ||||
req.bRequest = UPLCOM_SET_REQUEST; | req.bRequest = UPLCOM_SET_REQUEST; | ||||
USETW(req.wValue, 0); | USETW(req.wValue, 0); | ||||
Context not available. | |||||
{ | { | ||||
int err; | int err; | ||||
if (chiptype == TYPE_PL2303HXN) { | |||||
/* PL2303HXN doesn't need this initialization sequence */ | |||||
return (0); | |||||
} | |||||
if (uplcom_pl2303_do(udev, UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 1) | if (uplcom_pl2303_do(udev, UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 1) | ||||
|| uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x0404, 0, 0) | || uplcom_pl2303_do(udev, UT_WRITE_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x0404, 0, 0) | ||||
|| uplcom_pl2303_do(udev, UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 1) | || uplcom_pl2303_do(udev, UT_READ_VENDOR_DEVICE, UPLCOM_SET_REQUEST, 0x8484, 0, 1) | ||||
Context not available. | |||||
* | * | ||||
* The PL2303 can only set specific baud rates, up to 1228800 baud. | * The PL2303 can only set specific baud rates, up to 1228800 baud. | ||||
* The PL2303HX can set any baud rate up to 6Mb. | * The PL2303HX can set any baud rate up to 6Mb. | ||||
* The PL2303HX rev. D can set any baud rate up to 12Mb. | * The PL2303HX rev. D and PL2303HXN can set any baud rate up to 12Mb. | ||||
* | * | ||||
*/ | */ | ||||
Context not available. | |||||
if (t->c_ospeed & 0x80000000) | if (t->c_ospeed & 0x80000000) | ||||
return 0; | return 0; | ||||
switch (sc->sc_chiptype) { | switch (sc->sc_chiptype) { | ||||
case TYPE_PL2303HXN: | |||||
if (t->c_ospeed <= 12000000) | |||||
return (0); | |||||
break; | |||||
case TYPE_PL2303HXD: | case TYPE_PL2303HXD: | ||||
if (t->c_ospeed <= 12000000) | if (t->c_ospeed <= 12000000) | ||||
return (0); | return (0); | ||||
Context not available. | |||||
DPRINTF("crtscts = on\n"); | DPRINTF("crtscts = on\n"); | ||||
req.bmRequestType = UT_WRITE_VENDOR_DEVICE; | req.bmRequestType = UT_WRITE_VENDOR_DEVICE; | ||||
req.bRequest = UPLCOM_SET_REQUEST; | if (sc->sc_chiptype == TYPE_PL2303HXN) { | ||||
USETW(req.wValue, 0); | req.bRequest = UPLCOM_SET_REQUEST_PL2303HXN; | ||||
if (sc->sc_chiptype != TYPE_PL2303) | USETW(req.wValue, UPLCOM_CRTSCTS_REG_PL2303HXN); | ||||
USETW(req.wIndex, UPLCOM_SET_CRTSCTS_PL2303X); | USETW(req.wIndex, UPLCOM_SET_CRTSCTS_PL2303HXN); | ||||
else | } else { | ||||
USETW(req.wIndex, UPLCOM_SET_CRTSCTS); | req.bRequest = UPLCOM_SET_REQUEST; | ||||
USETW(req.wValue, 0); | |||||
if (sc->sc_chiptype != TYPE_PL2303) | |||||
USETW(req.wIndex, UPLCOM_SET_CRTSCTS_PL2303X); | |||||
else | |||||
USETW(req.wIndex, UPLCOM_SET_CRTSCTS); | |||||
} | |||||
USETW(req.wLength, 0); | USETW(req.wLength, 0); | ||||
ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, | ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, | ||||
&req, NULL, 0, 1000); | &req, NULL, 0, 1000); | ||||
} else { | } else { | ||||
Context not available. |