diff options
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r-- | drivers/usb/serial/ftdi_sio.c | 30 | ||||
-rw-r--r-- | drivers/usb/serial/ftdi_sio_ids.h | 9 | ||||
-rw-r--r-- | drivers/usb/serial/option.c | 1 | ||||
-rw-r--r-- | drivers/usb/serial/ssu100.c | 56 | ||||
-rw-r--r-- | drivers/usb/serial/usb-serial.c | 3 | ||||
-rw-r--r-- | drivers/usb/serial/usb-wwan.h | 2 | ||||
-rw-r--r-- | drivers/usb/serial/usb_wwan.c | 79 |
7 files changed, 132 insertions, 48 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 76f8b3556672..a2668d089260 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -75,6 +75,7 @@ struct ftdi_private { unsigned long last_dtr_rts; /* saved modem control outputs */ wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ char prev_status, diff_status; /* Used for TIOCMIWAIT */ + char transmit_empty; /* If transmitter is empty or not */ struct usb_serial_port *port; __u16 interface; /* FT2232C, FT2232H or FT4232H port interface (0 for FT232/245) */ @@ -201,6 +202,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_MTXORB_5_PID) }, { USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) }, { USB_DEVICE(FTDI_VID, FTDI_R2000KU_TRUE_RNG) }, + { USB_DEVICE(FTDI_VID, FTDI_VARDAAN_PID) }, { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0100_PID) }, { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0101_PID) }, { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0102_PID) }, @@ -696,6 +698,7 @@ static struct usb_device_id id_table_combined [] = { .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) }, { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_SERIAL_VX7_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_CT29B_PID) }, { USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) }, { USB_DEVICE(FTDI_VID, FTDI_PHI_FISCO_PID) }, { USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) }, @@ -794,6 +797,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LOGBOOKML_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LS_LOGBOOK_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_HS_LOGBOOK_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_DOTEC_PID) }, { USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { }, /* Optional parameter entry */ @@ -1320,6 +1324,23 @@ check_and_exit: return 0; } +static int get_lsr_info(struct usb_serial_port *port, + struct serial_struct __user *retinfo) +{ + struct ftdi_private *priv = usb_get_serial_port_data(port); + unsigned int result = 0; + + if (!retinfo) + return -EFAULT; + + if (priv->transmit_empty) + result = TIOCSER_TEMT; + + if (copy_to_user(retinfo, &result, sizeof(unsigned int))) + return -EFAULT; + return 0; +} + /* Determine type of FTDI chip based on USB config and descriptor. */ static void ftdi_determine_type(struct usb_serial_port *port) @@ -1869,6 +1890,12 @@ static int ftdi_process_packet(struct tty_struct *tty, tty_insert_flip_char(tty, 0, TTY_OVERRUN); } + /* save if the transmitter is empty or not */ + if (packet[1] & FTDI_RS_TEMT) + priv->transmit_empty = 1; + else + priv->transmit_empty = 0; + len -= 2; if (!len) return 0; /* status only */ @@ -2232,6 +2259,9 @@ static int ftdi_ioctl(struct tty_struct *tty, struct file *file, } } return 0; + case TIOCSERGETLSR: + return get_lsr_info(port, (struct serial_struct __user *)arg); + break; default: break; } diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 263f62551197..bf0867285481 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -114,6 +114,9 @@ /* Lenz LI-USB Computer Interface. */ #define FTDI_LENZ_LIUSB_PID 0xD780 +/* Vardaan Enterprises Serial Interface VEUSB422R3 */ +#define FTDI_VARDAAN_PID 0xF070 + /* * Xsens Technologies BV products (http://www.xsens.com). */ @@ -721,6 +724,7 @@ */ #define RTSYSTEMS_VID 0x2100 /* Vendor ID */ #define RTSYSTEMS_SERIAL_VX7_PID 0x9e52 /* Serial converter for VX-7 Radios using FT232RL */ +#define RTSYSTEMS_CT29B_PID 0x9e54 /* CT29B Radio Cable */ /* * Bayer Ascensia Contour blood glucose meter USB-converter cable. @@ -1077,6 +1081,11 @@ #define MJSG_HD_RADIO_PID 0x937C /* + * D.O.Tec products (http://www.directout.eu) + */ +#define FTDI_DOTEC_PID 0x9868 + +/* * Xverve Signalyzer tools (http://www.signalyzer.com/) */ #define XVERVE_SIGNALYZER_ST_PID 0xBCA0 diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index ef2977d3a613..cdfb1868caef 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -989,6 +989,7 @@ static struct usb_serial_driver option_1port_device = { .set_termios = usb_wwan_set_termios, .tiocmget = usb_wwan_tiocmget, .tiocmset = usb_wwan_tiocmset, + .ioctl = usb_wwan_ioctl, .attach = usb_wwan_startup, .disconnect = usb_wwan_disconnect, .release = usb_wwan_release, diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index f5312dd3331b..8359ec798959 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c @@ -79,7 +79,6 @@ struct ssu100_port_private { u8 shadowLSR; u8 shadowMSR; wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ - unsigned short max_packet_size; struct async_icount icount; }; @@ -464,36 +463,6 @@ static int ssu100_ioctl(struct tty_struct *tty, struct file *file, return -ENOIOCTLCMD; } -static void ssu100_set_max_packet_size(struct usb_serial_port *port) -{ - struct ssu100_port_private *priv = usb_get_serial_port_data(port); - struct usb_serial *serial = port->serial; - struct usb_device *udev = serial->dev; - - struct usb_interface *interface = serial->interface; - struct usb_endpoint_descriptor *ep_desc = &interface->cur_altsetting->endpoint[1].desc; - - unsigned num_endpoints; - int i; - unsigned long flags; - - num_endpoints = interface->cur_altsetting->desc.bNumEndpoints; - dev_info(&udev->dev, "Number of endpoints %d\n", num_endpoints); - - for (i = 0; i < num_endpoints; i++) { - dev_info(&udev->dev, "Endpoint %d MaxPacketSize %d\n", i+1, - interface->cur_altsetting->endpoint[i].desc.wMaxPacketSize); - ep_desc = &interface->cur_altsetting->endpoint[i].desc; - } - - /* set max packet size based on descriptor */ - spin_lock_irqsave(&priv->status_lock, flags); - priv->max_packet_size = ep_desc->wMaxPacketSize; - spin_unlock_irqrestore(&priv->status_lock, flags); - - dev_info(&udev->dev, "Setting MaxPacketSize %d\n", priv->max_packet_size); -} - static int ssu100_attach(struct usb_serial *serial) { struct ssu100_port_private *priv; @@ -511,7 +480,6 @@ static int ssu100_attach(struct usb_serial *serial) spin_lock_init(&priv->status_lock); init_waitqueue_head(&priv->delta_msr_wait); usb_set_serial_port_data(port, priv); - ssu100_set_max_packet_size(port); return ssu100_initdevice(serial->dev); } @@ -641,13 +609,14 @@ static void ssu100_update_lsr(struct usb_serial_port *port, u8 lsr, } -static int ssu100_process_packet(struct tty_struct *tty, - struct usb_serial_port *port, - struct ssu100_port_private *priv, - char *packet, int len) +static int ssu100_process_packet(struct urb *urb, + struct tty_struct *tty) { - int i; + struct usb_serial_port *port = urb->context; + char *packet = (char *)urb->transfer_buffer; char flag = TTY_NORMAL; + u32 len = urb->actual_length; + int i; char *ch; dbg("%s - port %d", __func__, port->number); @@ -685,12 +654,8 @@ static int ssu100_process_packet(struct tty_struct *tty, static void ssu100_process_read_urb(struct urb *urb) { struct usb_serial_port *port = urb->context; - struct ssu100_port_private *priv = usb_get_serial_port_data(port); - char *data = (char *)urb->transfer_buffer; struct tty_struct *tty; - int count = 0; - int i; - int len; + int count; dbg("%s", __func__); @@ -698,10 +663,7 @@ static void ssu100_process_read_urb(struct urb *urb) if (!tty) return; - for (i = 0; i < urb->actual_length; i += priv->max_packet_size) { - len = min_t(int, urb->actual_length - i, priv->max_packet_size); - count += ssu100_process_packet(tty, port, priv, &data[i], len); - } + count = ssu100_process_packet(urb, tty); if (count) tty_flip_buffer_push(tty); @@ -717,8 +679,6 @@ static struct usb_serial_driver ssu100_device = { .id_table = id_table, .usb_driver = &ssu100_driver, .num_ports = 1, - .bulk_in_size = 256, - .bulk_out_size = 256, .open = ssu100_open, .close = ssu100_close, .attach = ssu100_attach, diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 861223f2af6e..6954de50c0ff 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -51,6 +51,7 @@ static struct usb_driver usb_serial_driver = { .suspend = usb_serial_suspend, .resume = usb_serial_resume, .no_dynamic_id = 1, + .supports_autosuspend = 1, }; /* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead @@ -1343,6 +1344,8 @@ int usb_serial_register(struct usb_serial_driver *driver) return -ENODEV; fixup_generic(driver); + if (driver->usb_driver) + driver->usb_driver->supports_autosuspend = 1; if (!driver->description) driver->description = driver->driver.name; diff --git a/drivers/usb/serial/usb-wwan.h b/drivers/usb/serial/usb-wwan.h index 2be298a1305b..3ab77c5d9819 100644 --- a/drivers/usb/serial/usb-wwan.h +++ b/drivers/usb/serial/usb-wwan.h @@ -18,6 +18,8 @@ extern void usb_wwan_set_termios(struct tty_struct *tty, extern int usb_wwan_tiocmget(struct tty_struct *tty, struct file *file); extern int usb_wwan_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); +extern int usb_wwan_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg); extern int usb_wwan_send_setup(struct usb_serial_port *port); extern int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count); diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index fbc946797801..b004b2a485c3 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -31,8 +31,10 @@ #include <linux/tty_flip.h> #include <linux/module.h> #include <linux/bitops.h> +#include <linux/uaccess.h> #include <linux/usb.h> #include <linux/usb/serial.h> +#include <linux/serial.h> #include "usb-wwan.h" static int debug; @@ -123,6 +125,83 @@ int usb_wwan_tiocmset(struct tty_struct *tty, struct file *file, } EXPORT_SYMBOL(usb_wwan_tiocmset); +static int get_serial_info(struct usb_serial_port *port, + struct serial_struct __user *retinfo) +{ + struct serial_struct tmp; + + if (!retinfo) + return -EFAULT; + + memset(&tmp, 0, sizeof(tmp)); + tmp.line = port->serial->minor; + tmp.port = port->number; + tmp.baud_base = tty_get_baud_rate(port->port.tty); + tmp.close_delay = port->port.close_delay / 10; + tmp.closing_wait = port->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ? + ASYNC_CLOSING_WAIT_NONE : + port->port.closing_wait / 10; + + if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) + return -EFAULT; + return 0; +} + +static int set_serial_info(struct usb_serial_port *port, + struct serial_struct __user *newinfo) +{ + struct serial_struct new_serial; + unsigned int closing_wait, close_delay; + int retval = 0; + + if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) + return -EFAULT; + + close_delay = new_serial.close_delay * 10; + closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ? + ASYNC_CLOSING_WAIT_NONE : new_serial.closing_wait * 10; + + mutex_lock(&port->port.mutex); + + if (!capable(CAP_SYS_ADMIN)) { + if ((close_delay != port->port.close_delay) || + (closing_wait != port->port.closing_wait)) + retval = -EPERM; + else + retval = -EOPNOTSUPP; + } else { + port->port.close_delay = close_delay; + port->port.closing_wait = closing_wait; + } + + mutex_unlock(&port->port.mutex); + return retval; +} + +int usb_wwan_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct usb_serial_port *port = tty->driver_data; + + dbg("%s cmd 0x%04x", __func__, cmd); + + switch (cmd) { + case TIOCGSERIAL: + return get_serial_info(port, + (struct serial_struct __user *) arg); + case TIOCSSERIAL: + return set_serial_info(port, + (struct serial_struct __user *) arg); + default: + break; + } + + dbg("%s arg not supported", __func__); + + return -ENOIOCTLCMD; +} +EXPORT_SYMBOL(usb_wwan_ioctl); + /* Write */ int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count) |