diff options
| author | Oliver Neukum <oliver@neukum.org> | 2012-02-17 17:21:24 -0500 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-02-24 16:12:15 -0500 |
| commit | 18c75720e667719c923e0547abb60dfcd9c4ee90 (patch) | |
| tree | 624773408b86c053c665ee840f8394c63c829b5b /drivers/usb/class | |
| parent | 4c954326823585bd014f36b2babd39c107c2bbb4 (diff) | |
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 <oliver@neukum.org>
Signed-off-by: Dave Jones <davej@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/class')
| -rw-r--r-- | drivers/usb/class/cdc-acm.c | 30 |
1 files changed, 29 insertions, 1 deletions
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 @@ | |||
| 39 | #include <linux/serial.h> | 39 | #include <linux/serial.h> |
| 40 | #include <linux/tty_driver.h> | 40 | #include <linux/tty_driver.h> |
| 41 | #include <linux/tty_flip.h> | 41 | #include <linux/tty_flip.h> |
| 42 | #include <linux/serial.h> | ||
| 42 | #include <linux/module.h> | 43 | #include <linux/module.h> |
| 43 | #include <linux/mutex.h> | 44 | #include <linux/mutex.h> |
| 44 | #include <linux/uaccess.h> | 45 | #include <linux/uaccess.h> |
| @@ -773,10 +774,37 @@ static int acm_tty_tiocmset(struct tty_struct *tty, | |||
| 773 | return acm_set_control(acm, acm->ctrlout = newctrl); | 774 | return acm_set_control(acm, acm->ctrlout = newctrl); |
| 774 | } | 775 | } |
| 775 | 776 | ||
| 777 | static int get_serial_info(struct acm *acm, struct serial_struct __user *info) | ||
| 778 | { | ||
| 779 | struct serial_struct tmp; | ||
| 780 | |||
| 781 | if (!info) | ||
| 782 | return -EINVAL; | ||
| 783 | |||
| 784 | memset(&tmp, 0, sizeof(tmp)); | ||
| 785 | tmp.flags = ASYNC_LOW_LATENCY; | ||
| 786 | tmp.xmit_fifo_size = acm->writesize; | ||
| 787 | tmp.baud_base = le32_to_cpu(acm->line.dwDTERate); | ||
| 788 | |||
| 789 | if (copy_to_user(info, &tmp, sizeof(tmp))) | ||
| 790 | return -EFAULT; | ||
| 791 | else | ||
| 792 | return 0; | ||
| 793 | } | ||
| 794 | |||
| 776 | static int acm_tty_ioctl(struct tty_struct *tty, | 795 | static int acm_tty_ioctl(struct tty_struct *tty, |
| 777 | unsigned int cmd, unsigned long arg) | 796 | unsigned int cmd, unsigned long arg) |
| 778 | { | 797 | { |
| 779 | return -ENOIOCTLCMD; | 798 | struct acm *acm = tty->driver_data; |
| 799 | int rv = -ENOIOCTLCMD; | ||
| 800 | |||
| 801 | switch (cmd) { | ||
| 802 | case TIOCGSERIAL: /* gets serial port data */ | ||
| 803 | rv = get_serial_info(acm, (struct serial_struct __user *) arg); | ||
| 804 | break; | ||
| 805 | } | ||
| 806 | |||
| 807 | return rv; | ||
| 780 | } | 808 | } |
| 781 | 809 | ||
| 782 | static const __u32 acm_tty_speed[] = { | 810 | static const __u32 acm_tty_speed[] = { |
