aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/class/cdc-acm.c
diff options
context:
space:
mode:
authorOliver Neukum <oliver@neukum.org>2012-02-17 17:21:24 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-02-24 16:12:15 -0500
commit18c75720e667719c923e0547abb60dfcd9c4ee90 (patch)
tree624773408b86c053c665ee840f8394c63c829b5b /drivers/usb/class/cdc-acm.c
parent4c954326823585bd014f36b2babd39c107c2bbb4 (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/cdc-acm.c')
-rw-r--r--drivers/usb/class/cdc-acm.c30
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
777static 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
776static int acm_tty_ioctl(struct tty_struct *tty, 795static 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
782static const __u32 acm_tty_speed[] = { 810static const __u32 acm_tty_speed[] = {