summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
authorJohan Hovold <jhovold@gmail.com>2014-05-26 19:23:51 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-05-27 15:04:10 -0700
commit0943d8ead30e9474034cc5e92225ab0fd29fd0d4 (patch)
tree21a9b48b35f9f599b44aca5777777903405444c2 /drivers/usb
parent308fee18e0f06215b47b54a2b254bfaf55527bdd (diff)
USB: cdc-acm: use tty-port dtr_rts
Add dtr_rts tty-port operation which implements proper DTR/RTS handling (e.g. only lower DTR/RTS during shutdown if HUPCL is set). Note that modem-control locking still needs to be added throughout the driver. Signed-off-by: Johan Hovold <jhovold@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/class/cdc-acm.c32
1 files changed, 20 insertions, 12 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 8f654ce52570..e934e19f49f5 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -504,6 +504,25 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
return tty_port_open(&acm->port, tty, filp);
}
+static void acm_port_dtr_rts(struct tty_port *port, int raise)
+{
+ struct acm *acm = container_of(port, struct acm, port);
+ int val;
+ int res;
+
+ if (raise)
+ val = ACM_CTRL_DTR | ACM_CTRL_RTS;
+ else
+ val = 0;
+
+ /* FIXME: add missing ctrlout locking throughout driver */
+ acm->ctrlout = val;
+
+ res = acm_set_control(acm, val);
+ if (res && (acm->ctrl_caps & USB_CDC_CAP_LINE))
+ dev_err(&acm->control->dev, "failed to set dtr/rts\n");
+}
+
static int acm_port_activate(struct tty_port *port, struct tty_struct *tty)
{
struct acm *acm = container_of(port, struct acm, port);
@@ -535,11 +554,6 @@ static int acm_port_activate(struct tty_port *port, struct tty_struct *tty)
goto error_submit_urb;
}
- acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS;
- retval = acm_set_control(acm, acm->ctrlout);
- if (retval < 0 && (acm->ctrl_caps & USB_CDC_CAP_LINE))
- goto error_set_control;
-
/*
* Unthrottle device in case the TTY was closed while throttled.
*/
@@ -561,9 +575,6 @@ static int acm_port_activate(struct tty_port *port, struct tty_struct *tty)
error_submit_read_urbs:
for (i = 0; i < acm->rx_buflimit; i++)
usb_kill_urb(acm->read_urbs[i]);
- acm->ctrlout = 0;
- acm_set_control(acm, acm->ctrlout);
-error_set_control:
usb_kill_urb(acm->ctrlurb);
error_submit_urb:
usb_autopm_put_interface(acm->control);
@@ -595,8 +606,6 @@ static void acm_port_shutdown(struct tty_port *port)
dev_dbg(&acm->control->dev, "%s\n", __func__);
- acm_set_control(acm, acm->ctrlout = 0);
-
/*
* Need to grab write_lock to prevent race with resume, but no need to
* hold it due to the tty-port initialised flag.
@@ -992,6 +1001,7 @@ static void acm_tty_set_termios(struct tty_struct *tty,
}
static const struct tty_port_operations acm_port_ops = {
+ .dtr_rts = acm_port_dtr_rts,
.shutdown = acm_port_shutdown,
.activate = acm_port_activate,
.destruct = acm_port_destruct,
@@ -1429,8 +1439,6 @@ skip_countries:
dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor);
- acm_set_control(acm, acm->ctrlout);
-
acm->line.dwDTERate = cpu_to_le32(9600);
acm->line.bDataBits = 8;
acm_set_line(acm, &acm->line);