示例#1
0
文件: FTDI.cpp 项目: DonCN/haiku
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;
}
示例#2
0
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);
}
示例#3
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);
}