diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-03-05 10:15:17 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-03-05 10:15:17 -0500 |
commit | d3d5389475e8554842ec5640e1e0e93a298f2680 (patch) | |
tree | eb39b8220b32e05f3c76ca710f549269dabbee61 | |
parent | b20b1618b8fca858c83e52da4aa22cd6b13b0359 (diff) | |
parent | c7d373c3f0da2b2b78c4b1ce5ae41485b3ef848c (diff) |
Merge tag 'usb-serial-4.0-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial into usb-linus
Johan writes:
USB-serial fixes for v4.0-rc3
Here are a few fixes for reported problems including a usb-debug device
buffer overflow, potential use-after-free on failed probe, and a couple
of issues with the USB console.
Some new device IDs are also added.
Signed-off-by: Johan Hovold <johan@kernel.org>
-rw-r--r-- | drivers/usb/serial/bus.c | 45 | ||||
-rw-r--r-- | drivers/usb/serial/ch341.c | 15 | ||||
-rw-r--r-- | drivers/usb/serial/console.c | 2 | ||||
-rw-r--r-- | drivers/usb/serial/cp210x.c | 2 | ||||
-rw-r--r-- | drivers/usb/serial/ftdi_sio.c | 19 | ||||
-rw-r--r-- | drivers/usb/serial/ftdi_sio_ids.h | 23 | ||||
-rw-r--r-- | drivers/usb/serial/mxuport.c | 3 | ||||
-rw-r--r-- | drivers/usb/serial/pl2303.c | 18 | ||||
-rw-r--r-- | drivers/usb/serial/usb-serial.c | 21 | ||||
-rw-r--r-- | include/linux/usb/serial.h | 3 |
10 files changed, 106 insertions, 45 deletions
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c index 9374bd2aba20..8936a83c96cd 100644 --- a/drivers/usb/serial/bus.c +++ b/drivers/usb/serial/bus.c | |||
@@ -38,56 +38,51 @@ static int usb_serial_device_match(struct device *dev, | |||
38 | return 0; | 38 | return 0; |
39 | } | 39 | } |
40 | 40 | ||
41 | static ssize_t port_number_show(struct device *dev, | ||
42 | struct device_attribute *attr, char *buf) | ||
43 | { | ||
44 | struct usb_serial_port *port = to_usb_serial_port(dev); | ||
45 | |||
46 | return sprintf(buf, "%d\n", port->port_number); | ||
47 | } | ||
48 | static DEVICE_ATTR_RO(port_number); | ||
49 | |||
50 | static int usb_serial_device_probe(struct device *dev) | 41 | static int usb_serial_device_probe(struct device *dev) |
51 | { | 42 | { |
52 | struct usb_serial_driver *driver; | 43 | struct usb_serial_driver *driver; |
53 | struct usb_serial_port *port; | 44 | struct usb_serial_port *port; |
45 | struct device *tty_dev; | ||
54 | int retval = 0; | 46 | int retval = 0; |
55 | int minor; | 47 | int minor; |
56 | 48 | ||
57 | port = to_usb_serial_port(dev); | 49 | port = to_usb_serial_port(dev); |
58 | if (!port) { | 50 | if (!port) |
59 | retval = -ENODEV; | 51 | return -ENODEV; |
60 | goto exit; | ||
61 | } | ||
62 | 52 | ||
63 | /* make sure suspend/resume doesn't race against port_probe */ | 53 | /* make sure suspend/resume doesn't race against port_probe */ |
64 | retval = usb_autopm_get_interface(port->serial->interface); | 54 | retval = usb_autopm_get_interface(port->serial->interface); |
65 | if (retval) | 55 | if (retval) |
66 | goto exit; | 56 | return retval; |
67 | 57 | ||
68 | driver = port->serial->type; | 58 | driver = port->serial->type; |
69 | if (driver->port_probe) { | 59 | if (driver->port_probe) { |
70 | retval = driver->port_probe(port); | 60 | retval = driver->port_probe(port); |
71 | if (retval) | 61 | if (retval) |
72 | goto exit_with_autopm; | 62 | goto err_autopm_put; |
73 | } | 63 | } |
74 | 64 | ||
75 | retval = device_create_file(dev, &dev_attr_port_number); | 65 | minor = port->minor; |
76 | if (retval) { | 66 | tty_dev = tty_register_device(usb_serial_tty_driver, minor, dev); |
77 | if (driver->port_remove) | 67 | if (IS_ERR(tty_dev)) { |
78 | retval = driver->port_remove(port); | 68 | retval = PTR_ERR(tty_dev); |
79 | goto exit_with_autopm; | 69 | goto err_port_remove; |
80 | } | 70 | } |
81 | 71 | ||
82 | minor = port->minor; | 72 | usb_autopm_put_interface(port->serial->interface); |
83 | tty_register_device(usb_serial_tty_driver, minor, dev); | 73 | |
84 | dev_info(&port->serial->dev->dev, | 74 | dev_info(&port->serial->dev->dev, |
85 | "%s converter now attached to ttyUSB%d\n", | 75 | "%s converter now attached to ttyUSB%d\n", |
86 | driver->description, minor); | 76 | driver->description, minor); |
87 | 77 | ||
88 | exit_with_autopm: | 78 | return 0; |
79 | |||
80 | err_port_remove: | ||
81 | if (driver->port_remove) | ||
82 | driver->port_remove(port); | ||
83 | err_autopm_put: | ||
89 | usb_autopm_put_interface(port->serial->interface); | 84 | usb_autopm_put_interface(port->serial->interface); |
90 | exit: | 85 | |
91 | return retval; | 86 | return retval; |
92 | } | 87 | } |
93 | 88 | ||
@@ -114,8 +109,6 @@ static int usb_serial_device_remove(struct device *dev) | |||
114 | minor = port->minor; | 109 | minor = port->minor; |
115 | tty_unregister_device(usb_serial_tty_driver, minor); | 110 | tty_unregister_device(usb_serial_tty_driver, minor); |
116 | 111 | ||
117 | device_remove_file(&port->dev, &dev_attr_port_number); | ||
118 | |||
119 | driver = port->serial->type; | 112 | driver = port->serial->type; |
120 | if (driver->port_remove) | 113 | if (driver->port_remove) |
121 | retval = driver->port_remove(port); | 114 | retval = driver->port_remove(port); |
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index 2d72aa3564a3..ede4f5fcfadd 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c | |||
@@ -84,6 +84,10 @@ struct ch341_private { | |||
84 | u8 line_status; /* active status of modem control inputs */ | 84 | u8 line_status; /* active status of modem control inputs */ |
85 | }; | 85 | }; |
86 | 86 | ||
87 | static void ch341_set_termios(struct tty_struct *tty, | ||
88 | struct usb_serial_port *port, | ||
89 | struct ktermios *old_termios); | ||
90 | |||
87 | static int ch341_control_out(struct usb_device *dev, u8 request, | 91 | static int ch341_control_out(struct usb_device *dev, u8 request, |
88 | u16 value, u16 index) | 92 | u16 value, u16 index) |
89 | { | 93 | { |
@@ -309,19 +313,12 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
309 | struct ch341_private *priv = usb_get_serial_port_data(port); | 313 | struct ch341_private *priv = usb_get_serial_port_data(port); |
310 | int r; | 314 | int r; |
311 | 315 | ||
312 | priv->baud_rate = DEFAULT_BAUD_RATE; | ||
313 | |||
314 | r = ch341_configure(serial->dev, priv); | 316 | r = ch341_configure(serial->dev, priv); |
315 | if (r) | 317 | if (r) |
316 | goto out; | 318 | goto out; |
317 | 319 | ||
318 | r = ch341_set_handshake(serial->dev, priv->line_control); | 320 | if (tty) |
319 | if (r) | 321 | ch341_set_termios(tty, port, NULL); |
320 | goto out; | ||
321 | |||
322 | r = ch341_set_baudrate(serial->dev, priv); | ||
323 | if (r) | ||
324 | goto out; | ||
325 | 322 | ||
326 | dev_dbg(&port->dev, "%s - submitting interrupt urb\n", __func__); | 323 | dev_dbg(&port->dev, "%s - submitting interrupt urb\n", __func__); |
327 | r = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); | 324 | r = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); |
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 29fa1c3d0089..3806e7014199 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 14 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
15 | 15 | ||
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/module.h> | ||
17 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
18 | #include <linux/tty.h> | 19 | #include <linux/tty.h> |
19 | #include <linux/console.h> | 20 | #include <linux/console.h> |
@@ -144,6 +145,7 @@ static int usb_console_setup(struct console *co, char *options) | |||
144 | init_ldsem(&tty->ldisc_sem); | 145 | init_ldsem(&tty->ldisc_sem); |
145 | INIT_LIST_HEAD(&tty->tty_files); | 146 | INIT_LIST_HEAD(&tty->tty_files); |
146 | kref_get(&tty->driver->kref); | 147 | kref_get(&tty->driver->kref); |
148 | __module_get(tty->driver->owner); | ||
147 | tty->ops = &usb_console_fake_tty_ops; | 149 | tty->ops = &usb_console_fake_tty_ops; |
148 | if (tty_init_termios(tty)) { | 150 | if (tty_init_termios(tty)) { |
149 | retval = -ENOMEM; | 151 | retval = -ENOMEM; |
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index f40c856ff758..84ce2d74894c 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c | |||
@@ -147,6 +147,8 @@ static const struct usb_device_id id_table[] = { | |||
147 | { USB_DEVICE(0x166A, 0x0305) }, /* Clipsal C-5000CT2 C-Bus Spectrum Colour Touchscreen */ | 147 | { USB_DEVICE(0x166A, 0x0305) }, /* Clipsal C-5000CT2 C-Bus Spectrum Colour Touchscreen */ |
148 | { USB_DEVICE(0x166A, 0x0401) }, /* Clipsal L51xx C-Bus Architectural Dimmer */ | 148 | { USB_DEVICE(0x166A, 0x0401) }, /* Clipsal L51xx C-Bus Architectural Dimmer */ |
149 | { USB_DEVICE(0x166A, 0x0101) }, /* Clipsal 5560884 C-Bus Multi-room Audio Matrix Switcher */ | 149 | { USB_DEVICE(0x166A, 0x0101) }, /* Clipsal 5560884 C-Bus Multi-room Audio Matrix Switcher */ |
150 | { USB_DEVICE(0x16C0, 0x09B0) }, /* Lunatico Seletek */ | ||
151 | { USB_DEVICE(0x16C0, 0x09B1) }, /* Lunatico Seletek */ | ||
150 | { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */ | 152 | { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */ |
151 | { USB_DEVICE(0x16DC, 0x0010) }, /* W-IE-NE-R Plein & Baus GmbH PL512 Power Supply */ | 153 | { USB_DEVICE(0x16DC, 0x0010) }, /* W-IE-NE-R Plein & Baus GmbH PL512 Power Supply */ |
152 | { USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */ | 154 | { USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */ |
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 1ebb351b9e9a..3086dec0ef53 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -799,6 +799,8 @@ static const struct usb_device_id id_table_combined[] = { | |||
799 | { USB_DEVICE(FTDI_VID, FTDI_ELSTER_UNICOM_PID) }, | 799 | { USB_DEVICE(FTDI_VID, FTDI_ELSTER_UNICOM_PID) }, |
800 | { USB_DEVICE(FTDI_VID, FTDI_PROPOX_JTAGCABLEII_PID) }, | 800 | { USB_DEVICE(FTDI_VID, FTDI_PROPOX_JTAGCABLEII_PID) }, |
801 | { USB_DEVICE(FTDI_VID, FTDI_PROPOX_ISPCABLEIII_PID) }, | 801 | { USB_DEVICE(FTDI_VID, FTDI_PROPOX_ISPCABLEIII_PID) }, |
802 | { USB_DEVICE(FTDI_VID, CYBER_CORTEX_AV_PID), | ||
803 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, | ||
802 | { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID), | 804 | { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID), |
803 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, | 805 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, |
804 | { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID), | 806 | { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID), |
@@ -978,6 +980,23 @@ static const struct usb_device_id id_table_combined[] = { | |||
978 | { USB_DEVICE_INTERFACE_NUMBER(INFINEON_VID, INFINEON_TRIBOARD_PID, 1) }, | 980 | { USB_DEVICE_INTERFACE_NUMBER(INFINEON_VID, INFINEON_TRIBOARD_PID, 1) }, |
979 | /* GE Healthcare devices */ | 981 | /* GE Healthcare devices */ |
980 | { USB_DEVICE(GE_HEALTHCARE_VID, GE_HEALTHCARE_NEMO_TRACKER_PID) }, | 982 | { USB_DEVICE(GE_HEALTHCARE_VID, GE_HEALTHCARE_NEMO_TRACKER_PID) }, |
983 | /* Active Research (Actisense) devices */ | ||
984 | { USB_DEVICE(FTDI_VID, ACTISENSE_NDC_PID) }, | ||
985 | { USB_DEVICE(FTDI_VID, ACTISENSE_USG_PID) }, | ||
986 | { USB_DEVICE(FTDI_VID, ACTISENSE_NGT_PID) }, | ||
987 | { USB_DEVICE(FTDI_VID, ACTISENSE_NGW_PID) }, | ||
988 | { USB_DEVICE(FTDI_VID, ACTISENSE_D9AC_PID) }, | ||
989 | { USB_DEVICE(FTDI_VID, ACTISENSE_D9AD_PID) }, | ||
990 | { USB_DEVICE(FTDI_VID, ACTISENSE_D9AE_PID) }, | ||
991 | { USB_DEVICE(FTDI_VID, ACTISENSE_D9AF_PID) }, | ||
992 | { USB_DEVICE(FTDI_VID, CHETCO_SEAGAUGE_PID) }, | ||
993 | { USB_DEVICE(FTDI_VID, CHETCO_SEASWITCH_PID) }, | ||
994 | { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_NMEA2000_PID) }, | ||
995 | { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_ETHERNET_PID) }, | ||
996 | { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_WIFI_PID) }, | ||
997 | { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_DISPLAY_PID) }, | ||
998 | { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_LITE_PID) }, | ||
999 | { USB_DEVICE(FTDI_VID, CHETCO_SEASMART_ANALOG_PID) }, | ||
981 | { } /* Terminating entry */ | 1000 | { } /* Terminating entry */ |
982 | }; | 1001 | }; |
983 | 1002 | ||
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index e52409c9be99..56b1b55c4751 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h | |||
@@ -38,6 +38,9 @@ | |||
38 | 38 | ||
39 | #define FTDI_LUMEL_PD12_PID 0x6002 | 39 | #define FTDI_LUMEL_PD12_PID 0x6002 |
40 | 40 | ||
41 | /* Cyber Cortex AV by Fabulous Silicon (http://fabuloussilicon.com) */ | ||
42 | #define CYBER_CORTEX_AV_PID 0x8698 | ||
43 | |||
41 | /* | 44 | /* |
42 | * Marvell OpenRD Base, Client | 45 | * Marvell OpenRD Base, Client |
43 | * http://www.open-rd.org | 46 | * http://www.open-rd.org |
@@ -1438,3 +1441,23 @@ | |||
1438 | */ | 1441 | */ |
1439 | #define GE_HEALTHCARE_VID 0x1901 | 1442 | #define GE_HEALTHCARE_VID 0x1901 |
1440 | #define GE_HEALTHCARE_NEMO_TRACKER_PID 0x0015 | 1443 | #define GE_HEALTHCARE_NEMO_TRACKER_PID 0x0015 |
1444 | |||
1445 | /* | ||
1446 | * Active Research (Actisense) devices | ||
1447 | */ | ||
1448 | #define ACTISENSE_NDC_PID 0xD9A8 /* NDC USB Serial Adapter */ | ||
1449 | #define ACTISENSE_USG_PID 0xD9A9 /* USG USB Serial Adapter */ | ||
1450 | #define ACTISENSE_NGT_PID 0xD9AA /* NGT NMEA2000 Interface */ | ||
1451 | #define ACTISENSE_NGW_PID 0xD9AB /* NGW NMEA2000 Gateway */ | ||
1452 | #define ACTISENSE_D9AC_PID 0xD9AC /* Actisense Reserved */ | ||
1453 | #define ACTISENSE_D9AD_PID 0xD9AD /* Actisense Reserved */ | ||
1454 | #define ACTISENSE_D9AE_PID 0xD9AE /* Actisense Reserved */ | ||
1455 | #define ACTISENSE_D9AF_PID 0xD9AF /* Actisense Reserved */ | ||
1456 | #define CHETCO_SEAGAUGE_PID 0xA548 /* SeaGauge USB Adapter */ | ||
1457 | #define CHETCO_SEASWITCH_PID 0xA549 /* SeaSwitch USB Adapter */ | ||
1458 | #define CHETCO_SEASMART_NMEA2000_PID 0xA54A /* SeaSmart NMEA2000 Gateway */ | ||
1459 | #define CHETCO_SEASMART_ETHERNET_PID 0xA54B /* SeaSmart Ethernet Gateway */ | ||
1460 | #define CHETCO_SEASMART_WIFI_PID 0xA5AC /* SeaSmart Wifi Gateway */ | ||
1461 | #define CHETCO_SEASMART_DISPLAY_PID 0xA5AD /* SeaSmart NMEA2000 Display */ | ||
1462 | #define CHETCO_SEASMART_LITE_PID 0xA5AE /* SeaSmart Lite USB Adapter */ | ||
1463 | #define CHETCO_SEASMART_ANALOG_PID 0xA5AF /* SeaSmart Analog Adapter */ | ||
diff --git a/drivers/usb/serial/mxuport.c b/drivers/usb/serial/mxuport.c index ab1d690274ae..460a40669967 100644 --- a/drivers/usb/serial/mxuport.c +++ b/drivers/usb/serial/mxuport.c | |||
@@ -1284,7 +1284,8 @@ static int mxuport_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
1284 | } | 1284 | } |
1285 | 1285 | ||
1286 | /* Initial port termios */ | 1286 | /* Initial port termios */ |
1287 | mxuport_set_termios(tty, port, NULL); | 1287 | if (tty) |
1288 | mxuport_set_termios(tty, port, NULL); | ||
1288 | 1289 | ||
1289 | /* | 1290 | /* |
1290 | * TODO: use RQ_VENDOR_GET_MSR, once we know what it | 1291 | * TODO: use RQ_VENDOR_GET_MSR, once we know what it |
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 0f872e6b2c87..829604d11f3f 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c | |||
@@ -132,6 +132,7 @@ MODULE_DEVICE_TABLE(usb, id_table); | |||
132 | #define UART_OVERRUN_ERROR 0x40 | 132 | #define UART_OVERRUN_ERROR 0x40 |
133 | #define UART_CTS 0x80 | 133 | #define UART_CTS 0x80 |
134 | 134 | ||
135 | static void pl2303_set_break(struct usb_serial_port *port, bool enable); | ||
135 | 136 | ||
136 | enum pl2303_type { | 137 | enum pl2303_type { |
137 | TYPE_01, /* Type 0 and 1 (difference unknown) */ | 138 | TYPE_01, /* Type 0 and 1 (difference unknown) */ |
@@ -615,6 +616,7 @@ static void pl2303_close(struct usb_serial_port *port) | |||
615 | { | 616 | { |
616 | usb_serial_generic_close(port); | 617 | usb_serial_generic_close(port); |
617 | usb_kill_urb(port->interrupt_in_urb); | 618 | usb_kill_urb(port->interrupt_in_urb); |
619 | pl2303_set_break(port, false); | ||
618 | } | 620 | } |
619 | 621 | ||
620 | static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port) | 622 | static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port) |
@@ -741,17 +743,16 @@ static int pl2303_ioctl(struct tty_struct *tty, | |||
741 | return -ENOIOCTLCMD; | 743 | return -ENOIOCTLCMD; |
742 | } | 744 | } |
743 | 745 | ||
744 | static void pl2303_break_ctl(struct tty_struct *tty, int break_state) | 746 | static void pl2303_set_break(struct usb_serial_port *port, bool enable) |
745 | { | 747 | { |
746 | struct usb_serial_port *port = tty->driver_data; | ||
747 | struct usb_serial *serial = port->serial; | 748 | struct usb_serial *serial = port->serial; |
748 | u16 state; | 749 | u16 state; |
749 | int result; | 750 | int result; |
750 | 751 | ||
751 | if (break_state == 0) | 752 | if (enable) |
752 | state = BREAK_OFF; | ||
753 | else | ||
754 | state = BREAK_ON; | 753 | state = BREAK_ON; |
754 | else | ||
755 | state = BREAK_OFF; | ||
755 | 756 | ||
756 | dev_dbg(&port->dev, "%s - turning break %s\n", __func__, | 757 | dev_dbg(&port->dev, "%s - turning break %s\n", __func__, |
757 | state == BREAK_OFF ? "off" : "on"); | 758 | state == BREAK_OFF ? "off" : "on"); |
@@ -763,6 +764,13 @@ static void pl2303_break_ctl(struct tty_struct *tty, int break_state) | |||
763 | dev_err(&port->dev, "error sending break = %d\n", result); | 764 | dev_err(&port->dev, "error sending break = %d\n", result); |
764 | } | 765 | } |
765 | 766 | ||
767 | static void pl2303_break_ctl(struct tty_struct *tty, int state) | ||
768 | { | ||
769 | struct usb_serial_port *port = tty->driver_data; | ||
770 | |||
771 | pl2303_set_break(port, state); | ||
772 | } | ||
773 | |||
766 | static void pl2303_update_line_status(struct usb_serial_port *port, | 774 | static void pl2303_update_line_status(struct usb_serial_port *port, |
767 | unsigned char *data, | 775 | unsigned char *data, |
768 | unsigned int actual_length) | 776 | unsigned int actual_length) |
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 475723c006f9..529066bbc7e8 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -687,6 +687,21 @@ static void serial_port_dtr_rts(struct tty_port *port, int on) | |||
687 | drv->dtr_rts(p, on); | 687 | drv->dtr_rts(p, on); |
688 | } | 688 | } |
689 | 689 | ||
690 | static ssize_t port_number_show(struct device *dev, | ||
691 | struct device_attribute *attr, char *buf) | ||
692 | { | ||
693 | struct usb_serial_port *port = to_usb_serial_port(dev); | ||
694 | |||
695 | return sprintf(buf, "%u\n", port->port_number); | ||
696 | } | ||
697 | static DEVICE_ATTR_RO(port_number); | ||
698 | |||
699 | static struct attribute *usb_serial_port_attrs[] = { | ||
700 | &dev_attr_port_number.attr, | ||
701 | NULL | ||
702 | }; | ||
703 | ATTRIBUTE_GROUPS(usb_serial_port); | ||
704 | |||
690 | static const struct tty_port_operations serial_port_ops = { | 705 | static const struct tty_port_operations serial_port_ops = { |
691 | .carrier_raised = serial_port_carrier_raised, | 706 | .carrier_raised = serial_port_carrier_raised, |
692 | .dtr_rts = serial_port_dtr_rts, | 707 | .dtr_rts = serial_port_dtr_rts, |
@@ -902,6 +917,7 @@ static int usb_serial_probe(struct usb_interface *interface, | |||
902 | port->dev.driver = NULL; | 917 | port->dev.driver = NULL; |
903 | port->dev.bus = &usb_serial_bus_type; | 918 | port->dev.bus = &usb_serial_bus_type; |
904 | port->dev.release = &usb_serial_port_release; | 919 | port->dev.release = &usb_serial_port_release; |
920 | port->dev.groups = usb_serial_port_groups; | ||
905 | device_initialize(&port->dev); | 921 | device_initialize(&port->dev); |
906 | } | 922 | } |
907 | 923 | ||
@@ -940,8 +956,9 @@ static int usb_serial_probe(struct usb_interface *interface, | |||
940 | port = serial->port[i]; | 956 | port = serial->port[i]; |
941 | if (kfifo_alloc(&port->write_fifo, PAGE_SIZE, GFP_KERNEL)) | 957 | if (kfifo_alloc(&port->write_fifo, PAGE_SIZE, GFP_KERNEL)) |
942 | goto probe_error; | 958 | goto probe_error; |
943 | buffer_size = max_t(int, serial->type->bulk_out_size, | 959 | buffer_size = serial->type->bulk_out_size; |
944 | usb_endpoint_maxp(endpoint)); | 960 | if (!buffer_size) |
961 | buffer_size = usb_endpoint_maxp(endpoint); | ||
945 | port->bulk_out_size = buffer_size; | 962 | port->bulk_out_size = buffer_size; |
946 | port->bulk_out_endpointAddress = endpoint->bEndpointAddress; | 963 | port->bulk_out_endpointAddress = endpoint->bEndpointAddress; |
947 | 964 | ||
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 9bb547c7bce7..704a1ab8240c 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h | |||
@@ -190,8 +190,7 @@ static inline void usb_set_serial_data(struct usb_serial *serial, void *data) | |||
190 | * @num_ports: the number of different ports this device will have. | 190 | * @num_ports: the number of different ports this device will have. |
191 | * @bulk_in_size: minimum number of bytes to allocate for bulk-in buffer | 191 | * @bulk_in_size: minimum number of bytes to allocate for bulk-in buffer |
192 | * (0 = end-point size) | 192 | * (0 = end-point size) |
193 | * @bulk_out_size: minimum number of bytes to allocate for bulk-out buffer | 193 | * @bulk_out_size: bytes to allocate for bulk-out buffer (0 = end-point size) |
194 | * (0 = end-point size) | ||
195 | * @calc_num_ports: pointer to a function to determine how many ports this | 194 | * @calc_num_ports: pointer to a function to determine how many ports this |
196 | * device has dynamically. It will be called after the probe() | 195 | * device has dynamically. It will be called after the probe() |
197 | * callback is called, but before attach() | 196 | * callback is called, but before attach() |