From 18c75720e667719c923e0547abb60dfcd9c4ee90 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Fri, 17 Feb 2012 17:21:24 -0500 Subject: [PATCH] USB: allow users to run setserial with cdc-acm We had a user report that running setserial on /dev/ttyACM0 didn't work. He pointed at an old patch by Oliver Neukum from 2008 that never went anywhere.. http://permalink.gmane.org/gmane.linux.usb.general/9236 I made some minor changes to get it to apply again, and got the user to retest on 3.1, and he reported it worked for him. https://bugzilla.redhat.com/show_bug.cgi?id=787607 The diff below is against 3.3rc. The only difference between this and the version the user tested is the removal of the if (!ACM_READY) test Havard removed ACM_READY in 99823f457d5994b3bd3775515578c8bfacc64b04 I'm unclear if there's need for a different test in its place. From: Oliver Neukum Signed-off-by: Dave Jones Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 9543b19d410c..6dcc3a3fe6d1 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -773,10 +774,37 @@ static int acm_tty_tiocmset(struct tty_struct *tty, return acm_set_control(acm, acm->ctrlout = newctrl); } +static int get_serial_info(struct acm *acm, struct serial_struct __user *info) +{ + struct serial_struct tmp; + + if (!info) + return -EINVAL; + + memset(&tmp, 0, sizeof(tmp)); + tmp.flags = ASYNC_LOW_LATENCY; + tmp.xmit_fifo_size = acm->writesize; + tmp.baud_base = le32_to_cpu(acm->line.dwDTERate); + + if (copy_to_user(info, &tmp, sizeof(tmp))) + return -EFAULT; + else + return 0; +} + static int acm_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { - return -ENOIOCTLCMD; + struct acm *acm = tty->driver_data; + int rv = -ENOIOCTLCMD; + + switch (cmd) { + case TIOCGSERIAL: /* gets serial port data */ + rv = get_serial_info(acm, (struct serial_struct __user *) arg); + break; + } + + return rv; } static const __u32 acm_tty_speed[] = {