diff options
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r-- | drivers/usb/serial/Kconfig | 9 | ||||
-rw-r--r-- | drivers/usb/serial/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/serial/cp210x.c | 4 | ||||
-rw-r--r-- | drivers/usb/serial/digi_acceleport.c | 14 | ||||
-rw-r--r-- | drivers/usb/serial/ftdi_sio.c | 4 | ||||
-rw-r--r-- | drivers/usb/serial/ftdi_sio_ids.h | 10 | ||||
-rw-r--r-- | drivers/usb/serial/generic.c | 15 | ||||
-rw-r--r-- | drivers/usb/serial/io_ti.c | 4 | ||||
-rw-r--r-- | drivers/usb/serial/ipaq.c | 1 | ||||
-rw-r--r-- | drivers/usb/serial/iuu_phoenix.c | 54 | ||||
-rw-r--r-- | drivers/usb/serial/option.c | 17 | ||||
-rw-r--r-- | drivers/usb/serial/ssu100.c | 698 | ||||
-rw-r--r-- | drivers/usb/serial/usb-serial.c | 32 |
13 files changed, 817 insertions, 46 deletions
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index bd8aab0ef1cf..916b2b6d765f 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig | |||
@@ -642,6 +642,15 @@ config USB_SERIAL_ZIO | |||
642 | To compile this driver as a module, choose M here: the | 642 | To compile this driver as a module, choose M here: the |
643 | module will be called zio. | 643 | module will be called zio. |
644 | 644 | ||
645 | config USB_SERIAL_SSU100 | ||
646 | tristate "USB Quatech SSU-100 Single Port Serial Driver" | ||
647 | help | ||
648 | Say Y here if you want to use the Quatech SSU-100 single | ||
649 | port usb to serial adapter. | ||
650 | |||
651 | To compile this driver as a module, choose M here: the | ||
652 | module will be called ssu100. | ||
653 | |||
645 | config USB_SERIAL_DEBUG | 654 | config USB_SERIAL_DEBUG |
646 | tristate "USB Debugging Device" | 655 | tristate "USB Debugging Device" |
647 | help | 656 | help |
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index e54c728c016e..40ebe17b6ea8 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile | |||
@@ -51,6 +51,7 @@ obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o | |||
51 | obj-$(CONFIG_USB_SERIAL_SIEMENS_MPI) += siemens_mpi.o | 51 | obj-$(CONFIG_USB_SERIAL_SIEMENS_MPI) += siemens_mpi.o |
52 | obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o | 52 | obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o |
53 | obj-$(CONFIG_USB_SERIAL_SPCP8X5) += spcp8x5.o | 53 | obj-$(CONFIG_USB_SERIAL_SPCP8X5) += spcp8x5.o |
54 | obj-$(CONFIG_USB_SERIAL_SSU100) += ssu100.o | ||
54 | obj-$(CONFIG_USB_SERIAL_SYMBOL) += symbolserial.o | 55 | obj-$(CONFIG_USB_SERIAL_SYMBOL) += symbolserial.o |
55 | obj-$(CONFIG_USB_SERIAL_WWAN) += usb_wwan.o | 56 | obj-$(CONFIG_USB_SERIAL_WWAN) += usb_wwan.o |
56 | obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o | 57 | obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o |
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 8b8c7976b4c0..2bef4415c19c 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c | |||
@@ -126,6 +126,10 @@ static const struct usb_device_id id_table[] = { | |||
126 | { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */ | 126 | { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */ |
127 | { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ | 127 | { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ |
128 | { USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */ | 128 | { USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */ |
129 | { USB_DEVICE(0x16DC, 0x0010) }, /* W-IE-NE-R Plein & Baus GmbH PL512 Power Supply */ | ||
130 | { USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */ | ||
131 | { USB_DEVICE(0x16DC, 0x0012) }, /* W-IE-NE-R Plein & Baus GmbH MPOD Multi Channel Power Supply */ | ||
132 | { USB_DEVICE(0x16DC, 0x0015) }, /* W-IE-NE-R Plein & Baus GmbH CML Control, Monitoring and Data Logger */ | ||
129 | { } /* Terminating Entry */ | 133 | { } /* Terminating Entry */ |
130 | }; | 134 | }; |
131 | 135 | ||
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index fd35f73b5721..b92070c103cd 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c | |||
@@ -609,8 +609,10 @@ static void digi_wakeup_write_lock(struct work_struct *work) | |||
609 | static void digi_wakeup_write(struct usb_serial_port *port) | 609 | static void digi_wakeup_write(struct usb_serial_port *port) |
610 | { | 610 | { |
611 | struct tty_struct *tty = tty_port_tty_get(&port->port); | 611 | struct tty_struct *tty = tty_port_tty_get(&port->port); |
612 | tty_wakeup(tty); | 612 | if (tty) { |
613 | tty_kref_put(tty); | 613 | tty_wakeup(tty); |
614 | tty_kref_put(tty); | ||
615 | } | ||
614 | } | 616 | } |
615 | 617 | ||
616 | 618 | ||
@@ -1682,7 +1684,7 @@ static int digi_read_inb_callback(struct urb *urb) | |||
1682 | priv->dp_throttle_restart = 1; | 1684 | priv->dp_throttle_restart = 1; |
1683 | 1685 | ||
1684 | /* receive data */ | 1686 | /* receive data */ |
1685 | if (opcode == DIGI_CMD_RECEIVE_DATA) { | 1687 | if (tty && opcode == DIGI_CMD_RECEIVE_DATA) { |
1686 | /* get flag from port_status */ | 1688 | /* get flag from port_status */ |
1687 | flag = 0; | 1689 | flag = 0; |
1688 | 1690 | ||
@@ -1763,10 +1765,12 @@ static int digi_read_oob_callback(struct urb *urb) | |||
1763 | return -1; | 1765 | return -1; |
1764 | 1766 | ||
1765 | tty = tty_port_tty_get(&port->port); | 1767 | tty = tty_port_tty_get(&port->port); |
1768 | |||
1766 | rts = 0; | 1769 | rts = 0; |
1767 | rts = tty->termios->c_cflag & CRTSCTS; | 1770 | if (tty) |
1771 | rts = tty->termios->c_cflag & CRTSCTS; | ||
1768 | 1772 | ||
1769 | if (opcode == DIGI_CMD_READ_INPUT_SIGNALS) { | 1773 | if (tty && opcode == DIGI_CMD_READ_INPUT_SIGNALS) { |
1770 | spin_lock(&priv->dp_port_lock); | 1774 | spin_lock(&priv->dp_port_lock); |
1771 | /* convert from digi flags to termiox flags */ | 1775 | /* convert from digi flags to termiox flags */ |
1772 | if (val & DIGI_READ_INPUT_SIGNALS_CTS) { | 1776 | if (val & DIGI_READ_INPUT_SIGNALS_CTS) { |
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index e34023ff5771..4fc588cc4716 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -157,6 +157,9 @@ static struct usb_device_id id_table_combined [] = { | |||
157 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_5_PID) }, | 157 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_5_PID) }, |
158 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_6_PID) }, | 158 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_6_PID) }, |
159 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_7_PID) }, | 159 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_7_PID) }, |
160 | { USB_DEVICE(FTDI_VID, FTDI_USINT_CAT_PID) }, | ||
161 | { USB_DEVICE(FTDI_VID, FTDI_USINT_WKEY_PID) }, | ||
162 | { USB_DEVICE(FTDI_VID, FTDI_USINT_RS232_PID) }, | ||
160 | { USB_DEVICE(FTDI_VID, FTDI_ACTZWAVE_PID) }, | 163 | { USB_DEVICE(FTDI_VID, FTDI_ACTZWAVE_PID) }, |
161 | { USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) }, | 164 | { USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) }, |
162 | { USB_DEVICE(FTDI_VID, FTDI_IPLUS_PID) }, | 165 | { USB_DEVICE(FTDI_VID, FTDI_IPLUS_PID) }, |
@@ -746,6 +749,7 @@ static struct usb_device_id id_table_combined [] = { | |||
746 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, | 749 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, |
747 | { USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SH4_PID), | 750 | { USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SH4_PID), |
748 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, | 751 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, |
752 | { USB_DEVICE(FTDI_VID, SEGWAY_RMP200_PID) }, | ||
749 | { }, /* Optional parameter entry */ | 753 | { }, /* Optional parameter entry */ |
750 | { } /* Terminating entry */ | 754 | { } /* Terminating entry */ |
751 | }; | 755 | }; |
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index d01946db8fac..6e612c52e763 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h | |||
@@ -40,6 +40,11 @@ | |||
40 | 40 | ||
41 | #define FTDI_NXTCAM_PID 0xABB8 /* NXTCam for Mindstorms NXT */ | 41 | #define FTDI_NXTCAM_PID 0xABB8 /* NXTCam for Mindstorms NXT */ |
42 | 42 | ||
43 | /* US Interface Navigator (http://www.usinterface.com/) */ | ||
44 | #define FTDI_USINT_CAT_PID 0xb810 /* Navigator CAT and 2nd PTT lines */ | ||
45 | #define FTDI_USINT_WKEY_PID 0xb811 /* Navigator WKEY and FSK lines */ | ||
46 | #define FTDI_USINT_RS232_PID 0xb812 /* Navigator RS232 and CONFIG lines */ | ||
47 | |||
43 | /* OOCDlink by Joern Kaipf <joernk@web.de> | 48 | /* OOCDlink by Joern Kaipf <joernk@web.de> |
44 | * (http://www.joernonline.de/dw/doku.php?id=start&idx=projects:oocdlink) */ | 49 | * (http://www.joernonline.de/dw/doku.php?id=start&idx=projects:oocdlink) */ |
45 | #define FTDI_OOCDLINK_PID 0xbaf8 /* Amontec JTAGkey */ | 50 | #define FTDI_OOCDLINK_PID 0xbaf8 /* Amontec JTAGkey */ |
@@ -1032,3 +1037,8 @@ | |||
1032 | #define XVERVE_SIGNALYZER_SH2_PID 0xBCA2 | 1037 | #define XVERVE_SIGNALYZER_SH2_PID 0xBCA2 |
1033 | #define XVERVE_SIGNALYZER_SH4_PID 0xBCA4 | 1038 | #define XVERVE_SIGNALYZER_SH4_PID 0xBCA4 |
1034 | 1039 | ||
1040 | /* | ||
1041 | * Segway Robotic Mobility Platform USB interface (using VID 0x0403) | ||
1042 | * Submitted by John G. Rogers | ||
1043 | */ | ||
1044 | #define SEGWAY_RMP200_PID 0xe729 | ||
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index a817ced82835..ca92f67747cc 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c | |||
@@ -208,18 +208,23 @@ retry: | |||
208 | urb->transfer_buffer_length = count; | 208 | urb->transfer_buffer_length = count; |
209 | usb_serial_debug_data(debug, &port->dev, __func__, count, | 209 | usb_serial_debug_data(debug, &port->dev, __func__, count, |
210 | urb->transfer_buffer); | 210 | urb->transfer_buffer); |
211 | spin_lock_irqsave(&port->lock, flags); | ||
212 | port->tx_bytes += count; | ||
213 | spin_unlock_irqrestore(&port->lock, flags); | ||
214 | |||
215 | clear_bit(i, &port->write_urbs_free); | ||
211 | result = usb_submit_urb(urb, GFP_ATOMIC); | 216 | result = usb_submit_urb(urb, GFP_ATOMIC); |
212 | if (result) { | 217 | if (result) { |
213 | dev_err(&port->dev, "%s - error submitting urb: %d\n", | 218 | dev_err(&port->dev, "%s - error submitting urb: %d\n", |
214 | __func__, result); | 219 | __func__, result); |
220 | set_bit(i, &port->write_urbs_free); | ||
221 | spin_lock_irqsave(&port->lock, flags); | ||
222 | port->tx_bytes -= count; | ||
223 | spin_unlock_irqrestore(&port->lock, flags); | ||
224 | |||
215 | clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags); | 225 | clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags); |
216 | return result; | 226 | return result; |
217 | } | 227 | } |
218 | clear_bit(i, &port->write_urbs_free); | ||
219 | |||
220 | spin_lock_irqsave(&port->lock, flags); | ||
221 | port->tx_bytes += count; | ||
222 | spin_unlock_irqrestore(&port->lock, flags); | ||
223 | 228 | ||
224 | /* Try sending off another urb, unless in irq context (in which case | 229 | /* Try sending off another urb, unless in irq context (in which case |
225 | * there will be no free urb). */ | 230 | * there will be no free urb). */ |
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 4a6da66d5fd2..9d6be304dff9 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c | |||
@@ -1298,7 +1298,7 @@ static int download_fw(struct edgeport_serial *serial) | |||
1298 | kfree(header); | 1298 | kfree(header); |
1299 | kfree(rom_desc); | 1299 | kfree(rom_desc); |
1300 | kfree(ti_manuf_desc); | 1300 | kfree(ti_manuf_desc); |
1301 | return status; | 1301 | return -EINVAL; |
1302 | } | 1302 | } |
1303 | 1303 | ||
1304 | /* verify the write -- must do this in order for | 1304 | /* verify the write -- must do this in order for |
@@ -1321,7 +1321,7 @@ static int download_fw(struct edgeport_serial *serial) | |||
1321 | kfree(header); | 1321 | kfree(header); |
1322 | kfree(rom_desc); | 1322 | kfree(rom_desc); |
1323 | kfree(ti_manuf_desc); | 1323 | kfree(ti_manuf_desc); |
1324 | return status; | 1324 | return -EINVAL; |
1325 | } | 1325 | } |
1326 | 1326 | ||
1327 | kfree(vheader); | 1327 | kfree(vheader); |
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index 28913fa95fb7..4735931b4c7b 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c | |||
@@ -534,7 +534,6 @@ static struct usb_device_id ipaq_id_table [] = { | |||
534 | { USB_DEVICE(0x413C, 0x4009) }, /* Dell Axim USB Sync */ | 534 | { USB_DEVICE(0x413C, 0x4009) }, /* Dell Axim USB Sync */ |
535 | { USB_DEVICE(0x4505, 0x0010) }, /* Smartphone */ | 535 | { USB_DEVICE(0x4505, 0x0010) }, /* Smartphone */ |
536 | { USB_DEVICE(0x5E04, 0xCE00) }, /* SAGEM Wireless Assistant */ | 536 | { USB_DEVICE(0x5E04, 0xCE00) }, /* SAGEM Wireless Assistant */ |
537 | { USB_DEVICE(0x0BB4, 0x00CF) }, /* HTC smartphone modems */ | ||
538 | { } /* Terminating entry */ | 537 | { } /* Terminating entry */ |
539 | }; | 538 | }; |
540 | 539 | ||
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index 55766a65f0ad..12ed594f5f80 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c | |||
@@ -1,6 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Infinity Unlimited USB Phoenix driver | 2 | * Infinity Unlimited USB Phoenix driver |
3 | * | 3 | * |
4 | * Copyright (C) 2010 James Courtier-Dutton (James@superbug.co.uk) | ||
5 | |||
4 | * Copyright (C) 2007 Alain Degreffe (eczema@ecze.com) | 6 | * Copyright (C) 2007 Alain Degreffe (eczema@ecze.com) |
5 | * | 7 | * |
6 | * Original code taken from iuutool (Copyright (C) 2006 Juan Carlos Borrás) | 8 | * Original code taken from iuutool (Copyright (C) 2006 Juan Carlos Borrás) |
@@ -40,7 +42,7 @@ static int debug; | |||
40 | /* | 42 | /* |
41 | * Version Information | 43 | * Version Information |
42 | */ | 44 | */ |
43 | #define DRIVER_VERSION "v0.11" | 45 | #define DRIVER_VERSION "v0.12" |
44 | #define DRIVER_DESC "Infinity USB Unlimited Phoenix driver" | 46 | #define DRIVER_DESC "Infinity USB Unlimited Phoenix driver" |
45 | 47 | ||
46 | static const struct usb_device_id id_table[] = { | 48 | static const struct usb_device_id id_table[] = { |
@@ -81,6 +83,9 @@ struct iuu_private { | |||
81 | u8 *dbgbuf; /* debug buffer */ | 83 | u8 *dbgbuf; /* debug buffer */ |
82 | u8 len; | 84 | u8 len; |
83 | int vcc; /* vcc (either 3 or 5 V) */ | 85 | int vcc; /* vcc (either 3 or 5 V) */ |
86 | u32 baud; | ||
87 | u32 boost; | ||
88 | u32 clk; | ||
84 | }; | 89 | }; |
85 | 90 | ||
86 | 91 | ||
@@ -157,13 +162,14 @@ static int iuu_tiocmset(struct tty_struct *tty, struct file *file, | |||
157 | port->number, set, clear); | 162 | port->number, set, clear); |
158 | 163 | ||
159 | spin_lock_irqsave(&priv->lock, flags); | 164 | spin_lock_irqsave(&priv->lock, flags); |
160 | if (set & TIOCM_RTS) | ||
161 | priv->tiostatus = TIOCM_RTS; | ||
162 | 165 | ||
163 | if (!(set & TIOCM_RTS) && priv->tiostatus == TIOCM_RTS) { | 166 | if ((set & TIOCM_RTS) && !(priv->tiostatus == TIOCM_RTS)) { |
164 | dbg("%s TIOCMSET RESET called !!!", __func__); | 167 | dbg("%s TIOCMSET RESET called !!!", __func__); |
165 | priv->reset = 1; | 168 | priv->reset = 1; |
166 | } | 169 | } |
170 | if (set & TIOCM_RTS) | ||
171 | priv->tiostatus = TIOCM_RTS; | ||
172 | |||
167 | spin_unlock_irqrestore(&priv->lock, flags); | 173 | spin_unlock_irqrestore(&priv->lock, flags); |
168 | return 0; | 174 | return 0; |
169 | } | 175 | } |
@@ -850,20 +856,24 @@ static int iuu_uart_off(struct usb_serial_port *port) | |||
850 | return status; | 856 | return status; |
851 | } | 857 | } |
852 | 858 | ||
853 | static int iuu_uart_baud(struct usb_serial_port *port, u32 baud, | 859 | static int iuu_uart_baud(struct usb_serial_port *port, u32 baud_base, |
854 | u32 *actual, u8 parity) | 860 | u32 *actual, u8 parity) |
855 | { | 861 | { |
856 | int status; | 862 | int status; |
863 | u32 baud; | ||
857 | u8 *dataout; | 864 | u8 *dataout; |
858 | u8 DataCount = 0; | 865 | u8 DataCount = 0; |
859 | u8 T1Frekvens = 0; | 866 | u8 T1Frekvens = 0; |
860 | u8 T1reload = 0; | 867 | u8 T1reload = 0; |
861 | unsigned int T1FrekvensHZ = 0; | 868 | unsigned int T1FrekvensHZ = 0; |
862 | 869 | ||
870 | dbg("%s - enter baud_base=%d", __func__, baud_base); | ||
863 | dataout = kmalloc(sizeof(u8) * 5, GFP_KERNEL); | 871 | dataout = kmalloc(sizeof(u8) * 5, GFP_KERNEL); |
864 | 872 | ||
865 | if (!dataout) | 873 | if (!dataout) |
866 | return -ENOMEM; | 874 | return -ENOMEM; |
875 | /*baud = (((priv->clk / 35) * baud_base) / 100000); */ | ||
876 | baud = baud_base; | ||
867 | 877 | ||
868 | if (baud < 1200 || baud > 230400) { | 878 | if (baud < 1200 || baud > 230400) { |
869 | kfree(dataout); | 879 | kfree(dataout); |
@@ -947,15 +957,20 @@ static void iuu_set_termios(struct tty_struct *tty, | |||
947 | struct usb_serial_port *port, struct ktermios *old_termios) | 957 | struct usb_serial_port *port, struct ktermios *old_termios) |
948 | { | 958 | { |
949 | const u32 supported_mask = CMSPAR|PARENB|PARODD; | 959 | const u32 supported_mask = CMSPAR|PARENB|PARODD; |
950 | 960 | struct iuu_private *priv = usb_get_serial_port_data(port); | |
951 | unsigned int cflag = tty->termios->c_cflag; | 961 | unsigned int cflag = tty->termios->c_cflag; |
952 | int status; | 962 | int status; |
953 | u32 actual; | 963 | u32 actual; |
954 | u32 parity; | 964 | u32 parity; |
955 | int csize = CS7; | 965 | int csize = CS7; |
956 | int baud = 9600; /* Fixed for the moment */ | 966 | int baud; |
957 | u32 newval = cflag & supported_mask; | 967 | u32 newval = cflag & supported_mask; |
958 | 968 | ||
969 | /* Just use the ospeed. ispeed should be the same. */ | ||
970 | baud = tty->termios->c_ospeed; | ||
971 | |||
972 | dbg("%s - enter c_ospeed or baud=%d", __func__, baud); | ||
973 | |||
959 | /* compute the parity parameter */ | 974 | /* compute the parity parameter */ |
960 | parity = 0; | 975 | parity = 0; |
961 | if (cflag & CMSPAR) { /* Using mark space */ | 976 | if (cflag & CMSPAR) { /* Using mark space */ |
@@ -975,15 +990,15 @@ static void iuu_set_termios(struct tty_struct *tty, | |||
975 | 990 | ||
976 | /* set it */ | 991 | /* set it */ |
977 | status = iuu_uart_baud(port, | 992 | status = iuu_uart_baud(port, |
978 | (clockmode == 2) ? 16457 : 9600 * boost / 100, | 993 | baud * priv->boost / 100, |
979 | &actual, parity); | 994 | &actual, parity); |
980 | 995 | ||
981 | /* set the termios value to the real one, so the user now what has | 996 | /* set the termios value to the real one, so the user now what has |
982 | * changed. We support few fields so its easies to copy the old hw | 997 | * changed. We support few fields so its easies to copy the old hw |
983 | * settings back over and then adjust them | 998 | * settings back over and then adjust them |
984 | */ | 999 | */ |
985 | if (old_termios) | 1000 | if (old_termios) |
986 | tty_termios_copy_hw(tty->termios, old_termios); | 1001 | tty_termios_copy_hw(tty->termios, old_termios); |
987 | if (status != 0) /* Set failed - return old bits */ | 1002 | if (status != 0) /* Set failed - return old bits */ |
988 | return; | 1003 | return; |
989 | /* Re-encode speed, parity and csize */ | 1004 | /* Re-encode speed, parity and csize */ |
@@ -1017,6 +1032,7 @@ static void iuu_close(struct usb_serial_port *port) | |||
1017 | 1032 | ||
1018 | static void iuu_init_termios(struct tty_struct *tty) | 1033 | static void iuu_init_termios(struct tty_struct *tty) |
1019 | { | 1034 | { |
1035 | dbg("%s - enter", __func__); | ||
1020 | *(tty->termios) = tty_std_termios; | 1036 | *(tty->termios) = tty_std_termios; |
1021 | tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600 | 1037 | tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600 |
1022 | | TIOCM_CTS | CSTOPB | PARENB; | 1038 | | TIOCM_CTS | CSTOPB | PARENB; |
@@ -1032,10 +1048,16 @@ static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
1032 | struct usb_serial *serial = port->serial; | 1048 | struct usb_serial *serial = port->serial; |
1033 | u8 *buf; | 1049 | u8 *buf; |
1034 | int result; | 1050 | int result; |
1051 | int baud; | ||
1035 | u32 actual; | 1052 | u32 actual; |
1036 | struct iuu_private *priv = usb_get_serial_port_data(port); | 1053 | struct iuu_private *priv = usb_get_serial_port_data(port); |
1037 | 1054 | ||
1038 | dbg("%s - port %d", __func__, port->number); | 1055 | baud = tty->termios->c_ospeed; |
1056 | tty->termios->c_ispeed = baud; | ||
1057 | /* Re-encode speed */ | ||
1058 | tty_encode_baud_rate(tty, baud, baud); | ||
1059 | |||
1060 | dbg("%s - port %d, baud %d", __func__, port->number, baud); | ||
1039 | usb_clear_halt(serial->dev, port->write_urb->pipe); | 1061 | usb_clear_halt(serial->dev, port->write_urb->pipe); |
1040 | usb_clear_halt(serial->dev, port->read_urb->pipe); | 1062 | usb_clear_halt(serial->dev, port->read_urb->pipe); |
1041 | 1063 | ||
@@ -1070,23 +1092,29 @@ static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
1070 | iuu_uart_on(port); | 1092 | iuu_uart_on(port); |
1071 | if (boost < 100) | 1093 | if (boost < 100) |
1072 | boost = 100; | 1094 | boost = 100; |
1095 | priv->boost = boost; | ||
1096 | priv->baud = baud; | ||
1073 | switch (clockmode) { | 1097 | switch (clockmode) { |
1074 | case 2: /* 3.680 Mhz */ | 1098 | case 2: /* 3.680 Mhz */ |
1099 | priv->clk = IUU_CLK_3680000; | ||
1075 | iuu_clk(port, IUU_CLK_3680000 * boost / 100); | 1100 | iuu_clk(port, IUU_CLK_3680000 * boost / 100); |
1076 | result = | 1101 | result = |
1077 | iuu_uart_baud(port, 9600 * boost / 100, &actual, | 1102 | iuu_uart_baud(port, baud * boost / 100, &actual, |
1078 | IUU_PARITY_EVEN); | 1103 | IUU_PARITY_EVEN); |
1079 | break; | 1104 | break; |
1080 | case 3: /* 6.00 Mhz */ | 1105 | case 3: /* 6.00 Mhz */ |
1081 | iuu_clk(port, IUU_CLK_6000000 * boost / 100); | 1106 | iuu_clk(port, IUU_CLK_6000000 * boost / 100); |
1107 | priv->clk = IUU_CLK_6000000; | ||
1108 | /* Ratio of 6000000 to 3500000 for baud 9600 */ | ||
1082 | result = | 1109 | result = |
1083 | iuu_uart_baud(port, 16457 * boost / 100, &actual, | 1110 | iuu_uart_baud(port, 16457 * boost / 100, &actual, |
1084 | IUU_PARITY_EVEN); | 1111 | IUU_PARITY_EVEN); |
1085 | break; | 1112 | break; |
1086 | default: /* 3.579 Mhz */ | 1113 | default: /* 3.579 Mhz */ |
1087 | iuu_clk(port, IUU_CLK_3579000 * boost / 100); | 1114 | iuu_clk(port, IUU_CLK_3579000 * boost / 100); |
1115 | priv->clk = IUU_CLK_3579000; | ||
1088 | result = | 1116 | result = |
1089 | iuu_uart_baud(port, 9600 * boost / 100, &actual, | 1117 | iuu_uart_baud(port, baud * boost / 100, &actual, |
1090 | IUU_PARITY_EVEN); | 1118 | IUU_PARITY_EVEN); |
1091 | } | 1119 | } |
1092 | 1120 | ||
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 5cd30e4345c6..9fc6ea2c681f 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c | |||
@@ -145,7 +145,10 @@ static void option_instat_callback(struct urb *urb); | |||
145 | #define HUAWEI_PRODUCT_E143D 0x143D | 145 | #define HUAWEI_PRODUCT_E143D 0x143D |
146 | #define HUAWEI_PRODUCT_E143E 0x143E | 146 | #define HUAWEI_PRODUCT_E143E 0x143E |
147 | #define HUAWEI_PRODUCT_E143F 0x143F | 147 | #define HUAWEI_PRODUCT_E143F 0x143F |
148 | #define HUAWEI_PRODUCT_K4505 0x1464 | ||
149 | #define HUAWEI_PRODUCT_K3765 0x1465 | ||
148 | #define HUAWEI_PRODUCT_E14AC 0x14AC | 150 | #define HUAWEI_PRODUCT_E14AC 0x14AC |
151 | #define HUAWEI_PRODUCT_ETS1220 0x1803 | ||
149 | 152 | ||
150 | #define QUANTA_VENDOR_ID 0x0408 | 153 | #define QUANTA_VENDOR_ID 0x0408 |
151 | #define QUANTA_PRODUCT_Q101 0xEA02 | 154 | #define QUANTA_PRODUCT_Q101 0xEA02 |
@@ -264,9 +267,6 @@ static void option_instat_callback(struct urb *urb); | |||
264 | #define BANDRICH_PRODUCT_1011 0x1011 | 267 | #define BANDRICH_PRODUCT_1011 0x1011 |
265 | #define BANDRICH_PRODUCT_1012 0x1012 | 268 | #define BANDRICH_PRODUCT_1012 0x1012 |
266 | 269 | ||
267 | #define AMOI_VENDOR_ID 0x1614 | ||
268 | #define AMOI_PRODUCT_9508 0x0800 | ||
269 | |||
270 | #define QUALCOMM_VENDOR_ID 0x05C6 | 270 | #define QUALCOMM_VENDOR_ID 0x05C6 |
271 | 271 | ||
272 | #define CMOTECH_VENDOR_ID 0x16d8 | 272 | #define CMOTECH_VENDOR_ID 0x16d8 |
@@ -482,8 +482,10 @@ static const struct usb_device_id option_ids[] = { | |||
482 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143D, 0xff, 0xff, 0xff) }, | 482 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143D, 0xff, 0xff, 0xff) }, |
483 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143E, 0xff, 0xff, 0xff) }, | 483 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143E, 0xff, 0xff, 0xff) }, |
484 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143F, 0xff, 0xff, 0xff) }, | 484 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143F, 0xff, 0xff, 0xff) }, |
485 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff) }, | ||
486 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff) }, | ||
487 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ETS1220, 0xff, 0xff, 0xff) }, | ||
485 | { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC) }, | 488 | { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC) }, |
486 | { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_9508) }, | ||
487 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, /* Novatel Merlin V640/XV620 */ | 489 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, /* Novatel Merlin V640/XV620 */ |
488 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, /* Novatel Merlin V620/S620 */ | 490 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, /* Novatel Merlin V620/S620 */ |
489 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) }, /* Novatel Merlin EX720/V740/X720 */ | 491 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) }, /* Novatel Merlin EX720/V740/X720 */ |
@@ -1017,6 +1019,13 @@ static int option_probe(struct usb_serial *serial, | |||
1017 | serial->interface->cur_altsetting->desc.bInterfaceClass != 0xff) | 1019 | serial->interface->cur_altsetting->desc.bInterfaceClass != 0xff) |
1018 | return -ENODEV; | 1020 | return -ENODEV; |
1019 | 1021 | ||
1022 | /* Don't bind network interfaces on Huawei K3765 & K4505 */ | ||
1023 | if (serial->dev->descriptor.idVendor == HUAWEI_VENDOR_ID && | ||
1024 | (serial->dev->descriptor.idProduct == HUAWEI_PRODUCT_K3765 || | ||
1025 | serial->dev->descriptor.idProduct == HUAWEI_PRODUCT_K4505) && | ||
1026 | serial->interface->cur_altsetting->desc.bInterfaceNumber == 1) | ||
1027 | return -ENODEV; | ||
1028 | |||
1020 | data = serial->private = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL); | 1029 | data = serial->private = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL); |
1021 | 1030 | ||
1022 | if (!data) | 1031 | if (!data) |
diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c new file mode 100644 index 000000000000..6e82d4f54bc8 --- /dev/null +++ b/drivers/usb/serial/ssu100.c | |||
@@ -0,0 +1,698 @@ | |||
1 | /* | ||
2 | * usb-serial driver for Quatech SSU-100 | ||
3 | * | ||
4 | * based on ftdi_sio.c and the original serqt_usb.c from Quatech | ||
5 | * | ||
6 | */ | ||
7 | |||
8 | #include <linux/errno.h> | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/slab.h> | ||
11 | #include <linux/tty.h> | ||
12 | #include <linux/tty_driver.h> | ||
13 | #include <linux/tty_flip.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/serial.h> | ||
16 | #include <linux/usb.h> | ||
17 | #include <linux/usb/serial.h> | ||
18 | #include <linux/uaccess.h> | ||
19 | |||
20 | #define QT_OPEN_CLOSE_CHANNEL 0xca | ||
21 | #define QT_SET_GET_DEVICE 0xc2 | ||
22 | #define QT_SET_GET_REGISTER 0xc0 | ||
23 | #define QT_GET_SET_PREBUF_TRIG_LVL 0xcc | ||
24 | #define QT_SET_ATF 0xcd | ||
25 | #define QT_GET_SET_UART 0xc1 | ||
26 | #define QT_TRANSFER_IN 0xc0 | ||
27 | #define QT_HW_FLOW_CONTROL_MASK 0xc5 | ||
28 | #define QT_SW_FLOW_CONTROL_MASK 0xc6 | ||
29 | |||
30 | #define MODEM_CTL_REGISTER 0x04 | ||
31 | #define MODEM_STATUS_REGISTER 0x06 | ||
32 | |||
33 | |||
34 | #define SERIAL_LSR_OE 0x02 | ||
35 | #define SERIAL_LSR_PE 0x04 | ||
36 | #define SERIAL_LSR_FE 0x08 | ||
37 | #define SERIAL_LSR_BI 0x10 | ||
38 | |||
39 | #define SERIAL_LSR_TEMT 0x40 | ||
40 | |||
41 | #define SERIAL_MCR_DTR 0x01 | ||
42 | #define SERIAL_MCR_RTS 0x02 | ||
43 | #define SERIAL_MCR_LOOP 0x10 | ||
44 | |||
45 | #define SERIAL_MSR_CTS 0x10 | ||
46 | #define SERIAL_MSR_CD 0x80 | ||
47 | #define SERIAL_MSR_RI 0x40 | ||
48 | #define SERIAL_MSR_DSR 0x20 | ||
49 | #define SERIAL_MSR_MASK 0xf0 | ||
50 | |||
51 | #define SERIAL_CRTSCTS ((SERIAL_MCR_RTS << 8) | SERIAL_MSR_CTS) | ||
52 | |||
53 | #define SERIAL_8_DATA 0x03 | ||
54 | #define SERIAL_7_DATA 0x02 | ||
55 | #define SERIAL_6_DATA 0x01 | ||
56 | #define SERIAL_5_DATA 0x00 | ||
57 | |||
58 | #define SERIAL_ODD_PARITY 0X08 | ||
59 | #define SERIAL_EVEN_PARITY 0X18 | ||
60 | |||
61 | #define MAX_BAUD_RATE 460800 | ||
62 | |||
63 | #define ATC_DISABLED 0x00 | ||
64 | #define DUPMODE_BITS 0xc0 | ||
65 | #define RR_BITS 0x03 | ||
66 | #define LOOPMODE_BITS 0x41 | ||
67 | #define RS232_MODE 0x00 | ||
68 | #define RTSCTS_TO_CONNECTOR 0x40 | ||
69 | #define CLKS_X4 0x02 | ||
70 | #define FULLPWRBIT 0x00000080 | ||
71 | #define NEXT_BOARD_POWER_BIT 0x00000004 | ||
72 | |||
73 | static int debug = 1; | ||
74 | |||
75 | /* Version Information */ | ||
76 | #define DRIVER_VERSION "v0.1" | ||
77 | #define DRIVER_DESC "Quatech SSU-100 USB to Serial Driver" | ||
78 | |||
79 | #define USB_VENDOR_ID_QUATECH 0x061d /* Quatech VID */ | ||
80 | #define QUATECH_SSU100 0xC020 /* SSU100 */ | ||
81 | |||
82 | static const struct usb_device_id id_table[] = { | ||
83 | {USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU100)}, | ||
84 | {} /* Terminating entry */ | ||
85 | }; | ||
86 | |||
87 | MODULE_DEVICE_TABLE(usb, id_table); | ||
88 | |||
89 | |||
90 | static struct usb_driver ssu100_driver = { | ||
91 | .name = "ssu100", | ||
92 | .probe = usb_serial_probe, | ||
93 | .disconnect = usb_serial_disconnect, | ||
94 | .id_table = id_table, | ||
95 | .suspend = usb_serial_suspend, | ||
96 | .resume = usb_serial_resume, | ||
97 | .no_dynamic_id = 1, | ||
98 | .supports_autosuspend = 1, | ||
99 | }; | ||
100 | |||
101 | struct ssu100_port_private { | ||
102 | u8 shadowLSR; | ||
103 | u8 shadowMSR; | ||
104 | wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ | ||
105 | unsigned short max_packet_size; | ||
106 | }; | ||
107 | |||
108 | static void ssu100_release(struct usb_serial *serial) | ||
109 | { | ||
110 | struct ssu100_port_private *priv = usb_get_serial_port_data(*serial->port); | ||
111 | |||
112 | dbg("%s", __func__); | ||
113 | kfree(priv); | ||
114 | } | ||
115 | |||
116 | static inline int ssu100_control_msg(struct usb_device *dev, | ||
117 | u8 request, u16 data, u16 index) | ||
118 | { | ||
119 | return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
120 | request, 0x40, data, index, | ||
121 | NULL, 0, 300); | ||
122 | } | ||
123 | |||
124 | static inline int ssu100_setdevice(struct usb_device *dev, u8 *data) | ||
125 | { | ||
126 | u16 x = ((u16)(data[1] << 8) | (u16)(data[0])); | ||
127 | |||
128 | return ssu100_control_msg(dev, QT_SET_GET_DEVICE, x, 0); | ||
129 | } | ||
130 | |||
131 | |||
132 | static inline int ssu100_getdevice(struct usb_device *dev, u8 *data) | ||
133 | { | ||
134 | return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | ||
135 | QT_SET_GET_DEVICE, 0xc0, 0, 0, | ||
136 | data, 3, 300); | ||
137 | } | ||
138 | |||
139 | static inline int ssu100_getregister(struct usb_device *dev, | ||
140 | unsigned short uart, | ||
141 | unsigned short reg, | ||
142 | u8 *data) | ||
143 | { | ||
144 | return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | ||
145 | QT_SET_GET_REGISTER, 0xc0, reg, | ||
146 | uart, data, sizeof(*data), 300); | ||
147 | |||
148 | } | ||
149 | |||
150 | |||
151 | static inline int ssu100_setregister(struct usb_device *dev, | ||
152 | unsigned short uart, | ||
153 | u16 data) | ||
154 | { | ||
155 | u16 value = (data << 8) | MODEM_CTL_REGISTER; | ||
156 | |||
157 | return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
158 | QT_SET_GET_REGISTER, 0x40, value, uart, | ||
159 | NULL, 0, 300); | ||
160 | |||
161 | } | ||
162 | |||
163 | #define set_mctrl(dev, set) update_mctrl((dev), (set), 0) | ||
164 | #define clear_mctrl(dev, clear) update_mctrl((dev), 0, (clear)) | ||
165 | |||
166 | /* these do not deal with device that have more than 1 port */ | ||
167 | static inline int update_mctrl(struct usb_device *dev, unsigned int set, | ||
168 | unsigned int clear) | ||
169 | { | ||
170 | unsigned urb_value; | ||
171 | int result; | ||
172 | |||
173 | if (((set | clear) & (TIOCM_DTR | TIOCM_RTS)) == 0) { | ||
174 | dbg("%s - DTR|RTS not being set|cleared", __func__); | ||
175 | return 0; /* no change */ | ||
176 | } | ||
177 | |||
178 | clear &= ~set; /* 'set' takes precedence over 'clear' */ | ||
179 | urb_value = 0; | ||
180 | if (set & TIOCM_DTR) | ||
181 | urb_value |= SERIAL_MCR_DTR; | ||
182 | if (set & TIOCM_RTS) | ||
183 | urb_value |= SERIAL_MCR_RTS; | ||
184 | |||
185 | result = ssu100_setregister(dev, 0, urb_value); | ||
186 | if (result < 0) | ||
187 | dbg("%s Error from MODEM_CTRL urb", __func__); | ||
188 | |||
189 | return result; | ||
190 | } | ||
191 | |||
192 | static int ssu100_initdevice(struct usb_device *dev) | ||
193 | { | ||
194 | u8 *data; | ||
195 | int result = 0; | ||
196 | |||
197 | dbg("%s", __func__); | ||
198 | |||
199 | data = kzalloc(3, GFP_KERNEL); | ||
200 | if (!data) | ||
201 | return -ENOMEM; | ||
202 | |||
203 | result = ssu100_getdevice(dev, data); | ||
204 | if (result < 0) { | ||
205 | dbg("%s - get_device failed %i", __func__, result); | ||
206 | goto out; | ||
207 | } | ||
208 | |||
209 | data[1] &= ~FULLPWRBIT; | ||
210 | |||
211 | result = ssu100_setdevice(dev, data); | ||
212 | if (result < 0) { | ||
213 | dbg("%s - setdevice failed %i", __func__, result); | ||
214 | goto out; | ||
215 | } | ||
216 | |||
217 | result = ssu100_control_msg(dev, QT_GET_SET_PREBUF_TRIG_LVL, 128, 0); | ||
218 | if (result < 0) { | ||
219 | dbg("%s - set prebuffer level failed %i", __func__, result); | ||
220 | goto out; | ||
221 | } | ||
222 | |||
223 | result = ssu100_control_msg(dev, QT_SET_ATF, ATC_DISABLED, 0); | ||
224 | if (result < 0) { | ||
225 | dbg("%s - set ATFprebuffer level failed %i", __func__, result); | ||
226 | goto out; | ||
227 | } | ||
228 | |||
229 | result = ssu100_getdevice(dev, data); | ||
230 | if (result < 0) { | ||
231 | dbg("%s - get_device failed %i", __func__, result); | ||
232 | goto out; | ||
233 | } | ||
234 | |||
235 | data[0] &= ~(RR_BITS | DUPMODE_BITS); | ||
236 | data[0] |= CLKS_X4; | ||
237 | data[1] &= ~(LOOPMODE_BITS); | ||
238 | data[1] |= RS232_MODE; | ||
239 | |||
240 | result = ssu100_setdevice(dev, data); | ||
241 | if (result < 0) { | ||
242 | dbg("%s - setdevice failed %i", __func__, result); | ||
243 | goto out; | ||
244 | } | ||
245 | |||
246 | out: kfree(data); | ||
247 | return result; | ||
248 | |||
249 | } | ||
250 | |||
251 | |||
252 | static void ssu100_set_termios(struct tty_struct *tty, | ||
253 | struct usb_serial_port *port, | ||
254 | struct ktermios *old_termios) | ||
255 | { | ||
256 | struct usb_device *dev = port->serial->dev; | ||
257 | struct ktermios *termios = tty->termios; | ||
258 | u16 baud, divisor, remainder; | ||
259 | unsigned int cflag = termios->c_cflag; | ||
260 | u16 urb_value = 0; /* will hold the new flags */ | ||
261 | int result; | ||
262 | |||
263 | dbg("%s", __func__); | ||
264 | |||
265 | if (cflag & PARENB) { | ||
266 | if (cflag & PARODD) | ||
267 | urb_value |= SERIAL_ODD_PARITY; | ||
268 | else | ||
269 | urb_value |= SERIAL_EVEN_PARITY; | ||
270 | } | ||
271 | |||
272 | switch (cflag & CSIZE) { | ||
273 | case CS5: | ||
274 | urb_value |= SERIAL_5_DATA; | ||
275 | break; | ||
276 | case CS6: | ||
277 | urb_value |= SERIAL_6_DATA; | ||
278 | break; | ||
279 | case CS7: | ||
280 | urb_value |= SERIAL_7_DATA; | ||
281 | break; | ||
282 | default: | ||
283 | case CS8: | ||
284 | urb_value |= SERIAL_8_DATA; | ||
285 | break; | ||
286 | } | ||
287 | |||
288 | baud = tty_get_baud_rate(tty); | ||
289 | if (!baud) | ||
290 | baud = 9600; | ||
291 | |||
292 | dbg("%s - got baud = %d\n", __func__, baud); | ||
293 | |||
294 | |||
295 | divisor = MAX_BAUD_RATE / baud; | ||
296 | remainder = MAX_BAUD_RATE % baud; | ||
297 | if (((remainder * 2) >= baud) && (baud != 110)) | ||
298 | divisor++; | ||
299 | |||
300 | urb_value = urb_value << 8; | ||
301 | |||
302 | result = ssu100_control_msg(dev, QT_GET_SET_UART, divisor, urb_value); | ||
303 | if (result < 0) | ||
304 | dbg("%s - set uart failed", __func__); | ||
305 | |||
306 | if (cflag & CRTSCTS) | ||
307 | result = ssu100_control_msg(dev, QT_HW_FLOW_CONTROL_MASK, | ||
308 | SERIAL_CRTSCTS, 0); | ||
309 | else | ||
310 | result = ssu100_control_msg(dev, QT_HW_FLOW_CONTROL_MASK, | ||
311 | 0, 0); | ||
312 | if (result < 0) | ||
313 | dbg("%s - set HW flow control failed", __func__); | ||
314 | |||
315 | if (I_IXOFF(tty) || I_IXON(tty)) { | ||
316 | u16 x = ((u16)(START_CHAR(tty) << 8) | (u16)(STOP_CHAR(tty))); | ||
317 | |||
318 | result = ssu100_control_msg(dev, QT_SW_FLOW_CONTROL_MASK, | ||
319 | x, 0); | ||
320 | } else | ||
321 | result = ssu100_control_msg(dev, QT_SW_FLOW_CONTROL_MASK, | ||
322 | 0, 0); | ||
323 | |||
324 | if (result < 0) | ||
325 | dbg("%s - set SW flow control failed", __func__); | ||
326 | |||
327 | } | ||
328 | |||
329 | |||
330 | static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port) | ||
331 | { | ||
332 | struct usb_device *dev = port->serial->dev; | ||
333 | struct ssu100_port_private *priv = usb_get_serial_port_data(port); | ||
334 | u8 *data; | ||
335 | int result; | ||
336 | |||
337 | dbg("%s - port %d", __func__, port->number); | ||
338 | |||
339 | data = kzalloc(2, GFP_KERNEL); | ||
340 | if (!data) | ||
341 | return -ENOMEM; | ||
342 | |||
343 | result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | ||
344 | QT_OPEN_CLOSE_CHANNEL, | ||
345 | QT_TRANSFER_IN, 0x01, | ||
346 | 0, data, 2, 300); | ||
347 | if (result < 0) { | ||
348 | dbg("%s - open failed %i", __func__, result); | ||
349 | kfree(data); | ||
350 | return result; | ||
351 | } | ||
352 | |||
353 | priv->shadowLSR = data[0] & (SERIAL_LSR_OE | SERIAL_LSR_PE | | ||
354 | SERIAL_LSR_FE | SERIAL_LSR_BI); | ||
355 | |||
356 | priv->shadowMSR = data[1] & (SERIAL_MSR_CTS | SERIAL_MSR_DSR | | ||
357 | SERIAL_MSR_RI | SERIAL_MSR_CD); | ||
358 | |||
359 | kfree(data); | ||
360 | |||
361 | /* set to 9600 */ | ||
362 | result = ssu100_control_msg(dev, QT_GET_SET_UART, 0x30, 0x0300); | ||
363 | if (result < 0) | ||
364 | dbg("%s - set uart failed", __func__); | ||
365 | |||
366 | if (tty) | ||
367 | ssu100_set_termios(tty, port, tty->termios); | ||
368 | |||
369 | return usb_serial_generic_open(tty, port); | ||
370 | } | ||
371 | |||
372 | static void ssu100_close(struct usb_serial_port *port) | ||
373 | { | ||
374 | dbg("%s", __func__); | ||
375 | usb_serial_generic_close(port); | ||
376 | } | ||
377 | |||
378 | static int get_serial_info(struct usb_serial_port *port, | ||
379 | struct serial_struct __user *retinfo) | ||
380 | { | ||
381 | struct serial_struct tmp; | ||
382 | |||
383 | if (!retinfo) | ||
384 | return -EFAULT; | ||
385 | |||
386 | memset(&tmp, 0, sizeof(tmp)); | ||
387 | tmp.line = port->serial->minor; | ||
388 | tmp.port = 0; | ||
389 | tmp.irq = 0; | ||
390 | tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; | ||
391 | tmp.xmit_fifo_size = port->bulk_out_size; | ||
392 | tmp.baud_base = 9600; | ||
393 | tmp.close_delay = 5*HZ; | ||
394 | tmp.closing_wait = 30*HZ; | ||
395 | |||
396 | if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) | ||
397 | return -EFAULT; | ||
398 | return 0; | ||
399 | } | ||
400 | |||
401 | static int ssu100_ioctl(struct tty_struct *tty, struct file *file, | ||
402 | unsigned int cmd, unsigned long arg) | ||
403 | { | ||
404 | struct usb_serial_port *port = tty->driver_data; | ||
405 | struct ssu100_port_private *priv = usb_get_serial_port_data(port); | ||
406 | |||
407 | dbg("%s cmd 0x%04x", __func__, cmd); | ||
408 | |||
409 | switch (cmd) { | ||
410 | case TIOCGSERIAL: | ||
411 | return get_serial_info(port, | ||
412 | (struct serial_struct __user *) arg); | ||
413 | |||
414 | case TIOCMIWAIT: | ||
415 | while (priv != NULL) { | ||
416 | u8 prevMSR = priv->shadowMSR & SERIAL_MSR_MASK; | ||
417 | interruptible_sleep_on(&priv->delta_msr_wait); | ||
418 | /* see if a signal did it */ | ||
419 | if (signal_pending(current)) | ||
420 | return -ERESTARTSYS; | ||
421 | else { | ||
422 | u8 diff = (priv->shadowMSR & SERIAL_MSR_MASK) ^ prevMSR; | ||
423 | if (!diff) | ||
424 | return -EIO; /* no change => error */ | ||
425 | |||
426 | /* Return 0 if caller wanted to know about | ||
427 | these bits */ | ||
428 | |||
429 | if (((arg & TIOCM_RNG) && (diff & SERIAL_MSR_RI)) || | ||
430 | ((arg & TIOCM_DSR) && (diff & SERIAL_MSR_DSR)) || | ||
431 | ((arg & TIOCM_CD) && (diff & SERIAL_MSR_CD)) || | ||
432 | ((arg & TIOCM_CTS) && (diff & SERIAL_MSR_CTS))) | ||
433 | return 0; | ||
434 | } | ||
435 | } | ||
436 | return 0; | ||
437 | |||
438 | default: | ||
439 | break; | ||
440 | } | ||
441 | |||
442 | dbg("%s arg not supported", __func__); | ||
443 | |||
444 | return -ENOIOCTLCMD; | ||
445 | } | ||
446 | |||
447 | static void ssu100_set_max_packet_size(struct usb_serial_port *port) | ||
448 | { | ||
449 | struct ssu100_port_private *priv = usb_get_serial_port_data(port); | ||
450 | struct usb_serial *serial = port->serial; | ||
451 | struct usb_device *udev = serial->dev; | ||
452 | |||
453 | struct usb_interface *interface = serial->interface; | ||
454 | struct usb_endpoint_descriptor *ep_desc = &interface->cur_altsetting->endpoint[1].desc; | ||
455 | |||
456 | unsigned num_endpoints; | ||
457 | int i; | ||
458 | |||
459 | num_endpoints = interface->cur_altsetting->desc.bNumEndpoints; | ||
460 | dev_info(&udev->dev, "Number of endpoints %d\n", num_endpoints); | ||
461 | |||
462 | for (i = 0; i < num_endpoints; i++) { | ||
463 | dev_info(&udev->dev, "Endpoint %d MaxPacketSize %d\n", i+1, | ||
464 | interface->cur_altsetting->endpoint[i].desc.wMaxPacketSize); | ||
465 | ep_desc = &interface->cur_altsetting->endpoint[i].desc; | ||
466 | } | ||
467 | |||
468 | /* set max packet size based on descriptor */ | ||
469 | priv->max_packet_size = ep_desc->wMaxPacketSize; | ||
470 | |||
471 | dev_info(&udev->dev, "Setting MaxPacketSize %d\n", priv->max_packet_size); | ||
472 | } | ||
473 | |||
474 | static int ssu100_attach(struct usb_serial *serial) | ||
475 | { | ||
476 | struct ssu100_port_private *priv; | ||
477 | struct usb_serial_port *port = *serial->port; | ||
478 | |||
479 | dbg("%s", __func__); | ||
480 | |||
481 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
482 | if (!priv) { | ||
483 | dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", __func__, | ||
484 | sizeof(*priv)); | ||
485 | return -ENOMEM; | ||
486 | } | ||
487 | |||
488 | init_waitqueue_head(&priv->delta_msr_wait); | ||
489 | usb_set_serial_port_data(port, priv); | ||
490 | |||
491 | ssu100_set_max_packet_size(port); | ||
492 | |||
493 | return ssu100_initdevice(serial->dev); | ||
494 | } | ||
495 | |||
496 | static int ssu100_tiocmget(struct tty_struct *tty, struct file *file) | ||
497 | { | ||
498 | struct usb_serial_port *port = tty->driver_data; | ||
499 | struct usb_device *dev = port->serial->dev; | ||
500 | u8 *d; | ||
501 | int r; | ||
502 | |||
503 | dbg("%s\n", __func__); | ||
504 | |||
505 | d = kzalloc(2, GFP_KERNEL); | ||
506 | if (!d) | ||
507 | return -ENOMEM; | ||
508 | |||
509 | r = ssu100_getregister(dev, 0, MODEM_CTL_REGISTER, d); | ||
510 | if (r < 0) | ||
511 | goto mget_out; | ||
512 | |||
513 | r = ssu100_getregister(dev, 0, MODEM_STATUS_REGISTER, d+1); | ||
514 | if (r < 0) | ||
515 | goto mget_out; | ||
516 | |||
517 | r = (d[0] & SERIAL_MCR_DTR ? TIOCM_DTR : 0) | | ||
518 | (d[0] & SERIAL_MCR_RTS ? TIOCM_RTS : 0) | | ||
519 | (d[1] & SERIAL_MSR_CTS ? TIOCM_CTS : 0) | | ||
520 | (d[1] & SERIAL_MSR_CD ? TIOCM_CAR : 0) | | ||
521 | (d[1] & SERIAL_MSR_RI ? TIOCM_RI : 0) | | ||
522 | (d[1] & SERIAL_MSR_DSR ? TIOCM_DSR : 0); | ||
523 | |||
524 | mget_out: | ||
525 | kfree(d); | ||
526 | return r; | ||
527 | } | ||
528 | |||
529 | static int ssu100_tiocmset(struct tty_struct *tty, struct file *file, | ||
530 | unsigned int set, unsigned int clear) | ||
531 | { | ||
532 | struct usb_serial_port *port = tty->driver_data; | ||
533 | struct usb_device *dev = port->serial->dev; | ||
534 | |||
535 | dbg("%s\n", __func__); | ||
536 | return update_mctrl(dev, set, clear); | ||
537 | } | ||
538 | |||
539 | static void ssu100_dtr_rts(struct usb_serial_port *port, int on) | ||
540 | { | ||
541 | struct usb_device *dev = port->serial->dev; | ||
542 | |||
543 | dbg("%s\n", __func__); | ||
544 | |||
545 | mutex_lock(&port->serial->disc_mutex); | ||
546 | if (!port->serial->disconnected) { | ||
547 | /* Disable flow control */ | ||
548 | if (!on && | ||
549 | ssu100_setregister(dev, 0, 0) < 0) | ||
550 | dev_err(&port->dev, "error from flowcontrol urb\n"); | ||
551 | /* drop RTS and DTR */ | ||
552 | if (on) | ||
553 | set_mctrl(dev, TIOCM_DTR | TIOCM_RTS); | ||
554 | else | ||
555 | clear_mctrl(dev, TIOCM_DTR | TIOCM_RTS); | ||
556 | } | ||
557 | mutex_unlock(&port->serial->disc_mutex); | ||
558 | } | ||
559 | |||
560 | static int ssu100_process_packet(struct tty_struct *tty, | ||
561 | struct usb_serial_port *port, | ||
562 | struct ssu100_port_private *priv, | ||
563 | char *packet, int len) | ||
564 | { | ||
565 | int i; | ||
566 | char flag; | ||
567 | char *ch; | ||
568 | |||
569 | dbg("%s - port %d", __func__, port->number); | ||
570 | |||
571 | if (len < 4) { | ||
572 | dbg("%s - malformed packet", __func__); | ||
573 | return 0; | ||
574 | } | ||
575 | |||
576 | if ((packet[0] == 0x1b) && (packet[1] == 0x1b) && | ||
577 | ((packet[2] == 0x00) || (packet[2] == 0x01))) { | ||
578 | if (packet[2] == 0x00) | ||
579 | priv->shadowLSR = packet[3] & (SERIAL_LSR_OE | | ||
580 | SERIAL_LSR_PE | | ||
581 | SERIAL_LSR_FE | | ||
582 | SERIAL_LSR_BI); | ||
583 | |||
584 | if (packet[2] == 0x01) { | ||
585 | priv->shadowMSR = packet[3]; | ||
586 | wake_up_interruptible(&priv->delta_msr_wait); | ||
587 | } | ||
588 | |||
589 | len -= 4; | ||
590 | ch = packet + 4; | ||
591 | } else | ||
592 | ch = packet; | ||
593 | |||
594 | if (!len) | ||
595 | return 0; /* status only */ | ||
596 | |||
597 | if (port->port.console && port->sysrq) { | ||
598 | for (i = 0; i < len; i++, ch++) { | ||
599 | if (!usb_serial_handle_sysrq_char(tty, port, *ch)) | ||
600 | tty_insert_flip_char(tty, *ch, flag); | ||
601 | } | ||
602 | } else | ||
603 | tty_insert_flip_string_fixed_flag(tty, ch, flag, len); | ||
604 | |||
605 | return len; | ||
606 | } | ||
607 | |||
608 | static void ssu100_process_read_urb(struct urb *urb) | ||
609 | { | ||
610 | struct usb_serial_port *port = urb->context; | ||
611 | struct ssu100_port_private *priv = usb_get_serial_port_data(port); | ||
612 | char *data = (char *)urb->transfer_buffer; | ||
613 | struct tty_struct *tty; | ||
614 | int count = 0; | ||
615 | int i; | ||
616 | int len; | ||
617 | |||
618 | dbg("%s", __func__); | ||
619 | |||
620 | tty = tty_port_tty_get(&port->port); | ||
621 | if (!tty) | ||
622 | return; | ||
623 | |||
624 | for (i = 0; i < urb->actual_length; i += priv->max_packet_size) { | ||
625 | len = min_t(int, urb->actual_length - i, priv->max_packet_size); | ||
626 | count += ssu100_process_packet(tty, port, priv, &data[i], len); | ||
627 | } | ||
628 | |||
629 | if (count) | ||
630 | tty_flip_buffer_push(tty); | ||
631 | tty_kref_put(tty); | ||
632 | } | ||
633 | |||
634 | |||
635 | static struct usb_serial_driver ssu100_device = { | ||
636 | .driver = { | ||
637 | .owner = THIS_MODULE, | ||
638 | .name = "ssu100", | ||
639 | }, | ||
640 | .description = DRIVER_DESC, | ||
641 | .id_table = id_table, | ||
642 | .usb_driver = &ssu100_driver, | ||
643 | .num_ports = 1, | ||
644 | .bulk_in_size = 256, | ||
645 | .bulk_out_size = 256, | ||
646 | .open = ssu100_open, | ||
647 | .close = ssu100_close, | ||
648 | .attach = ssu100_attach, | ||
649 | .release = ssu100_release, | ||
650 | .dtr_rts = ssu100_dtr_rts, | ||
651 | .process_read_urb = ssu100_process_read_urb, | ||
652 | .tiocmget = ssu100_tiocmget, | ||
653 | .tiocmset = ssu100_tiocmset, | ||
654 | .ioctl = ssu100_ioctl, | ||
655 | .set_termios = ssu100_set_termios, | ||
656 | }; | ||
657 | |||
658 | static int __init ssu100_init(void) | ||
659 | { | ||
660 | int retval; | ||
661 | |||
662 | dbg("%s", __func__); | ||
663 | |||
664 | /* register with usb-serial */ | ||
665 | retval = usb_serial_register(&ssu100_device); | ||
666 | |||
667 | if (retval) | ||
668 | goto failed_usb_sio_register; | ||
669 | |||
670 | retval = usb_register(&ssu100_driver); | ||
671 | if (retval) | ||
672 | goto failed_usb_register; | ||
673 | |||
674 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" | ||
675 | DRIVER_DESC "\n"); | ||
676 | |||
677 | return 0; | ||
678 | |||
679 | failed_usb_register: | ||
680 | usb_serial_deregister(&ssu100_device); | ||
681 | failed_usb_sio_register: | ||
682 | return retval; | ||
683 | } | ||
684 | |||
685 | static void __exit ssu100_exit(void) | ||
686 | { | ||
687 | usb_deregister(&ssu100_driver); | ||
688 | usb_serial_deregister(&ssu100_device); | ||
689 | } | ||
690 | |||
691 | module_init(ssu100_init); | ||
692 | module_exit(ssu100_exit); | ||
693 | |||
694 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
695 | MODULE_LICENSE("GPL"); | ||
696 | |||
697 | module_param(debug, bool, S_IRUGO | S_IWUSR); | ||
698 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | ||
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 941c2d409f85..2a982e62963b 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -653,6 +653,7 @@ exit: | |||
653 | return id; | 653 | return id; |
654 | } | 654 | } |
655 | 655 | ||
656 | /* Caller must hold table_lock */ | ||
656 | static struct usb_serial_driver *search_serial_device( | 657 | static struct usb_serial_driver *search_serial_device( |
657 | struct usb_interface *iface) | 658 | struct usb_interface *iface) |
658 | { | 659 | { |
@@ -718,17 +719,23 @@ int usb_serial_probe(struct usb_interface *interface, | |||
718 | int num_ports = 0; | 719 | int num_ports = 0; |
719 | int max_endpoints; | 720 | int max_endpoints; |
720 | 721 | ||
721 | lock_kernel(); /* guard against unloading a serial driver module */ | 722 | mutex_lock(&table_lock); |
722 | type = search_serial_device(interface); | 723 | type = search_serial_device(interface); |
723 | if (!type) { | 724 | if (!type) { |
724 | unlock_kernel(); | 725 | mutex_unlock(&table_lock); |
725 | dbg("none matched"); | 726 | dbg("none matched"); |
726 | return -ENODEV; | 727 | return -ENODEV; |
727 | } | 728 | } |
728 | 729 | ||
730 | if (!try_module_get(type->driver.owner)) { | ||
731 | mutex_unlock(&table_lock); | ||
732 | dev_err(&interface->dev, "module get failed, exiting\n"); | ||
733 | return -EIO; | ||
734 | } | ||
735 | mutex_unlock(&table_lock); | ||
736 | |||
729 | serial = create_serial(dev, interface, type); | 737 | serial = create_serial(dev, interface, type); |
730 | if (!serial) { | 738 | if (!serial) { |
731 | unlock_kernel(); | ||
732 | dev_err(&interface->dev, "%s - out of memory\n", __func__); | 739 | dev_err(&interface->dev, "%s - out of memory\n", __func__); |
733 | return -ENOMEM; | 740 | return -ENOMEM; |
734 | } | 741 | } |
@@ -737,20 +744,11 @@ int usb_serial_probe(struct usb_interface *interface, | |||
737 | if (type->probe) { | 744 | if (type->probe) { |
738 | const struct usb_device_id *id; | 745 | const struct usb_device_id *id; |
739 | 746 | ||
740 | if (!try_module_get(type->driver.owner)) { | ||
741 | unlock_kernel(); | ||
742 | dev_err(&interface->dev, | ||
743 | "module get failed, exiting\n"); | ||
744 | kfree(serial); | ||
745 | return -EIO; | ||
746 | } | ||
747 | |||
748 | id = get_iface_id(type, interface); | 747 | id = get_iface_id(type, interface); |
749 | retval = type->probe(serial, id); | 748 | retval = type->probe(serial, id); |
750 | module_put(type->driver.owner); | 749 | module_put(type->driver.owner); |
751 | 750 | ||
752 | if (retval) { | 751 | if (retval) { |
753 | unlock_kernel(); | ||
754 | dbg("sub driver rejected device"); | 752 | dbg("sub driver rejected device"); |
755 | kfree(serial); | 753 | kfree(serial); |
756 | return retval; | 754 | return retval; |
@@ -822,7 +820,6 @@ int usb_serial_probe(struct usb_interface *interface, | |||
822 | * properly during a later invocation of usb_serial_probe | 820 | * properly during a later invocation of usb_serial_probe |
823 | */ | 821 | */ |
824 | if (num_bulk_in == 0 || num_bulk_out == 0) { | 822 | if (num_bulk_in == 0 || num_bulk_out == 0) { |
825 | unlock_kernel(); | ||
826 | dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n"); | 823 | dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n"); |
827 | kfree(serial); | 824 | kfree(serial); |
828 | return -ENODEV; | 825 | return -ENODEV; |
@@ -835,7 +832,6 @@ int usb_serial_probe(struct usb_interface *interface, | |||
835 | if (type == &usb_serial_generic_device) { | 832 | if (type == &usb_serial_generic_device) { |
836 | num_ports = num_bulk_out; | 833 | num_ports = num_bulk_out; |
837 | if (num_ports == 0) { | 834 | if (num_ports == 0) { |
838 | unlock_kernel(); | ||
839 | dev_err(&interface->dev, | 835 | dev_err(&interface->dev, |
840 | "Generic device with no bulk out, not allowed.\n"); | 836 | "Generic device with no bulk out, not allowed.\n"); |
841 | kfree(serial); | 837 | kfree(serial); |
@@ -847,7 +843,6 @@ int usb_serial_probe(struct usb_interface *interface, | |||
847 | /* if this device type has a calc_num_ports function, call it */ | 843 | /* if this device type has a calc_num_ports function, call it */ |
848 | if (type->calc_num_ports) { | 844 | if (type->calc_num_ports) { |
849 | if (!try_module_get(type->driver.owner)) { | 845 | if (!try_module_get(type->driver.owner)) { |
850 | unlock_kernel(); | ||
851 | dev_err(&interface->dev, | 846 | dev_err(&interface->dev, |
852 | "module get failed, exiting\n"); | 847 | "module get failed, exiting\n"); |
853 | kfree(serial); | 848 | kfree(serial); |
@@ -878,7 +873,6 @@ int usb_serial_probe(struct usb_interface *interface, | |||
878 | max_endpoints = max(max_endpoints, num_interrupt_out); | 873 | max_endpoints = max(max_endpoints, num_interrupt_out); |
879 | max_endpoints = max(max_endpoints, (int)serial->num_ports); | 874 | max_endpoints = max(max_endpoints, (int)serial->num_ports); |
880 | serial->num_port_pointers = max_endpoints; | 875 | serial->num_port_pointers = max_endpoints; |
881 | unlock_kernel(); | ||
882 | 876 | ||
883 | dbg("%s - setting up %d port structures for this device", | 877 | dbg("%s - setting up %d port structures for this device", |
884 | __func__, max_endpoints); | 878 | __func__, max_endpoints); |
@@ -1077,6 +1071,8 @@ int usb_serial_probe(struct usb_interface *interface, | |||
1077 | dev_set_name(&port->dev, "ttyUSB%d", port->number); | 1071 | dev_set_name(&port->dev, "ttyUSB%d", port->number); |
1078 | dbg ("%s - registering %s", __func__, dev_name(&port->dev)); | 1072 | dbg ("%s - registering %s", __func__, dev_name(&port->dev)); |
1079 | port->dev_state = PORT_REGISTERING; | 1073 | port->dev_state = PORT_REGISTERING; |
1074 | device_enable_async_suspend(&port->dev); | ||
1075 | |||
1080 | retval = device_add(&port->dev); | 1076 | retval = device_add(&port->dev); |
1081 | if (retval) { | 1077 | if (retval) { |
1082 | dev_err(&port->dev, "Error registering port device, " | 1078 | dev_err(&port->dev, "Error registering port device, " |
@@ -1349,6 +1345,7 @@ int usb_serial_register(struct usb_serial_driver *driver) | |||
1349 | driver->description = driver->driver.name; | 1345 | driver->description = driver->driver.name; |
1350 | 1346 | ||
1351 | /* Add this device to our list of devices */ | 1347 | /* Add this device to our list of devices */ |
1348 | mutex_lock(&table_lock); | ||
1352 | list_add(&driver->driver_list, &usb_serial_driver_list); | 1349 | list_add(&driver->driver_list, &usb_serial_driver_list); |
1353 | 1350 | ||
1354 | retval = usb_serial_bus_register(driver); | 1351 | retval = usb_serial_bus_register(driver); |
@@ -1360,6 +1357,7 @@ int usb_serial_register(struct usb_serial_driver *driver) | |||
1360 | printk(KERN_INFO "USB Serial support registered for %s\n", | 1357 | printk(KERN_INFO "USB Serial support registered for %s\n", |
1361 | driver->description); | 1358 | driver->description); |
1362 | 1359 | ||
1360 | mutex_unlock(&table_lock); | ||
1363 | return retval; | 1361 | return retval; |
1364 | } | 1362 | } |
1365 | EXPORT_SYMBOL_GPL(usb_serial_register); | 1363 | EXPORT_SYMBOL_GPL(usb_serial_register); |
@@ -1370,8 +1368,10 @@ void usb_serial_deregister(struct usb_serial_driver *device) | |||
1370 | /* must be called with BKL held */ | 1368 | /* must be called with BKL held */ |
1371 | printk(KERN_INFO "USB Serial deregistering driver %s\n", | 1369 | printk(KERN_INFO "USB Serial deregistering driver %s\n", |
1372 | device->description); | 1370 | device->description); |
1371 | mutex_lock(&table_lock); | ||
1373 | list_del(&device->driver_list); | 1372 | list_del(&device->driver_list); |
1374 | usb_serial_bus_deregister(device); | 1373 | usb_serial_bus_deregister(device); |
1374 | mutex_unlock(&table_lock); | ||
1375 | } | 1375 | } |
1376 | EXPORT_SYMBOL_GPL(usb_serial_deregister); | 1376 | EXPORT_SYMBOL_GPL(usb_serial_deregister); |
1377 | 1377 | ||