aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r--drivers/usb/serial/ftdi_sio.c27
-rw-r--r--drivers/usb/serial/option.c1
-rw-r--r--drivers/usb/serial/ssu100.c56
-rw-r--r--drivers/usb/serial/usb-wwan.h2
-rw-r--r--drivers/usb/serial/usb_wwan.c79
5 files changed, 117 insertions, 48 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 2dec50013528..a2668d089260 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -75,6 +75,7 @@ struct ftdi_private {
75 unsigned long last_dtr_rts; /* saved modem control outputs */ 75 unsigned long last_dtr_rts; /* saved modem control outputs */
76 wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ 76 wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
77 char prev_status, diff_status; /* Used for TIOCMIWAIT */ 77 char prev_status, diff_status; /* Used for TIOCMIWAIT */
78 char transmit_empty; /* If transmitter is empty or not */
78 struct usb_serial_port *port; 79 struct usb_serial_port *port;
79 __u16 interface; /* FT2232C, FT2232H or FT4232H port interface 80 __u16 interface; /* FT2232C, FT2232H or FT4232H port interface
80 (0 for FT232/245) */ 81 (0 for FT232/245) */
@@ -1323,6 +1324,23 @@ check_and_exit:
1323 return 0; 1324 return 0;
1324} 1325}
1325 1326
1327static int get_lsr_info(struct usb_serial_port *port,
1328 struct serial_struct __user *retinfo)
1329{
1330 struct ftdi_private *priv = usb_get_serial_port_data(port);
1331 unsigned int result = 0;
1332
1333 if (!retinfo)
1334 return -EFAULT;
1335
1336 if (priv->transmit_empty)
1337 result = TIOCSER_TEMT;
1338
1339 if (copy_to_user(retinfo, &result, sizeof(unsigned int)))
1340 return -EFAULT;
1341 return 0;
1342}
1343
1326 1344
1327/* Determine type of FTDI chip based on USB config and descriptor. */ 1345/* Determine type of FTDI chip based on USB config and descriptor. */
1328static void ftdi_determine_type(struct usb_serial_port *port) 1346static void ftdi_determine_type(struct usb_serial_port *port)
@@ -1872,6 +1890,12 @@ static int ftdi_process_packet(struct tty_struct *tty,
1872 tty_insert_flip_char(tty, 0, TTY_OVERRUN); 1890 tty_insert_flip_char(tty, 0, TTY_OVERRUN);
1873 } 1891 }
1874 1892
1893 /* save if the transmitter is empty or not */
1894 if (packet[1] & FTDI_RS_TEMT)
1895 priv->transmit_empty = 1;
1896 else
1897 priv->transmit_empty = 0;
1898
1875 len -= 2; 1899 len -= 2;
1876 if (!len) 1900 if (!len)
1877 return 0; /* status only */ 1901 return 0; /* status only */
@@ -2235,6 +2259,9 @@ static int ftdi_ioctl(struct tty_struct *tty, struct file *file,
2235 } 2259 }
2236 } 2260 }
2237 return 0; 2261 return 0;
2262 case TIOCSERGETLSR:
2263 return get_lsr_info(port, (struct serial_struct __user *)arg);
2264 break;
2238 default: 2265 default:
2239 break; 2266 break;
2240 } 2267 }
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 = {
989 .set_termios = usb_wwan_set_termios, 989 .set_termios = usb_wwan_set_termios,
990 .tiocmget = usb_wwan_tiocmget, 990 .tiocmget = usb_wwan_tiocmget,
991 .tiocmset = usb_wwan_tiocmset, 991 .tiocmset = usb_wwan_tiocmset,
992 .ioctl = usb_wwan_ioctl,
992 .attach = usb_wwan_startup, 993 .attach = usb_wwan_startup,
993 .disconnect = usb_wwan_disconnect, 994 .disconnect = usb_wwan_disconnect,
994 .release = usb_wwan_release, 995 .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 {
79 u8 shadowLSR; 79 u8 shadowLSR;
80 u8 shadowMSR; 80 u8 shadowMSR;
81 wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ 81 wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
82 unsigned short max_packet_size;
83 struct async_icount icount; 82 struct async_icount icount;
84}; 83};
85 84
@@ -464,36 +463,6 @@ static int ssu100_ioctl(struct tty_struct *tty, struct file *file,
464 return -ENOIOCTLCMD; 463 return -ENOIOCTLCMD;
465} 464}
466 465
467static void ssu100_set_max_packet_size(struct usb_serial_port *port)
468{
469 struct ssu100_port_private *priv = usb_get_serial_port_data(port);
470 struct usb_serial *serial = port->serial;
471 struct usb_device *udev = serial->dev;
472
473 struct usb_interface *interface = serial->interface;
474 struct usb_endpoint_descriptor *ep_desc = &interface->cur_altsetting->endpoint[1].desc;
475
476 unsigned num_endpoints;
477 int i;
478 unsigned long flags;
479
480 num_endpoints = interface->cur_altsetting->desc.bNumEndpoints;
481 dev_info(&udev->dev, "Number of endpoints %d\n", num_endpoints);
482
483 for (i = 0; i < num_endpoints; i++) {
484 dev_info(&udev->dev, "Endpoint %d MaxPacketSize %d\n", i+1,
485 interface->cur_altsetting->endpoint[i].desc.wMaxPacketSize);
486 ep_desc = &interface->cur_altsetting->endpoint[i].desc;
487 }
488
489 /* set max packet size based on descriptor */
490 spin_lock_irqsave(&priv->status_lock, flags);
491 priv->max_packet_size = ep_desc->wMaxPacketSize;
492 spin_unlock_irqrestore(&priv->status_lock, flags);
493
494 dev_info(&udev->dev, "Setting MaxPacketSize %d\n", priv->max_packet_size);
495}
496
497static int ssu100_attach(struct usb_serial *serial) 466static int ssu100_attach(struct usb_serial *serial)
498{ 467{
499 struct ssu100_port_private *priv; 468 struct ssu100_port_private *priv;
@@ -511,7 +480,6 @@ static int ssu100_attach(struct usb_serial *serial)
511 spin_lock_init(&priv->status_lock); 480 spin_lock_init(&priv->status_lock);
512 init_waitqueue_head(&priv->delta_msr_wait); 481 init_waitqueue_head(&priv->delta_msr_wait);
513 usb_set_serial_port_data(port, priv); 482 usb_set_serial_port_data(port, priv);
514 ssu100_set_max_packet_size(port);
515 483
516 return ssu100_initdevice(serial->dev); 484 return ssu100_initdevice(serial->dev);
517} 485}
@@ -641,13 +609,14 @@ static void ssu100_update_lsr(struct usb_serial_port *port, u8 lsr,
641 609
642} 610}
643 611
644static int ssu100_process_packet(struct tty_struct *tty, 612static int ssu100_process_packet(struct urb *urb,
645 struct usb_serial_port *port, 613 struct tty_struct *tty)
646 struct ssu100_port_private *priv,
647 char *packet, int len)
648{ 614{
649 int i; 615 struct usb_serial_port *port = urb->context;
616 char *packet = (char *)urb->transfer_buffer;
650 char flag = TTY_NORMAL; 617 char flag = TTY_NORMAL;
618 u32 len = urb->actual_length;
619 int i;
651 char *ch; 620 char *ch;
652 621
653 dbg("%s - port %d", __func__, port->number); 622 dbg("%s - port %d", __func__, port->number);
@@ -685,12 +654,8 @@ static int ssu100_process_packet(struct tty_struct *tty,
685static void ssu100_process_read_urb(struct urb *urb) 654static void ssu100_process_read_urb(struct urb *urb)
686{ 655{
687 struct usb_serial_port *port = urb->context; 656 struct usb_serial_port *port = urb->context;
688 struct ssu100_port_private *priv = usb_get_serial_port_data(port);
689 char *data = (char *)urb->transfer_buffer;
690 struct tty_struct *tty; 657 struct tty_struct *tty;
691 int count = 0; 658 int count;
692 int i;
693 int len;
694 659
695 dbg("%s", __func__); 660 dbg("%s", __func__);
696 661
@@ -698,10 +663,7 @@ static void ssu100_process_read_urb(struct urb *urb)
698 if (!tty) 663 if (!tty)
699 return; 664 return;
700 665
701 for (i = 0; i < urb->actual_length; i += priv->max_packet_size) { 666 count = ssu100_process_packet(urb, tty);
702 len = min_t(int, urb->actual_length - i, priv->max_packet_size);
703 count += ssu100_process_packet(tty, port, priv, &data[i], len);
704 }
705 667
706 if (count) 668 if (count)
707 tty_flip_buffer_push(tty); 669 tty_flip_buffer_push(tty);
@@ -717,8 +679,6 @@ static struct usb_serial_driver ssu100_device = {
717 .id_table = id_table, 679 .id_table = id_table,
718 .usb_driver = &ssu100_driver, 680 .usb_driver = &ssu100_driver,
719 .num_ports = 1, 681 .num_ports = 1,
720 .bulk_in_size = 256,
721 .bulk_out_size = 256,
722 .open = ssu100_open, 682 .open = ssu100_open,
723 .close = ssu100_close, 683 .close = ssu100_close,
724 .attach = ssu100_attach, 684 .attach = ssu100_attach,
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,
18extern int usb_wwan_tiocmget(struct tty_struct *tty, struct file *file); 18extern int usb_wwan_tiocmget(struct tty_struct *tty, struct file *file);
19extern int usb_wwan_tiocmset(struct tty_struct *tty, struct file *file, 19extern int usb_wwan_tiocmset(struct tty_struct *tty, struct file *file,
20 unsigned int set, unsigned int clear); 20 unsigned int set, unsigned int clear);
21extern int usb_wwan_ioctl(struct tty_struct *tty, struct file *file,
22 unsigned int cmd, unsigned long arg);
21extern int usb_wwan_send_setup(struct usb_serial_port *port); 23extern int usb_wwan_send_setup(struct usb_serial_port *port);
22extern int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port, 24extern int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port,
23 const unsigned char *buf, int count); 25 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 @@
31#include <linux/tty_flip.h> 31#include <linux/tty_flip.h>
32#include <linux/module.h> 32#include <linux/module.h>
33#include <linux/bitops.h> 33#include <linux/bitops.h>
34#include <linux/uaccess.h>
34#include <linux/usb.h> 35#include <linux/usb.h>
35#include <linux/usb/serial.h> 36#include <linux/usb/serial.h>
37#include <linux/serial.h>
36#include "usb-wwan.h" 38#include "usb-wwan.h"
37 39
38static int debug; 40static int debug;
@@ -123,6 +125,83 @@ int usb_wwan_tiocmset(struct tty_struct *tty, struct file *file,
123} 125}
124EXPORT_SYMBOL(usb_wwan_tiocmset); 126EXPORT_SYMBOL(usb_wwan_tiocmset);
125 127
128static int get_serial_info(struct usb_serial_port *port,
129 struct serial_struct __user *retinfo)
130{
131 struct serial_struct tmp;
132
133 if (!retinfo)
134 return -EFAULT;
135
136 memset(&tmp, 0, sizeof(tmp));
137 tmp.line = port->serial->minor;
138 tmp.port = port->number;
139 tmp.baud_base = tty_get_baud_rate(port->port.tty);
140 tmp.close_delay = port->port.close_delay / 10;
141 tmp.closing_wait = port->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
142 ASYNC_CLOSING_WAIT_NONE :
143 port->port.closing_wait / 10;
144
145 if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
146 return -EFAULT;
147 return 0;
148}
149
150static int set_serial_info(struct usb_serial_port *port,
151 struct serial_struct __user *newinfo)
152{
153 struct serial_struct new_serial;
154 unsigned int closing_wait, close_delay;
155 int retval = 0;
156
157 if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
158 return -EFAULT;
159
160 close_delay = new_serial.close_delay * 10;
161 closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
162 ASYNC_CLOSING_WAIT_NONE : new_serial.closing_wait * 10;
163
164 mutex_lock(&port->port.mutex);
165
166 if (!capable(CAP_SYS_ADMIN)) {
167 if ((close_delay != port->port.close_delay) ||
168 (closing_wait != port->port.closing_wait))
169 retval = -EPERM;
170 else
171 retval = -EOPNOTSUPP;
172 } else {
173 port->port.close_delay = close_delay;
174 port->port.closing_wait = closing_wait;
175 }
176
177 mutex_unlock(&port->port.mutex);
178 return retval;
179}
180
181int usb_wwan_ioctl(struct tty_struct *tty, struct file *file,
182 unsigned int cmd, unsigned long arg)
183{
184 struct usb_serial_port *port = tty->driver_data;
185
186 dbg("%s cmd 0x%04x", __func__, cmd);
187
188 switch (cmd) {
189 case TIOCGSERIAL:
190 return get_serial_info(port,
191 (struct serial_struct __user *) arg);
192 case TIOCSSERIAL:
193 return set_serial_info(port,
194 (struct serial_struct __user *) arg);
195 default:
196 break;
197 }
198
199 dbg("%s arg not supported", __func__);
200
201 return -ENOIOCTLCMD;
202}
203EXPORT_SYMBOL(usb_wwan_ioctl);
204
126/* Write */ 205/* Write */
127int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port, 206int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port,
128 const unsigned char *buf, int count) 207 const unsigned char *buf, int count)