Commit d94c7bd4 authored by Alan Cox's avatar Alan Cox Committed by Greg Kroah-Hartman

tty: cp210x: Fix carrier handling

Original discussion:
http://thread.gmane.org/gmane.linux.usb.general/23217/focus=23248
or
http://marc.info/?l=linux-usb&m=125553790714133&w=2

9a68e39d broke carrier handling so that a
cp210x setup which needed the carrier lines set up (non CLOCAL) which did
not make a call which set the termios bits left the lines down even if
CLOCAL was not asserted.

Fix this not by reverting but by adding the proper dtr_rts and
carrier_raised methods. This both sets the modem lines properly and also
implements the correct blocking semantics for the port as required by
POSIX.
Signed-off-by: default avatarAlan Cox <alan@linux.intel.com>
Reported-by: default avatarKarl Hiramoto <karl@hiramoto.org>
Tested-by: default avatarKarl Hiramoto <karl@hiramoto.org>
Cc: stable <stable@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 4175f3e3
...@@ -50,6 +50,8 @@ static int cp210x_tiocmset_port(struct usb_serial_port *port, struct file *, ...@@ -50,6 +50,8 @@ static int cp210x_tiocmset_port(struct usb_serial_port *port, struct file *,
static void cp210x_break_ctl(struct tty_struct *, int); static void cp210x_break_ctl(struct tty_struct *, int);
static int cp210x_startup(struct usb_serial *); static int cp210x_startup(struct usb_serial *);
static void cp210x_disconnect(struct usb_serial *); static void cp210x_disconnect(struct usb_serial *);
static void cp210x_dtr_rts(struct usb_serial_port *p, int on);
static int cp210x_carrier_raised(struct usb_serial_port *p);
static int debug; static int debug;
...@@ -143,6 +145,8 @@ static struct usb_serial_driver cp210x_device = { ...@@ -143,6 +145,8 @@ static struct usb_serial_driver cp210x_device = {
.tiocmset = cp210x_tiocmset, .tiocmset = cp210x_tiocmset,
.attach = cp210x_startup, .attach = cp210x_startup,
.disconnect = cp210x_disconnect, .disconnect = cp210x_disconnect,
.dtr_rts = cp210x_dtr_rts,
.carrier_raised = cp210x_carrier_raised
}; };
/* Config request types */ /* Config request types */
...@@ -746,6 +750,14 @@ static int cp210x_tiocmset_port(struct usb_serial_port *port, struct file *file, ...@@ -746,6 +750,14 @@ static int cp210x_tiocmset_port(struct usb_serial_port *port, struct file *file,
return cp210x_set_config(port, CP210X_SET_MHS, &control, 2); return cp210x_set_config(port, CP210X_SET_MHS, &control, 2);
} }
static void cp210x_dtr_rts(struct usb_serial_port *p, int on)
{
if (on)
cp210x_tiocmset_port(p, NULL, TIOCM_DTR|TIOCM_RTS, 0);
else
cp210x_tiocmset_port(p, NULL, 0, TIOCM_DTR|TIOCM_RTS);
}
static int cp210x_tiocmget (struct tty_struct *tty, struct file *file) static int cp210x_tiocmget (struct tty_struct *tty, struct file *file)
{ {
struct usb_serial_port *port = tty->driver_data; struct usb_serial_port *port = tty->driver_data;
...@@ -768,6 +780,15 @@ static int cp210x_tiocmget (struct tty_struct *tty, struct file *file) ...@@ -768,6 +780,15 @@ static int cp210x_tiocmget (struct tty_struct *tty, struct file *file)
return result; return result;
} }
static int cp210x_carrier_raised(struct usb_serial_port *p)
{
unsigned int control;
cp210x_get_config(p, CP210X_GET_MDMSTS, &control, 1);
if (control & CONTROL_DCD)
return 1;
return 0;
}
static void cp210x_break_ctl (struct tty_struct *tty, int break_state) static void cp210x_break_ctl (struct tty_struct *tty, int break_state)
{ {
struct usb_serial_port *port = tty->driver_data; struct usb_serial_port *port = tty->driver_data;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment