From: Oliver Neukum Date: Fri, 17 Feb 2012 22:21:24 +0000 (-0500) Subject: USB: allow users to run setserial with cdc-acm X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=18c75720e667719c923e0547abb60dfcd9c4ee90;p=linux-beck.git 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 --- 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[] = {