aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/class/cdc-acm.c
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2013-05-01 11:47:44 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2013-05-01 11:47:44 -0400
commitbf61c8840efe60fd8f91446860b63338fb424158 (patch)
tree7a71832407a4f0d6346db773343f4c3ae2257b19 /drivers/usb/class/cdc-acm.c
parent5846115b30f3a881e542c8bfde59a699c1c13740 (diff)
parent0c6a61657da78098472fd0eb71cc01f2387fa1bb (diff)
Merge branch 'next' into for-linus
Prepare first set of updates for 3.10 merge window.
Diffstat (limited to 'drivers/usb/class/cdc-acm.c')
-rw-r--r--drivers/usb/class/cdc-acm.c67
1 files changed, 57 insertions, 10 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 6e49ec6f3adc..cb8ef3ef5c94 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -410,19 +410,12 @@ static int acm_submit_read_urbs(struct acm *acm, gfp_t mem_flags)
410 410
411static void acm_process_read_urb(struct acm *acm, struct urb *urb) 411static void acm_process_read_urb(struct acm *acm, struct urb *urb)
412{ 412{
413 struct tty_struct *tty;
414
415 if (!urb->actual_length) 413 if (!urb->actual_length)
416 return; 414 return;
417 415
418 tty = tty_port_tty_get(&acm->port); 416 tty_insert_flip_string(&acm->port, urb->transfer_buffer,
419 if (!tty) 417 urb->actual_length);
420 return; 418 tty_flip_buffer_push(&acm->port);
421
422 tty_insert_flip_string(tty, urb->transfer_buffer, urb->actual_length);
423 tty_flip_buffer_push(tty);
424
425 tty_kref_put(tty);
426} 419}
427 420
428static void acm_read_bulk_callback(struct urb *urb) 421static void acm_read_bulk_callback(struct urb *urb)
@@ -787,6 +780,10 @@ static int get_serial_info(struct acm *acm, struct serial_struct __user *info)
787 tmp.flags = ASYNC_LOW_LATENCY; 780 tmp.flags = ASYNC_LOW_LATENCY;
788 tmp.xmit_fifo_size = acm->writesize; 781 tmp.xmit_fifo_size = acm->writesize;
789 tmp.baud_base = le32_to_cpu(acm->line.dwDTERate); 782 tmp.baud_base = le32_to_cpu(acm->line.dwDTERate);
783 tmp.close_delay = acm->port.close_delay / 10;
784 tmp.closing_wait = acm->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
785 ASYNC_CLOSING_WAIT_NONE :
786 acm->port.closing_wait / 10;
790 787
791 if (copy_to_user(info, &tmp, sizeof(tmp))) 788 if (copy_to_user(info, &tmp, sizeof(tmp)))
792 return -EFAULT; 789 return -EFAULT;
@@ -794,6 +791,37 @@ static int get_serial_info(struct acm *acm, struct serial_struct __user *info)
794 return 0; 791 return 0;
795} 792}
796 793
794static int set_serial_info(struct acm *acm,
795 struct serial_struct __user *newinfo)
796{
797 struct serial_struct new_serial;
798 unsigned int closing_wait, close_delay;
799 int retval = 0;
800
801 if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
802 return -EFAULT;
803
804 close_delay = new_serial.close_delay * 10;
805 closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
806 ASYNC_CLOSING_WAIT_NONE : new_serial.closing_wait * 10;
807
808 mutex_lock(&acm->port.mutex);
809
810 if (!capable(CAP_SYS_ADMIN)) {
811 if ((close_delay != acm->port.close_delay) ||
812 (closing_wait != acm->port.closing_wait))
813 retval = -EPERM;
814 else
815 retval = -EOPNOTSUPP;
816 } else {
817 acm->port.close_delay = close_delay;
818 acm->port.closing_wait = closing_wait;
819 }
820
821 mutex_unlock(&acm->port.mutex);
822 return retval;
823}
824
797static int acm_tty_ioctl(struct tty_struct *tty, 825static int acm_tty_ioctl(struct tty_struct *tty,
798 unsigned int cmd, unsigned long arg) 826 unsigned int cmd, unsigned long arg)
799{ 827{
@@ -804,6 +832,9 @@ static int acm_tty_ioctl(struct tty_struct *tty,
804 case TIOCGSERIAL: /* gets serial port data */ 832 case TIOCGSERIAL: /* gets serial port data */
805 rv = get_serial_info(acm, (struct serial_struct __user *) arg); 833 rv = get_serial_info(acm, (struct serial_struct __user *) arg);
806 break; 834 break;
835 case TIOCSSERIAL:
836 rv = set_serial_info(acm, (struct serial_struct __user *) arg);
837 break;
807 } 838 }
808 839
809 return rv; 840 return rv;
@@ -949,6 +980,10 @@ static int acm_probe(struct usb_interface *intf,
949 980
950 /* normal quirks */ 981 /* normal quirks */
951 quirks = (unsigned long)id->driver_info; 982 quirks = (unsigned long)id->driver_info;
983
984 if (quirks == IGNORE_DEVICE)
985 return -ENODEV;
986
952 num_rx_buf = (quirks == SINGLE_RX_URB) ? 1 : ACM_NR; 987 num_rx_buf = (quirks == SINGLE_RX_URB) ? 1 : ACM_NR;
953 988
954 /* handle quirks deadly to normal probing*/ 989 /* handle quirks deadly to normal probing*/
@@ -1564,6 +1599,9 @@ static const struct usb_device_id acm_ids[] = {
1564 { USB_DEVICE(0x0572, 0x1340), /* Conexant CX93010-2x UCMxx */ 1599 { USB_DEVICE(0x0572, 0x1340), /* Conexant CX93010-2x UCMxx */
1565 .driver_info = NO_UNION_NORMAL, 1600 .driver_info = NO_UNION_NORMAL,
1566 }, 1601 },
1602 { USB_DEVICE(0x05f9, 0x4002), /* PSC Scanning, Magellan 800i */
1603 .driver_info = NO_UNION_NORMAL,
1604 },
1567 { USB_DEVICE(0x1bbb, 0x0003), /* Alcatel OT-I650 */ 1605 { USB_DEVICE(0x1bbb, 0x0003), /* Alcatel OT-I650 */
1568 .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ 1606 .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */
1569 }, 1607 },
@@ -1650,6 +1688,15 @@ static const struct usb_device_id acm_ids[] = {
1650 .driver_info = NO_DATA_INTERFACE, 1688 .driver_info = NO_DATA_INTERFACE,
1651 }, 1689 },
1652 1690
1691#if IS_ENABLED(CONFIG_INPUT_IMS_PCU)
1692 { USB_DEVICE(0x04d8, 0x0082), /* Application mode */
1693 .driver_info = IGNORE_DEVICE,
1694 },
1695 { USB_DEVICE(0x04d8, 0x0083), /* Bootloader mode */
1696 .driver_info = IGNORE_DEVICE,
1697 },
1698#endif
1699
1653 /* control interfaces without any protocol set */ 1700 /* control interfaces without any protocol set */
1654 { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, 1701 { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
1655 USB_CDC_PROTO_NONE) }, 1702 USB_CDC_PROTO_NONE) },