[Ftdi-usb-sio-devel] Question about FlowControl.
Brought to you by:
bryder
|
From: Toan P. <tph...@gm...> - 2009-01-30 15:15:13
|
Bill,
I have a question about flow control in the ftdi driver.
I notice that when I use serial port without flow control, the
ftdi driver still does some kind of flow control with the ftdi chip.
This is found in the set_mctrl, clear_mctrl, and update_mctrl functions.
Is there a documentation on how flow control is implemented in this driver?
Also, in the function update_mctrl, when something goes bad
you disconnect the usb device, as seen in the code below.
I've been experiencing alot of disconnections at this point,
maybe due to noise in the bus; but I've tried shorter cable
length, and disconnection still happen. Would you please
explain why we disconnect here, and how often we do
flow control request with the chip? thank you.
REFERENCE:
---------------------------------------------------------------------------------
static int update_mctrl(struct usb_serial_port *port, unsigned int
set, unsigned int clear)
{
struct ftdi_private *priv = usb_get_serial_port_data(port);
char *buf;
unsigned urb_value;
int rv;
if (((set | clear) & (TIOCM_DTR | TIOCM_RTS)) == 0) {
dbg("%s - DTR|RTS not being set|cleared", __FUNCTION__);
return 0; /* no change */
}
buf = kmalloc(1, GFP_NOIO);
if (!buf) {
return -ENOMEM;
}
clear &= ~set; /* 'set' takes precedence over 'clear' */
urb_value = 0;
if (clear & TIOCM_DTR)
urb_value |= FTDI_SIO_SET_DTR_LOW;
if (clear & TIOCM_RTS)
urb_value |= FTDI_SIO_SET_RTS_LOW;
if (set & TIOCM_DTR)
urb_value |= FTDI_SIO_SET_DTR_HIGH;
if (set & TIOCM_RTS)
urb_value |= FTDI_SIO_SET_RTS_HIGH;
rv = usb_control_msg(port->serial->dev,
usb_sndctrlpipe(port->serial->dev, 0),
FTDI_SIO_SET_MODEM_CTRL_REQUEST,
FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
urb_value, priv->interface,
buf, 0, WDR_TIMEOUT);
kfree(buf);
if (rv < 0) {
err("%s Error from MODEM_CTRL urb: DTR %s, RTS %s",
__FUNCTION__,
(set & TIOCM_DTR) ? "HIGH" :
(clear & TIOCM_DTR) ? "LOW" : "unchanged",
(set & TIOCM_RTS) ? "HIGH" :
(clear & TIOCM_RTS) ? "LOW" : "unchanged");
usb_disconnect(port); /* THIS IS WHERE I OFFEN GET DISCONNECTIONS,
i AM NOT SURE WHAT WENT BAD, HOST CONTROLLER, HUB, DEVICE?*/
} else {
dbg("%s - DTR %s, RTS %s", __FUNCTION__,
(set & TIOCM_DTR) ? "HIGH" :
(clear & TIOCM_DTR) ? "LOW" : "unchanged",
(set & TIOCM_RTS) ? "HIGH" :
(clear & TIOCM_RTS) ? "LOW" : "unchanged");
priv->last_dtr_rts = (priv->last_dtr_rts & ~clear) | set;
}
return rv;
}
|