aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/class/cdc-acm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/class/cdc-acm.c')
-rw-r--r--drivers/usb/class/cdc-acm.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 6e49ec6f3adc..8d809a811e16 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -787,6 +787,10 @@ static int get_serial_info(struct acm *acm, struct serial_struct __user *info)
787 tmp.flags = ASYNC_LOW_LATENCY; 787 tmp.flags = ASYNC_LOW_LATENCY;
788 tmp.xmit_fifo_size = acm->writesize; 788 tmp.xmit_fifo_size = acm->writesize;
789 tmp.baud_base = le32_to_cpu(acm->line.dwDTERate); 789 tmp.baud_base = le32_to_cpu(acm->line.dwDTERate);
790 tmp.close_delay = acm->port.close_delay / 10;
791 tmp.closing_wait = acm->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
792 ASYNC_CLOSING_WAIT_NONE :
793 acm->port.closing_wait / 10;
790 794
791 if (copy_to_user(info, &tmp, sizeof(tmp))) 795 if (copy_to_user(info, &tmp, sizeof(tmp)))
792 return -EFAULT; 796 return -EFAULT;
@@ -794,6 +798,37 @@ static int get_serial_info(struct acm *acm, struct serial_struct __user *info)
794 return 0; 798 return 0;
795} 799}
796 800
801static int set_serial_info(struct acm *acm,
802 struct serial_struct __user *newinfo)
803{
804 struct serial_struct new_serial;
805 unsigned int closing_wait, close_delay;
806 int retval = 0;
807
808 if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
809 return -EFAULT;
810
811 close_delay = new_serial.close_delay * 10;
812 closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
813 ASYNC_CLOSING_WAIT_NONE : new_serial.closing_wait * 10;
814
815 mutex_lock(&acm->port.mutex);
816
817 if (!capable(CAP_SYS_ADMIN)) {
818 if ((close_delay != acm->port.close_delay) ||
819 (closing_wait != acm->port.closing_wait))
820 retval = -EPERM;
821 else
822 retval = -EOPNOTSUPP;
823 } else {
824 acm->port.close_delay = close_delay;
825 acm->port.closing_wait = closing_wait;
826 }
827
828 mutex_unlock(&acm->port.mutex);
829 return retval;
830}
831
797static int acm_tty_ioctl(struct tty_struct *tty, 832static int acm_tty_ioctl(struct tty_struct *tty,
798 unsigned int cmd, unsigned long arg) 833 unsigned int cmd, unsigned long arg)
799{ 834{
@@ -804,6 +839,9 @@ static int acm_tty_ioctl(struct tty_struct *tty,
804 case TIOCGSERIAL: /* gets serial port data */ 839 case TIOCGSERIAL: /* gets serial port data */
805 rv = get_serial_info(acm, (struct serial_struct __user *) arg); 840 rv = get_serial_info(acm, (struct serial_struct __user *) arg);
806 break; 841 break;
842 case TIOCSSERIAL:
843 rv = set_serial_info(acm, (struct serial_struct __user *) arg);
844 break;
807 } 845 }
808 846
809 return rv; 847 return rv;