mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-07 04:12:04 -04:00
USB-serial updates for v4.18-rc1
Here are the USB-serial updates for 4.18-rc1, including:
- support for hardware-assisted XON/XOFF output flow control for pl2303
- fix for a long-standing IXON/IXOFF mixup in ftdi_sio
- blacklist of two apparently unused dwm-158 modem interfaces that
confused some user space daemon (option)
- add missing const to a tty helper currently used by USB serial only
Included are also various clean ups.
All have been in linux-next with no reported issues.
Signed-off-by: Johan Hovold <johan@kernel.org>
-----BEGIN PGP SIGNATURE-----
iQJFBAABCAAvFiEEHszNKQClByu0A+9RQQ3kT97htJUFAlsPvjYRHGpvaGFuQGtl
cm5lbC5vcmcACgkQQQ3kT97htJV/DA/9Huw/RMPo8uSeTiBErvglMf6UJGU8m4qp
YKFzLCkyThPIBBDTYKe1pTWebx422EFCGJwm4zG309ZNxpBcDOmp19FMcQsqCoqN
nRANSJ6L73sbsOLy48/zv59z8vpvVLn0Ob1mQi6iM4KfDdor9PVwHH8zSFHVWO6M
izOLgfeRcfvp8OHPQEodFseQ25jH8SaKA4HSjDmr1vryiMxB8Bh7cVWovC0z2SP8
s8FseAgnhbGp1RF6S4CDUR0OIr064RvoLZjBjVe7iyRiNW6LeruO9I9ctHQQZAh+
D7iVFNj5xTeZQTfgXual7Vbvt5eOBpptcRJqI4Zr+8RR9yIGCpvSh8Kzufkl1uc2
i+0KSo/so2AjBiGS99fxNHrSMD30wL+9Vc2qsq0CuZdkbHamr/8FLtPIuPdq99CW
LBvjJxmzRTl2LDIWDa3fv5Dkfp42asWtg7iN33pf7UcobwgXT8MHrNd6rvsJTMg0
AZHVyZvuplWP3kyZlOCSbZEcIZGiV5lEKLnI0kDtc0io2pJ3+0D6Ys7+lz9o2IHx
zyznyB+dHoiPFd55BooFRIKN75uOLszzA0AhrZLGtUZ20gsdhfLWWgg9VzoaZUsz
NSJIV9tFbBYsnzLDX3W7Q1/VLuvYGidi8Hw7czR5mkWYWFIxShywf4xyaeY3VoiN
i73ad0YjmE8=
=gsOA
-----END PGP SIGNATURE-----
Merge tag 'usb-serial-4.18-rc1' of https://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial into usb-next
Johan writes:
USB-serial updates for v4.18-rc1
Here are the USB-serial updates for 4.18-rc1, including:
- support for hardware-assisted XON/XOFF output flow control for pl2303
- fix for a long-standing IXON/IXOFF mixup in ftdi_sio
- blacklist of two apparently unused dwm-158 modem interfaces that
confused some user space daemon (option)
- add missing const to a tty helper currently used by USB serial only
Included are also various clean ups.
All have been in linux-next with no reported issues.
Signed-off-by: Johan Hovold <johan@kernel.org>
This commit is contained in:
commit
7eeb11190f
7 changed files with 99 additions and 123 deletions
|
|
@ -290,7 +290,7 @@ EXPORT_SYMBOL(tty_termios_copy_hw);
|
|||
* between the two termios structures, or a speed change is needed.
|
||||
*/
|
||||
|
||||
int tty_termios_hw_change(struct ktermios *a, struct ktermios *b)
|
||||
int tty_termios_hw_change(const struct ktermios *a, const struct ktermios *b)
|
||||
{
|
||||
if (a->c_ispeed != b->c_ispeed || a->c_ospeed != b->c_ospeed)
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -60,7 +60,8 @@ static int usb_serial_device_probe(struct device *dev)
|
|||
}
|
||||
|
||||
minor = port->minor;
|
||||
tty_dev = tty_register_device(usb_serial_tty_driver, minor, dev);
|
||||
tty_dev = tty_port_register_device(&port->port, usb_serial_tty_driver,
|
||||
minor, dev);
|
||||
if (IS_ERR(tty_dev)) {
|
||||
retval = PTR_ERR(tty_dev);
|
||||
goto err_port_remove;
|
||||
|
|
|
|||
|
|
@ -54,15 +54,14 @@ struct ftdi_private {
|
|||
int custom_divisor; /* custom_divisor kludge, this is for
|
||||
baud_base (different from what goes to the
|
||||
chip!) */
|
||||
__u16 last_set_data_urb_value ;
|
||||
/* the last data state set - needed for doing
|
||||
* a break
|
||||
*/
|
||||
u16 last_set_data_value; /* the last data state set - needed for doing
|
||||
* a break
|
||||
*/
|
||||
int flags; /* some ASYNC_xxxx flags are supported */
|
||||
unsigned long last_dtr_rts; /* saved modem control outputs */
|
||||
char prev_status; /* Used for TIOCMIWAIT */
|
||||
char transmit_empty; /* If transmitter is empty or not */
|
||||
__u16 interface; /* FT2232C, FT2232H or FT4232H port interface
|
||||
u16 interface; /* FT2232C, FT2232H or FT4232H port interface
|
||||
(0 for FT232/245) */
|
||||
|
||||
speed_t force_baud; /* if non-zero, force the baud rate to
|
||||
|
|
@ -1063,10 +1062,10 @@ static int ftdi_get_modem_status(struct usb_serial_port *port,
|
|||
|
||||
static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base);
|
||||
static unsigned short int ftdi_232am_baud_to_divisor(int baud);
|
||||
static __u32 ftdi_232bm_baud_base_to_divisor(int baud, int base);
|
||||
static __u32 ftdi_232bm_baud_to_divisor(int baud);
|
||||
static __u32 ftdi_2232h_baud_base_to_divisor(int baud, int base);
|
||||
static __u32 ftdi_2232h_baud_to_divisor(int baud);
|
||||
static u32 ftdi_232bm_baud_base_to_divisor(int baud, int base);
|
||||
static u32 ftdi_232bm_baud_to_divisor(int baud);
|
||||
static u32 ftdi_2232h_baud_base_to_divisor(int baud, int base);
|
||||
static u32 ftdi_2232h_baud_to_divisor(int baud);
|
||||
|
||||
static struct usb_serial_driver ftdi_sio_device = {
|
||||
.driver = {
|
||||
|
|
@ -1136,14 +1135,14 @@ static unsigned short int ftdi_232am_baud_to_divisor(int baud)
|
|||
return ftdi_232am_baud_base_to_divisor(baud, 48000000);
|
||||
}
|
||||
|
||||
static __u32 ftdi_232bm_baud_base_to_divisor(int baud, int base)
|
||||
static u32 ftdi_232bm_baud_base_to_divisor(int baud, int base)
|
||||
{
|
||||
static const unsigned char divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 };
|
||||
__u32 divisor;
|
||||
u32 divisor;
|
||||
/* divisor shifted 3 bits to the left */
|
||||
int divisor3 = base / 2 / baud;
|
||||
divisor = divisor3 >> 3;
|
||||
divisor |= (__u32)divfrac[divisor3 & 0x7] << 14;
|
||||
divisor |= (u32)divfrac[divisor3 & 0x7] << 14;
|
||||
/* Deal with special cases for highest baud rates. */
|
||||
if (divisor == 1)
|
||||
divisor = 0;
|
||||
|
|
@ -1152,22 +1151,22 @@ static __u32 ftdi_232bm_baud_base_to_divisor(int baud, int base)
|
|||
return divisor;
|
||||
}
|
||||
|
||||
static __u32 ftdi_232bm_baud_to_divisor(int baud)
|
||||
static u32 ftdi_232bm_baud_to_divisor(int baud)
|
||||
{
|
||||
return ftdi_232bm_baud_base_to_divisor(baud, 48000000);
|
||||
}
|
||||
|
||||
static __u32 ftdi_2232h_baud_base_to_divisor(int baud, int base)
|
||||
static u32 ftdi_2232h_baud_base_to_divisor(int baud, int base)
|
||||
{
|
||||
static const unsigned char divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 };
|
||||
__u32 divisor;
|
||||
u32 divisor;
|
||||
int divisor3;
|
||||
|
||||
/* hi-speed baud rate is 10-bit sampling instead of 16-bit */
|
||||
divisor3 = base * 8 / (baud * 10);
|
||||
|
||||
divisor = divisor3 >> 3;
|
||||
divisor |= (__u32)divfrac[divisor3 & 0x7] << 14;
|
||||
divisor |= (u32)divfrac[divisor3 & 0x7] << 14;
|
||||
/* Deal with special cases for highest baud rates. */
|
||||
if (divisor == 1)
|
||||
divisor = 0;
|
||||
|
|
@ -1182,7 +1181,7 @@ static __u32 ftdi_2232h_baud_base_to_divisor(int baud, int base)
|
|||
return divisor;
|
||||
}
|
||||
|
||||
static __u32 ftdi_2232h_baud_to_divisor(int baud)
|
||||
static u32 ftdi_2232h_baud_to_divisor(int baud)
|
||||
{
|
||||
return ftdi_2232h_baud_base_to_divisor(baud, 120000000);
|
||||
}
|
||||
|
|
@ -1195,7 +1194,7 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set,
|
|||
{
|
||||
struct ftdi_private *priv = usb_get_serial_port_data(port);
|
||||
struct device *dev = &port->dev;
|
||||
unsigned urb_value;
|
||||
unsigned value;
|
||||
int rv;
|
||||
|
||||
if (((set | clear) & (TIOCM_DTR | TIOCM_RTS)) == 0) {
|
||||
|
|
@ -1204,20 +1203,20 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set,
|
|||
}
|
||||
|
||||
clear &= ~set; /* 'set' takes precedence over 'clear' */
|
||||
urb_value = 0;
|
||||
value = 0;
|
||||
if (clear & TIOCM_DTR)
|
||||
urb_value |= FTDI_SIO_SET_DTR_LOW;
|
||||
value |= FTDI_SIO_SET_DTR_LOW;
|
||||
if (clear & TIOCM_RTS)
|
||||
urb_value |= FTDI_SIO_SET_RTS_LOW;
|
||||
value |= FTDI_SIO_SET_RTS_LOW;
|
||||
if (set & TIOCM_DTR)
|
||||
urb_value |= FTDI_SIO_SET_DTR_HIGH;
|
||||
value |= FTDI_SIO_SET_DTR_HIGH;
|
||||
if (set & TIOCM_RTS)
|
||||
urb_value |= FTDI_SIO_SET_RTS_HIGH;
|
||||
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,
|
||||
value, priv->interface,
|
||||
NULL, 0, WDR_TIMEOUT);
|
||||
if (rv < 0) {
|
||||
dev_dbg(dev, "%s Error from MODEM_CTRL urb: DTR %s, RTS %s\n",
|
||||
|
|
@ -1236,12 +1235,12 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set,
|
|||
}
|
||||
|
||||
|
||||
static __u32 get_ftdi_divisor(struct tty_struct *tty,
|
||||
static u32 get_ftdi_divisor(struct tty_struct *tty,
|
||||
struct usb_serial_port *port)
|
||||
{
|
||||
struct ftdi_private *priv = usb_get_serial_port_data(port);
|
||||
struct device *dev = &port->dev;
|
||||
__u32 div_value = 0;
|
||||
u32 div_value = 0;
|
||||
int div_okay = 1;
|
||||
int baud;
|
||||
|
||||
|
|
@ -1299,7 +1298,7 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty,
|
|||
case FT232RL: /* FT232RL chip */
|
||||
case FTX: /* FT-X series */
|
||||
if (baud <= 3000000) {
|
||||
__u16 product_id = le16_to_cpu(
|
||||
u16 product_id = le16_to_cpu(
|
||||
port->serial->dev->descriptor.idProduct);
|
||||
if (((product_id == FTDI_NDI_HUC_PID) ||
|
||||
(product_id == FTDI_NDI_SPECTRA_SCU_PID) ||
|
||||
|
|
@ -1346,26 +1345,26 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty,
|
|||
static int change_speed(struct tty_struct *tty, struct usb_serial_port *port)
|
||||
{
|
||||
struct ftdi_private *priv = usb_get_serial_port_data(port);
|
||||
__u16 urb_value;
|
||||
__u16 urb_index;
|
||||
__u32 urb_index_value;
|
||||
u16 value;
|
||||
u16 index;
|
||||
u32 index_value;
|
||||
int rv;
|
||||
|
||||
urb_index_value = get_ftdi_divisor(tty, port);
|
||||
urb_value = (__u16)urb_index_value;
|
||||
urb_index = (__u16)(urb_index_value >> 16);
|
||||
index_value = get_ftdi_divisor(tty, port);
|
||||
value = (u16)index_value;
|
||||
index = (u16)(index_value >> 16);
|
||||
if ((priv->chip_type == FT2232C) || (priv->chip_type == FT2232H) ||
|
||||
(priv->chip_type == FT4232H) || (priv->chip_type == FT232H)) {
|
||||
/* Probably the BM type needs the MSB of the encoded fractional
|
||||
* divider also moved like for the chips above. Any infos? */
|
||||
urb_index = (__u16)((urb_index << 8) | priv->interface);
|
||||
index = (u16)((index << 8) | priv->interface);
|
||||
}
|
||||
|
||||
rv = usb_control_msg(port->serial->dev,
|
||||
usb_sndctrlpipe(port->serial->dev, 0),
|
||||
FTDI_SIO_SET_BAUDRATE_REQUEST,
|
||||
FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE,
|
||||
urb_value, urb_index,
|
||||
value, index,
|
||||
NULL, 0, WDR_SHORT_TIMEOUT);
|
||||
return rv;
|
||||
}
|
||||
|
|
@ -2140,29 +2139,29 @@ static void ftdi_break_ctl(struct tty_struct *tty, int break_state)
|
|||
{
|
||||
struct usb_serial_port *port = tty->driver_data;
|
||||
struct ftdi_private *priv = usb_get_serial_port_data(port);
|
||||
__u16 urb_value;
|
||||
u16 value;
|
||||
|
||||
/* break_state = -1 to turn on break, and 0 to turn off break */
|
||||
/* see drivers/char/tty_io.c to see it used */
|
||||
/* last_set_data_urb_value NEVER has the break bit set in it */
|
||||
/* last_set_data_value NEVER has the break bit set in it */
|
||||
|
||||
if (break_state)
|
||||
urb_value = priv->last_set_data_urb_value | FTDI_SIO_SET_BREAK;
|
||||
value = priv->last_set_data_value | FTDI_SIO_SET_BREAK;
|
||||
else
|
||||
urb_value = priv->last_set_data_urb_value;
|
||||
value = priv->last_set_data_value;
|
||||
|
||||
if (usb_control_msg(port->serial->dev,
|
||||
usb_sndctrlpipe(port->serial->dev, 0),
|
||||
FTDI_SIO_SET_DATA_REQUEST,
|
||||
FTDI_SIO_SET_DATA_REQUEST_TYPE,
|
||||
urb_value , priv->interface,
|
||||
value , priv->interface,
|
||||
NULL, 0, WDR_TIMEOUT) < 0) {
|
||||
dev_err(&port->dev, "%s FAILED to enable/disable break state (state was %d)\n",
|
||||
__func__, break_state);
|
||||
}
|
||||
|
||||
dev_dbg(&port->dev, "%s break state is %d - urb is %d\n", __func__,
|
||||
break_state, urb_value);
|
||||
break_state, value);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -2192,12 +2191,8 @@ static void ftdi_set_termios(struct tty_struct *tty,
|
|||
struct ftdi_private *priv = usb_get_serial_port_data(port);
|
||||
struct ktermios *termios = &tty->termios;
|
||||
unsigned int cflag = termios->c_cflag;
|
||||
__u16 urb_value; /* will hold the new flags */
|
||||
|
||||
/* Added for xon/xoff support */
|
||||
unsigned int iflag = termios->c_iflag;
|
||||
unsigned char vstop;
|
||||
unsigned char vstart;
|
||||
u16 value, index;
|
||||
int ret;
|
||||
|
||||
/* Force baud rate if this device requires it, unless it is set to
|
||||
B0. */
|
||||
|
|
@ -2258,44 +2253,44 @@ static void ftdi_set_termios(struct tty_struct *tty,
|
|||
no_skip:
|
||||
/* Set number of data bits, parity, stop bits */
|
||||
|
||||
urb_value = 0;
|
||||
urb_value |= (cflag & CSTOPB ? FTDI_SIO_SET_DATA_STOP_BITS_2 :
|
||||
FTDI_SIO_SET_DATA_STOP_BITS_1);
|
||||
value = 0;
|
||||
value |= (cflag & CSTOPB ? FTDI_SIO_SET_DATA_STOP_BITS_2 :
|
||||
FTDI_SIO_SET_DATA_STOP_BITS_1);
|
||||
if (cflag & PARENB) {
|
||||
if (cflag & CMSPAR)
|
||||
urb_value |= cflag & PARODD ?
|
||||
FTDI_SIO_SET_DATA_PARITY_MARK :
|
||||
FTDI_SIO_SET_DATA_PARITY_SPACE;
|
||||
value |= cflag & PARODD ?
|
||||
FTDI_SIO_SET_DATA_PARITY_MARK :
|
||||
FTDI_SIO_SET_DATA_PARITY_SPACE;
|
||||
else
|
||||
urb_value |= cflag & PARODD ?
|
||||
FTDI_SIO_SET_DATA_PARITY_ODD :
|
||||
FTDI_SIO_SET_DATA_PARITY_EVEN;
|
||||
value |= cflag & PARODD ?
|
||||
FTDI_SIO_SET_DATA_PARITY_ODD :
|
||||
FTDI_SIO_SET_DATA_PARITY_EVEN;
|
||||
} else {
|
||||
urb_value |= FTDI_SIO_SET_DATA_PARITY_NONE;
|
||||
value |= FTDI_SIO_SET_DATA_PARITY_NONE;
|
||||
}
|
||||
switch (cflag & CSIZE) {
|
||||
case CS5:
|
||||
dev_dbg(ddev, "Setting CS5 quirk\n");
|
||||
break;
|
||||
case CS7:
|
||||
urb_value |= 7;
|
||||
value |= 7;
|
||||
dev_dbg(ddev, "Setting CS7\n");
|
||||
break;
|
||||
default:
|
||||
case CS8:
|
||||
urb_value |= 8;
|
||||
value |= 8;
|
||||
dev_dbg(ddev, "Setting CS8\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* This is needed by the break command since it uses the same command
|
||||
- but is or'ed with this value */
|
||||
priv->last_set_data_urb_value = urb_value;
|
||||
priv->last_set_data_value = value;
|
||||
|
||||
if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
|
||||
FTDI_SIO_SET_DATA_REQUEST,
|
||||
FTDI_SIO_SET_DATA_REQUEST_TYPE,
|
||||
urb_value , priv->interface,
|
||||
value , priv->interface,
|
||||
NULL, 0, WDR_SHORT_TIMEOUT) < 0) {
|
||||
dev_err(ddev, "%s FAILED to set databits/stopbits/parity\n",
|
||||
__func__);
|
||||
|
|
@ -2326,65 +2321,30 @@ no_data_parity_stop_changes:
|
|||
set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
|
||||
}
|
||||
|
||||
/* Set flow control */
|
||||
/* Note device also supports DTR/CD (ugh) and Xon/Xoff in hardware */
|
||||
no_c_cflag_changes:
|
||||
if (cflag & CRTSCTS) {
|
||||
dev_dbg(ddev, "%s Setting to CRTSCTS flow control\n", __func__);
|
||||
if (usb_control_msg(dev,
|
||||
usb_sndctrlpipe(dev, 0),
|
||||
FTDI_SIO_SET_FLOW_CTRL_REQUEST,
|
||||
FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
|
||||
0 , (FTDI_SIO_RTS_CTS_HS | priv->interface),
|
||||
NULL, 0, WDR_TIMEOUT) < 0) {
|
||||
dev_err(ddev, "urb failed to set to rts/cts flow control\n");
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Xon/Xoff code
|
||||
*
|
||||
* Check the IXOFF status in the iflag component of the
|
||||
* termios structure. If IXOFF is not set, the pre-xon/xoff
|
||||
* code is executed.
|
||||
*/
|
||||
if (iflag & IXOFF) {
|
||||
dev_dbg(ddev, "%s request to enable xonxoff iflag=%04x\n",
|
||||
__func__, iflag);
|
||||
/* Try to enable the XON/XOFF on the ftdi_sio
|
||||
* Set the vstart and vstop -- could have been done up
|
||||
* above where a lot of other dereferencing is done but
|
||||
* that would be very inefficient as vstart and vstop
|
||||
* are not always needed.
|
||||
*/
|
||||
vstart = termios->c_cc[VSTART];
|
||||
vstop = termios->c_cc[VSTOP];
|
||||
urb_value = (vstop << 8) | (vstart);
|
||||
/* Set hardware-assisted flow control */
|
||||
value = 0;
|
||||
|
||||
if (usb_control_msg(dev,
|
||||
usb_sndctrlpipe(dev, 0),
|
||||
FTDI_SIO_SET_FLOW_CTRL_REQUEST,
|
||||
FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
|
||||
urb_value , (FTDI_SIO_XON_XOFF_HS
|
||||
| priv->interface),
|
||||
NULL, 0, WDR_TIMEOUT) < 0) {
|
||||
dev_err(&port->dev, "urb failed to set to "
|
||||
"xon/xoff flow control\n");
|
||||
}
|
||||
} else {
|
||||
/* else clause to only run if cflag ! CRTSCTS and iflag
|
||||
* ! XOFF. CHECKME Assuming XON/XOFF handled by tty
|
||||
* stack - not by device */
|
||||
dev_dbg(ddev, "%s Turning off hardware flow control\n", __func__);
|
||||
if (usb_control_msg(dev,
|
||||
usb_sndctrlpipe(dev, 0),
|
||||
FTDI_SIO_SET_FLOW_CTRL_REQUEST,
|
||||
FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
|
||||
0, priv->interface,
|
||||
NULL, 0, WDR_TIMEOUT) < 0) {
|
||||
dev_err(ddev, "urb failed to clear flow control\n");
|
||||
}
|
||||
}
|
||||
if (C_CRTSCTS(tty)) {
|
||||
dev_dbg(&port->dev, "enabling rts/cts flow control\n");
|
||||
index = FTDI_SIO_RTS_CTS_HS;
|
||||
} else if (I_IXON(tty)) {
|
||||
dev_dbg(&port->dev, "enabling xon/xoff flow control\n");
|
||||
index = FTDI_SIO_XON_XOFF_HS;
|
||||
value = STOP_CHAR(tty) << 8 | START_CHAR(tty);
|
||||
} else {
|
||||
dev_dbg(&port->dev, "disabling flow control\n");
|
||||
index = FTDI_SIO_DISABLE_FLOW_CTRL;
|
||||
}
|
||||
|
||||
index |= priv->interface;
|
||||
|
||||
ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
|
||||
FTDI_SIO_SET_FLOW_CTRL_REQUEST,
|
||||
FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
|
||||
value, index, NULL, 0, WDR_TIMEOUT);
|
||||
if (ret < 0)
|
||||
dev_err(&port->dev, "failed to set flow control: %d\n", ret);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -1916,7 +1916,8 @@ static const struct usb_device_id option_ids[] = {
|
|||
{ USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7d01, 0xff) }, /* D-Link DWM-156 (variant) */
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7d02, 0xff) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7d03, 0xff) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7d04, 0xff) }, /* D-Link DWM-158 */
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7d04, 0xff), /* D-Link DWM-158 */
|
||||
.driver_info = RSVD(4) | RSVD(5) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7d0e, 0xff) }, /* D-Link DWM-157 C1 */
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7e19, 0xff), /* D-Link DWM-221 B1 */
|
||||
.driver_info = RSVD(4) },
|
||||
|
|
|
|||
|
|
@ -533,6 +533,17 @@ static int pl2303_set_line_request(struct usb_serial_port *port,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool pl2303_termios_change(const struct ktermios *a, const struct ktermios *b)
|
||||
{
|
||||
bool ixon_change;
|
||||
|
||||
ixon_change = ((a->c_iflag ^ b->c_iflag) & (IXON | IXANY)) ||
|
||||
a->c_cc[VSTART] != b->c_cc[VSTART] ||
|
||||
a->c_cc[VSTOP] != b->c_cc[VSTOP];
|
||||
|
||||
return tty_termios_hw_change(a, b) || ixon_change;
|
||||
}
|
||||
|
||||
static void pl2303_set_termios(struct tty_struct *tty,
|
||||
struct usb_serial_port *port, struct ktermios *old_termios)
|
||||
{
|
||||
|
|
@ -544,7 +555,7 @@ static void pl2303_set_termios(struct tty_struct *tty,
|
|||
int ret;
|
||||
u8 control;
|
||||
|
||||
if (old_termios && !tty_termios_hw_change(&tty->termios, old_termios))
|
||||
if (old_termios && !pl2303_termios_change(&tty->termios, old_termios))
|
||||
return;
|
||||
|
||||
buf = kzalloc(7, GFP_KERNEL);
|
||||
|
|
@ -662,6 +673,9 @@ static void pl2303_set_termios(struct tty_struct *tty,
|
|||
pl2303_vendor_write(serial, 0x0, 0x41);
|
||||
else
|
||||
pl2303_vendor_write(serial, 0x0, 0x61);
|
||||
} else if (I_IXON(tty) && !I_IXANY(tty) && START_CHAR(tty) == 0x11 &&
|
||||
STOP_CHAR(tty) == 0x13) {
|
||||
pl2303_vendor_write(serial, 0x0, 0xc0);
|
||||
} else {
|
||||
pl2303_vendor_write(serial, 0x0, 0x0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
|
|||
if (retval)
|
||||
goto error_get_interface;
|
||||
|
||||
retval = tty_port_install(&port->port, driver, tty);
|
||||
retval = tty_standard_install(driver, tty);
|
||||
if (retval)
|
||||
goto error_init_termios;
|
||||
|
||||
|
|
|
|||
|
|
@ -527,7 +527,7 @@ static inline speed_t tty_get_baud_rate(struct tty_struct *tty)
|
|||
}
|
||||
|
||||
extern void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old);
|
||||
extern int tty_termios_hw_change(struct ktermios *a, struct ktermios *b);
|
||||
extern int tty_termios_hw_change(const struct ktermios *a, const struct ktermios *b);
|
||||
extern int tty_set_termios(struct tty_struct *tty, struct ktermios *kt);
|
||||
|
||||
extern struct tty_ldisc *tty_ldisc_ref(struct tty_struct *);
|
||||
|
|
|
|||
Loading…
Reference in a new issue