.. | .. |
---|
185 | 185 | for (;;) { |
---|
186 | 186 | wb = &acm->wb[wbn]; |
---|
187 | 187 | if (!wb->use) { |
---|
188 | | - wb->use = 1; |
---|
| 188 | + wb->use = true; |
---|
189 | 189 | wb->len = 0; |
---|
190 | 190 | return wbn; |
---|
191 | 191 | } |
---|
.. | .. |
---|
203 | 203 | n = ACM_NW; |
---|
204 | 204 | spin_lock_irqsave(&acm->write_lock, flags); |
---|
205 | 205 | for (i = 0; i < ACM_NW; i++) |
---|
206 | | - n -= acm->wb[i].use; |
---|
| 206 | + if(acm->wb[i].use) |
---|
| 207 | + n--; |
---|
207 | 208 | spin_unlock_irqrestore(&acm->write_lock, flags); |
---|
208 | 209 | return n; |
---|
209 | 210 | } |
---|
.. | .. |
---|
213 | 214 | */ |
---|
214 | 215 | static void acm_write_done(struct acm *acm, struct acm_wb *wb) |
---|
215 | 216 | { |
---|
216 | | - wb->use = 0; |
---|
| 217 | + wb->use = false; |
---|
217 | 218 | acm->transmitting--; |
---|
218 | 219 | usb_autopm_put_interface_async(acm->control); |
---|
219 | 220 | } |
---|
.. | .. |
---|
494 | 495 | { |
---|
495 | 496 | struct acm_rb *rb = urb->context; |
---|
496 | 497 | struct acm *acm = rb->instance; |
---|
497 | | - unsigned long flags; |
---|
498 | 498 | int status = urb->status; |
---|
499 | 499 | bool stopped = false; |
---|
500 | 500 | bool stalled = false; |
---|
.. | .. |
---|
558 | 558 | return; |
---|
559 | 559 | } |
---|
560 | 560 | |
---|
561 | | - /* throttle device if requested by tty */ |
---|
562 | | - spin_lock_irqsave(&acm->read_lock, flags); |
---|
563 | | - acm->throttled = acm->throttle_req; |
---|
564 | | - if (!acm->throttled) { |
---|
565 | | - spin_unlock_irqrestore(&acm->read_lock, flags); |
---|
566 | | - acm_submit_read_urb(acm, rb->index, GFP_ATOMIC); |
---|
567 | | - } else { |
---|
568 | | - spin_unlock_irqrestore(&acm->read_lock, flags); |
---|
569 | | - } |
---|
| 561 | + if (test_bit(ACM_THROTTLED, &acm->flags)) |
---|
| 562 | + return; |
---|
| 563 | + |
---|
| 564 | + acm_submit_read_urb(acm, rb->index, GFP_ATOMIC); |
---|
570 | 565 | } |
---|
571 | 566 | |
---|
572 | 567 | /* data interface wrote those outgoing bytes */ |
---|
.. | .. |
---|
710 | 705 | /* |
---|
711 | 706 | * Unthrottle device in case the TTY was closed while throttled. |
---|
712 | 707 | */ |
---|
713 | | - spin_lock_irq(&acm->read_lock); |
---|
714 | | - acm->throttled = 0; |
---|
715 | | - acm->throttle_req = 0; |
---|
716 | | - spin_unlock_irq(&acm->read_lock); |
---|
| 708 | + clear_bit(ACM_THROTTLED, &acm->flags); |
---|
717 | 709 | |
---|
718 | 710 | retval = acm_submit_read_urbs(acm, GFP_KERNEL); |
---|
719 | 711 | if (retval) |
---|
.. | .. |
---|
772 | 764 | if (!urb) |
---|
773 | 765 | break; |
---|
774 | 766 | wb = urb->context; |
---|
775 | | - wb->use = 0; |
---|
| 767 | + wb->use = false; |
---|
776 | 768 | usb_autopm_put_interface_async(acm->control); |
---|
777 | 769 | } |
---|
778 | 770 | |
---|
.. | .. |
---|
824 | 816 | wb = &acm->wb[wbn]; |
---|
825 | 817 | |
---|
826 | 818 | if (!acm->dev) { |
---|
827 | | - wb->use = 0; |
---|
| 819 | + wb->use = false; |
---|
828 | 820 | spin_unlock_irqrestore(&acm->write_lock, flags); |
---|
829 | 821 | return -ENODEV; |
---|
830 | 822 | } |
---|
.. | .. |
---|
836 | 828 | |
---|
837 | 829 | stat = usb_autopm_get_interface_async(acm->control); |
---|
838 | 830 | if (stat) { |
---|
839 | | - wb->use = 0; |
---|
| 831 | + wb->use = false; |
---|
840 | 832 | spin_unlock_irqrestore(&acm->write_lock, flags); |
---|
841 | 833 | return stat; |
---|
842 | 834 | } |
---|
.. | .. |
---|
884 | 876 | { |
---|
885 | 877 | struct acm *acm = tty->driver_data; |
---|
886 | 878 | |
---|
887 | | - spin_lock_irq(&acm->read_lock); |
---|
888 | | - acm->throttle_req = 1; |
---|
889 | | - spin_unlock_irq(&acm->read_lock); |
---|
| 879 | + set_bit(ACM_THROTTLED, &acm->flags); |
---|
890 | 880 | } |
---|
891 | 881 | |
---|
892 | 882 | static void acm_tty_unthrottle(struct tty_struct *tty) |
---|
893 | 883 | { |
---|
894 | 884 | struct acm *acm = tty->driver_data; |
---|
895 | | - unsigned int was_throttled; |
---|
896 | 885 | |
---|
897 | | - spin_lock_irq(&acm->read_lock); |
---|
898 | | - was_throttled = acm->throttled; |
---|
899 | | - acm->throttled = 0; |
---|
900 | | - acm->throttle_req = 0; |
---|
901 | | - spin_unlock_irq(&acm->read_lock); |
---|
| 886 | + clear_bit(ACM_THROTTLED, &acm->flags); |
---|
902 | 887 | |
---|
903 | 888 | /* Matches the smp_mb__after_atomic() in acm_read_bulk_callback(). */ |
---|
904 | 889 | smp_mb(); |
---|
905 | 890 | |
---|
906 | | - if (was_throttled) |
---|
907 | | - acm_submit_read_urbs(acm, GFP_KERNEL); |
---|
| 891 | + acm_submit_read_urbs(acm, GFP_KERNEL); |
---|
908 | 892 | } |
---|
909 | 893 | |
---|
910 | 894 | static int acm_tty_break_ctl(struct tty_struct *tty, int state) |
---|
.. | .. |
---|
950 | 934 | return acm_set_control(acm, acm->ctrlout = newctrl); |
---|
951 | 935 | } |
---|
952 | 936 | |
---|
953 | | -static int get_serial_info(struct acm *acm, struct serial_struct __user *info) |
---|
| 937 | +static int get_serial_info(struct tty_struct *tty, struct serial_struct *ss) |
---|
954 | 938 | { |
---|
955 | | - struct serial_struct tmp; |
---|
| 939 | + struct acm *acm = tty->driver_data; |
---|
956 | 940 | |
---|
957 | | - memset(&tmp, 0, sizeof(tmp)); |
---|
958 | | - tmp.xmit_fifo_size = acm->writesize; |
---|
959 | | - tmp.baud_base = le32_to_cpu(acm->line.dwDTERate); |
---|
960 | | - tmp.close_delay = jiffies_to_msecs(acm->port.close_delay) / 10; |
---|
961 | | - tmp.closing_wait = acm->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ? |
---|
| 941 | + ss->line = acm->minor; |
---|
| 942 | + ss->close_delay = jiffies_to_msecs(acm->port.close_delay) / 10; |
---|
| 943 | + ss->closing_wait = acm->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ? |
---|
962 | 944 | ASYNC_CLOSING_WAIT_NONE : |
---|
963 | 945 | jiffies_to_msecs(acm->port.closing_wait) / 10; |
---|
964 | | - |
---|
965 | | - if (copy_to_user(info, &tmp, sizeof(tmp))) |
---|
966 | | - return -EFAULT; |
---|
967 | | - else |
---|
968 | | - return 0; |
---|
| 946 | + return 0; |
---|
969 | 947 | } |
---|
970 | 948 | |
---|
971 | | -static int set_serial_info(struct acm *acm, |
---|
972 | | - struct serial_struct __user *newinfo) |
---|
| 949 | +static int set_serial_info(struct tty_struct *tty, struct serial_struct *ss) |
---|
973 | 950 | { |
---|
974 | | - struct serial_struct new_serial; |
---|
| 951 | + struct acm *acm = tty->driver_data; |
---|
975 | 952 | unsigned int closing_wait, close_delay; |
---|
976 | | - unsigned int old_closing_wait, old_close_delay; |
---|
977 | 953 | int retval = 0; |
---|
978 | 954 | |
---|
979 | | - if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) |
---|
980 | | - return -EFAULT; |
---|
981 | | - |
---|
982 | | - close_delay = msecs_to_jiffies(new_serial.close_delay * 10); |
---|
983 | | - closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ? |
---|
| 955 | + close_delay = msecs_to_jiffies(ss->close_delay * 10); |
---|
| 956 | + closing_wait = ss->closing_wait == ASYNC_CLOSING_WAIT_NONE ? |
---|
984 | 957 | ASYNC_CLOSING_WAIT_NONE : |
---|
985 | | - msecs_to_jiffies(new_serial.closing_wait * 10); |
---|
986 | | - |
---|
987 | | - /* we must redo the rounding here, so that the values match */ |
---|
988 | | - old_close_delay = jiffies_to_msecs(acm->port.close_delay) / 10; |
---|
989 | | - old_closing_wait = acm->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ? |
---|
990 | | - ASYNC_CLOSING_WAIT_NONE : |
---|
991 | | - jiffies_to_msecs(acm->port.closing_wait) / 10; |
---|
| 958 | + msecs_to_jiffies(ss->closing_wait * 10); |
---|
992 | 959 | |
---|
993 | 960 | mutex_lock(&acm->port.mutex); |
---|
994 | 961 | |
---|
995 | 962 | if (!capable(CAP_SYS_ADMIN)) { |
---|
996 | | - if ((new_serial.close_delay != old_close_delay) || |
---|
997 | | - (new_serial.closing_wait != old_closing_wait)) |
---|
| 963 | + if ((close_delay != acm->port.close_delay) || |
---|
| 964 | + (closing_wait != acm->port.closing_wait)) |
---|
998 | 965 | retval = -EPERM; |
---|
999 | 966 | } else { |
---|
1000 | 967 | acm->port.close_delay = close_delay; |
---|
.. | .. |
---|
1071 | 1038 | int rv = -ENOIOCTLCMD; |
---|
1072 | 1039 | |
---|
1073 | 1040 | switch (cmd) { |
---|
1074 | | - case TIOCGSERIAL: /* gets serial port data */ |
---|
1075 | | - rv = get_serial_info(acm, (struct serial_struct __user *) arg); |
---|
1076 | | - break; |
---|
1077 | | - case TIOCSSERIAL: |
---|
1078 | | - rv = set_serial_info(acm, (struct serial_struct __user *) arg); |
---|
1079 | | - break; |
---|
1080 | 1041 | case TIOCMIWAIT: |
---|
1081 | 1042 | rv = usb_autopm_get_interface(acm->control); |
---|
1082 | 1043 | if (rv < 0) { |
---|
.. | .. |
---|
1249 | 1210 | return -EINVAL; |
---|
1250 | 1211 | } |
---|
1251 | 1212 | |
---|
1252 | | - if (!intf->cur_altsetting) |
---|
1253 | | - return -EINVAL; |
---|
1254 | | - |
---|
1255 | 1213 | if (!buflen) { |
---|
1256 | 1214 | if (intf->cur_altsetting->endpoint && |
---|
1257 | 1215 | intf->cur_altsetting->endpoint->extralen && |
---|
.. | .. |
---|
1274 | 1232 | call_intf_num = cmgmd->bDataInterface; |
---|
1275 | 1233 | |
---|
1276 | 1234 | if (!union_header) { |
---|
1277 | | - if (call_intf_num > 0) { |
---|
| 1235 | + if (intf->cur_altsetting->desc.bNumEndpoints == 3) { |
---|
| 1236 | + dev_dbg(&intf->dev, "No union descriptor, assuming single interface\n"); |
---|
| 1237 | + combined_interfaces = 1; |
---|
| 1238 | + control_interface = data_interface = intf; |
---|
| 1239 | + goto look_for_collapsed_interface; |
---|
| 1240 | + } else if (call_intf_num > 0) { |
---|
1278 | 1241 | dev_dbg(&intf->dev, "No union descriptor, using call management descriptor\n"); |
---|
1279 | | - /* quirks for Droids MuIn LCD */ |
---|
1280 | | - if (quirks & NO_DATA_INTERFACE) { |
---|
1281 | | - data_interface = usb_ifnum_to_if(usb_dev, 0); |
---|
1282 | | - } else { |
---|
1283 | | - data_intf_num = call_intf_num; |
---|
1284 | | - data_interface = usb_ifnum_to_if(usb_dev, data_intf_num); |
---|
1285 | | - } |
---|
| 1242 | + data_intf_num = call_intf_num; |
---|
| 1243 | + data_interface = usb_ifnum_to_if(usb_dev, data_intf_num); |
---|
1286 | 1244 | control_interface = intf; |
---|
1287 | 1245 | } else { |
---|
1288 | | - if (intf->cur_altsetting->desc.bNumEndpoints != 3) { |
---|
1289 | | - dev_dbg(&intf->dev,"No union descriptor, giving up\n"); |
---|
1290 | | - return -ENODEV; |
---|
1291 | | - } else { |
---|
1292 | | - dev_warn(&intf->dev,"No union descriptor, testing for castrated device\n"); |
---|
1293 | | - combined_interfaces = 1; |
---|
1294 | | - control_interface = data_interface = intf; |
---|
1295 | | - goto look_for_collapsed_interface; |
---|
1296 | | - } |
---|
| 1246 | + dev_dbg(&intf->dev, "No union descriptor, giving up\n"); |
---|
| 1247 | + return -ENODEV; |
---|
1297 | 1248 | } |
---|
1298 | 1249 | } else { |
---|
1299 | 1250 | int class = -1; |
---|
.. | .. |
---|
1317 | 1268 | dev_dbg(&intf->dev, "no interfaces\n"); |
---|
1318 | 1269 | return -ENODEV; |
---|
1319 | 1270 | } |
---|
1320 | | - if (!data_interface->cur_altsetting || !control_interface->cur_altsetting) |
---|
1321 | | - return -ENODEV; |
---|
1322 | 1271 | |
---|
1323 | 1272 | if (data_intf_num != call_intf_num) |
---|
1324 | 1273 | dev_dbg(&intf->dev, "Separate call control interface. That is not fully supported.\n"); |
---|
.. | .. |
---|
1345 | 1294 | skip_normal_probe: |
---|
1346 | 1295 | |
---|
1347 | 1296 | /*workaround for switched interfaces */ |
---|
1348 | | - if (data_interface->cur_altsetting->desc.bInterfaceClass |
---|
1349 | | - != CDC_DATA_INTERFACE_TYPE) { |
---|
1350 | | - if (control_interface->cur_altsetting->desc.bInterfaceClass |
---|
1351 | | - == CDC_DATA_INTERFACE_TYPE) { |
---|
| 1297 | + if (data_interface->cur_altsetting->desc.bInterfaceClass != USB_CLASS_CDC_DATA) { |
---|
| 1298 | + if (control_interface->cur_altsetting->desc.bInterfaceClass == USB_CLASS_CDC_DATA) { |
---|
1352 | 1299 | dev_dbg(&intf->dev, |
---|
1353 | 1300 | "Your device has switched interfaces.\n"); |
---|
1354 | 1301 | swap(control_interface, data_interface); |
---|
.. | .. |
---|
1883 | 1830 | { USB_DEVICE(0x09d8, 0x0320), /* Elatec GmbH TWN3 */ |
---|
1884 | 1831 | .driver_info = NO_UNION_NORMAL, /* has misplaced union descriptor */ |
---|
1885 | 1832 | }, |
---|
| 1833 | + { USB_DEVICE(0x0c26, 0x0020), /* Icom ICF3400 Serie */ |
---|
| 1834 | + .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ |
---|
| 1835 | + }, |
---|
1886 | 1836 | { USB_DEVICE(0x0ca6, 0xa050), /* Castles VEGA3000 */ |
---|
1887 | 1837 | .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ |
---|
1888 | 1838 | }, |
---|
.. | .. |
---|
1960 | 1910 | |
---|
1961 | 1911 | /* NOTE: non-Nokia COMM/ACM/0xff is likely MSFT RNDIS... NOT a modem! */ |
---|
1962 | 1912 | |
---|
1963 | | - /* Support for Droids MuIn LCD */ |
---|
1964 | | - { USB_DEVICE(0x04d8, 0x000b), |
---|
1965 | | - .driver_info = NO_DATA_INTERFACE, |
---|
1966 | | - }, |
---|
1967 | | - |
---|
1968 | 1913 | #if IS_ENABLED(CONFIG_INPUT_IMS_PCU) |
---|
1969 | 1914 | { USB_DEVICE(0x04d8, 0x0082), /* Application mode */ |
---|
1970 | 1915 | .driver_info = IGNORE_DEVICE, |
---|
1971 | 1916 | }, |
---|
1972 | 1917 | { USB_DEVICE(0x04d8, 0x0083), /* Bootloader mode */ |
---|
| 1918 | + .driver_info = IGNORE_DEVICE, |
---|
| 1919 | + }, |
---|
| 1920 | +#endif |
---|
| 1921 | + |
---|
| 1922 | +#if IS_ENABLED(CONFIG_IR_TOY) |
---|
| 1923 | + { USB_DEVICE(0x04d8, 0xfd08), |
---|
1973 | 1924 | .driver_info = IGNORE_DEVICE, |
---|
1974 | 1925 | }, |
---|
1975 | 1926 | |
---|
.. | .. |
---|
2080 | 2031 | .set_termios = acm_tty_set_termios, |
---|
2081 | 2032 | .tiocmget = acm_tty_tiocmget, |
---|
2082 | 2033 | .tiocmset = acm_tty_tiocmset, |
---|
| 2034 | + .get_serial = get_serial_info, |
---|
| 2035 | + .set_serial = set_serial_info, |
---|
2083 | 2036 | .get_icount = acm_tty_get_icount, |
---|
2084 | 2037 | }; |
---|
2085 | 2038 | |
---|