status_t FTDIDevice::SetLineCoding(usb_cdc_line_coding *lineCoding) { TRACE_FUNCALLS("> FTDIDevice::SetLineCoding(0x%08x, {%d, 0x%02x, 0x%02x, 0x%02x})\n", this, lineCoding->speed, lineCoding->stopbits, lineCoding->parity, lineCoding->databits); int32 rate = 0; if (ProductID() == 0x8372) { // AU100AX switch (lineCoding->speed) { case 300: rate = ftdi_sio_b300; break; case 600: rate = ftdi_sio_b600; break; case 1200: rate = ftdi_sio_b1200; break; case 2400: rate = ftdi_sio_b2400; break; case 4800: rate = ftdi_sio_b4800; break; case 9600: rate = ftdi_sio_b9600; break; case 19200: rate = ftdi_sio_b19200; break; case 38400: rate = ftdi_sio_b38400; break; case 57600: rate = ftdi_sio_b57600; break; case 115200: rate = ftdi_sio_b115200; break; default: rate = ftdi_sio_b19200; TRACE_ALWAYS("= FTDIDevice::SetLineCoding(): Datarate: %d is " "not supported by this hardware. Defaulted to %d\n", lineCoding->speed, rate); break; } } else { switch (lineCoding->speed) { case 300: rate = ftdi_8u232am_b300; break; case 600: rate = ftdi_8u232am_b600; break; case 1200: rate = ftdi_8u232am_b1200; break; case 2400: rate = ftdi_8u232am_b2400; break; case 4800: rate = ftdi_8u232am_b4800; break; case 9600: rate = ftdi_8u232am_b9600; break; case 19200: rate = ftdi_8u232am_b19200; break; case 38400: rate = ftdi_8u232am_b38400; break; case 57600: rate = ftdi_8u232am_b57600; break; case 115200: rate = ftdi_8u232am_b115200; break; case 230400: rate = ftdi_8u232am_b230400; break; case 460800: rate = ftdi_8u232am_b460800; break; case 921600: rate = ftdi_8u232am_b921600; break; default: rate = ftdi_sio_b19200; TRACE_ALWAYS("= FTDIDevice::SetLineCoding(): Datarate: %d is " "not supported by this hardware. Defaulted to %d\n", lineCoding->speed, rate); break; } } size_t length = 0; status_t status = gUSBModule->send_request(Device(), USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, FTDI_SIO_SET_BAUD_RATE, rate, FTDI_PIT_DEFAULT, 0, NULL, &length); if (status != B_OK) TRACE_ALWAYS("= FTDIDevice::SetLineCoding(): datarate set request failed: 0x%08x\n", status); int32 data = 0; switch (lineCoding->stopbits) { case USB_CDC_LINE_CODING_1_STOPBIT: data = FTDI_SIO_SET_DATA_STOP_BITS_2; break; case USB_CDC_LINE_CODING_2_STOPBITS: data = FTDI_SIO_SET_DATA_STOP_BITS_1; break; default: TRACE_ALWAYS("= FTDIDevice::SetLineCoding(): Wrong stopbits param: %d\n", lineCoding->stopbits); break; } switch (lineCoding->parity) { case USB_CDC_LINE_CODING_NO_PARITY: data |= FTDI_SIO_SET_DATA_PARITY_NONE; break; case USB_CDC_LINE_CODING_EVEN_PARITY: data |= FTDI_SIO_SET_DATA_PARITY_EVEN; break; case USB_CDC_LINE_CODING_ODD_PARITY: data |= FTDI_SIO_SET_DATA_PARITY_ODD; break; default: TRACE_ALWAYS("= FTDIDevice::SetLineCoding(): Wrong parity param: %d\n", lineCoding->parity); break; } switch (lineCoding->databits) { case 8: data |= FTDI_SIO_SET_DATA_BITS(8); break; case 7: data |= FTDI_SIO_SET_DATA_BITS(7); break; default: TRACE_ALWAYS("= FTDIDevice::SetLineCoding(): Wrong databits param: %d\n", lineCoding->databits); break; } length = 0; status = gUSBModule->send_request(Device(), USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, FTDI_SIO_SET_DATA, data, FTDI_PIT_DEFAULT, 0, NULL, &length); if (status != B_OK) TRACE_ALWAYS("= FTDIDevice::SetLineCoding(): data set request failed: %08x\n", status); TRACE_FUNCRET("< FTDIDevice::SetLineCoding() returns: 0x%08x\n", status); return status; }
int uftdi_param(void *vsc, int portno, struct termios *t) { struct uftdi_softc *sc = vsc; usb_device_request_t req; usbd_status err; int rate, data, flow; DPRINTF(("uftdi_param: sc=%p\n", sc)); if (usbd_is_dying(sc->sc_udev)) return (EIO); switch (sc->sc_type) { case UFTDI_TYPE_SIO: switch (t->c_ospeed) { case 300: rate = ftdi_sio_b300; break; case 600: rate = ftdi_sio_b600; break; case 1200: rate = ftdi_sio_b1200; break; case 2400: rate = ftdi_sio_b2400; break; case 4800: rate = ftdi_sio_b4800; break; case 9600: rate = ftdi_sio_b9600; break; case 19200: rate = ftdi_sio_b19200; break; case 38400: rate = ftdi_sio_b38400; break; case 57600: rate = ftdi_sio_b57600; break; case 115200: rate = ftdi_sio_b115200; break; default: return (EINVAL); } break; case UFTDI_TYPE_8U232AM: if (uftdi_8u232am_getrate(t->c_ospeed, &rate) == -1) return (EINVAL); break; case UFTDI_TYPE_2232H: if (uftdi_2232h_getrate(t->c_ospeed, &rate) == -1) return (EINVAL); break; } req.bmRequestType = UT_WRITE_VENDOR_DEVICE; req.bRequest = FTDI_SIO_SET_BAUD_RATE; USETW(req.wValue, rate); USETW(req.wIndex, ((rate >> 8) & 0xFF00) | portno); USETW(req.wLength, 0); DPRINTFN(2,("uftdi_param: reqtype=0x%02x req=0x%02x value=0x%04x " "index=0x%04x len=%d\n", req.bmRequestType, req.bRequest, UGETW(req.wValue), UGETW(req.wIndex), UGETW(req.wLength))); err = usbd_do_request(sc->sc_udev, &req, NULL); if (err) return (EIO); if (ISSET(t->c_cflag, CSTOPB)) data = FTDI_SIO_SET_DATA_STOP_BITS_2; else data = FTDI_SIO_SET_DATA_STOP_BITS_1; if (ISSET(t->c_cflag, PARENB)) { if (ISSET(t->c_cflag, PARODD)) data |= FTDI_SIO_SET_DATA_PARITY_ODD; else data |= FTDI_SIO_SET_DATA_PARITY_EVEN; } else data |= FTDI_SIO_SET_DATA_PARITY_NONE; switch (ISSET(t->c_cflag, CSIZE)) { case CS5: data |= FTDI_SIO_SET_DATA_BITS(5); break; case CS6: data |= FTDI_SIO_SET_DATA_BITS(6); break; case CS7: data |= FTDI_SIO_SET_DATA_BITS(7); break; case CS8: data |= FTDI_SIO_SET_DATA_BITS(8); break; } sc->last_lcr = data; req.bmRequestType = UT_WRITE_VENDOR_DEVICE; req.bRequest = FTDI_SIO_SET_DATA; USETW(req.wValue, data); USETW(req.wIndex, portno); USETW(req.wLength, 0); DPRINTFN(2,("uftdi_param: reqtype=0x%02x req=0x%02x value=0x%04x " "index=0x%04x len=%d\n", req.bmRequestType, req.bRequest, UGETW(req.wValue), UGETW(req.wIndex), UGETW(req.wLength))); err = usbd_do_request(sc->sc_udev, &req, NULL); if (err) return (EIO); if (ISSET(t->c_cflag, CRTSCTS)) { flow = FTDI_SIO_RTS_CTS_HS; USETW(req.wValue, 0); } else if (ISSET(t->c_iflag, IXON|IXOFF)) { flow = FTDI_SIO_XON_XOFF_HS; USETW2(req.wValue, t->c_cc[VSTOP], t->c_cc[VSTART]); } else { flow = FTDI_SIO_DISABLE_FLOW_CTRL; USETW(req.wValue, 0); } req.bmRequestType = UT_WRITE_VENDOR_DEVICE; req.bRequest = FTDI_SIO_SET_FLOW_CTRL; USETW2(req.wIndex, flow, portno); USETW(req.wLength, 0); err = usbd_do_request(sc->sc_udev, &req, NULL); if (err) return (EIO); return (0); }
static int uftdi_param2regs(uftdi_state_t *uf, ds_port_params_t *tp, uftdi_regs_t *ur) { ds_port_param_entry_t *pe; int i; ur->ur_data = 0; ur->ur_flowval = 0; ur->ur_flowidx = FTDI_SIO_DISABLE_FLOW_CTRL << 8; for (i = 0, pe = tp->tp_entries; i < tp->tp_cnt; i++, pe++) { switch (pe->param) { case DS_PARAM_BAUD: switch (pe->val.ui) { case B300: ur->ur_baud = ftdi_8u232am_b300; break; case B600: ur->ur_baud = ftdi_8u232am_b600; break; case B1200: ur->ur_baud = ftdi_8u232am_b1200; break; case B2400: ur->ur_baud = ftdi_8u232am_b2400; break; case B4800: ur->ur_baud = ftdi_8u232am_b4800; break; case B9600: ur->ur_baud = ftdi_8u232am_b9600; break; case B19200: ur->ur_baud = ftdi_8u232am_b19200; break; case B38400: ur->ur_baud = ftdi_8u232am_b38400; break; case B57600: ur->ur_baud = ftdi_8u232am_b57600; break; case B115200: ur->ur_baud = ftdi_8u232am_b115200; break; case B230400: ur->ur_baud = ftdi_8u232am_b230400; break; case B460800: ur->ur_baud = ftdi_8u232am_b460800; break; case B921600: ur->ur_baud = ftdi_8u232am_b921600; break; default: USB_DPRINTF_L3(DPRINT_CTLOP, uf->uf_lh, "uftdi_param2regs: bad baud %d", pe->val.ui); return (USB_FAILURE); } break; case DS_PARAM_PARITY: if (pe->val.ui & PARENB) { if (pe->val.ui & PARODD) ur->ur_data |= FTDI_SIO_SET_DATA_PARITY_ODD; else ur->ur_data |= FTDI_SIO_SET_DATA_PARITY_EVEN; } else { /* LINTED [E_EXPR_NULL_EFFECT] */ ur->ur_data |= FTDI_SIO_SET_DATA_PARITY_NONE; } break; case DS_PARAM_STOPB: if (pe->val.ui & CSTOPB) ur->ur_data |= FTDI_SIO_SET_DATA_STOP_BITS_2; else { /* LINTED [E_EXPR_NULL_EFFECT] */ ur->ur_data |= FTDI_SIO_SET_DATA_STOP_BITS_1; } break; case DS_PARAM_CHARSZ: switch (pe->val.ui) { case CS5: ur->ur_data |= FTDI_SIO_SET_DATA_BITS(5); break; case CS6: ur->ur_data |= FTDI_SIO_SET_DATA_BITS(6); break; case CS7: ur->ur_data |= FTDI_SIO_SET_DATA_BITS(7); break; case CS8: default: ur->ur_data |= FTDI_SIO_SET_DATA_BITS(8); break; } break; case DS_PARAM_XON_XOFF: /* Software flow control */ if ((pe->val.ui & IXON) || (pe->val.ui & IXOFF)) { uint8_t xonc = pe->val.uc[0]; uint8_t xoffc = pe->val.uc[1]; ur->ur_flowval = (xoffc << 8) | xonc; ur->ur_flowidx = FTDI_SIO_XON_XOFF_HS << 8; } break; case DS_PARAM_FLOW_CTL: /* Hardware flow control */ if (pe->val.ui & (RTSXOFF | CTSXON)) { ur->ur_flowval = 0; ur->ur_flowidx = FTDI_SIO_RTS_CTS_HS << 8; } if (pe->val.ui & DTRXOFF) { ur->ur_flowval = 0; ur->ur_flowidx = FTDI_SIO_DTR_DSR_HS << 8; } break; default: USB_DPRINTF_L2(DPRINT_CTLOP, uf->uf_lh, "uftdi_param2regs: bad param %d", pe->param); break; } } return (USB_SUCCESS); }