aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/serial/option.c1
-rw-r--r--drivers/usb/serial/usb-wwan.h2
-rw-r--r--drivers/usb/serial/usb_wwan.c78
3 files changed, 81 insertions, 0 deletions
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 2297fb1bcf65..2a56cc35ad31 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/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..660b7caef784 100644
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -33,6 +33,7 @@
33#include <linux/bitops.h> 33#include <linux/bitops.h>
34#include <linux/usb.h> 34#include <linux/usb.h>
35#include <linux/usb/serial.h> 35#include <linux/usb/serial.h>
36#include <linux/serial.h>
36#include "usb-wwan.h" 37#include "usb-wwan.h"
37 38
38static int debug; 39static int debug;
@@ -123,6 +124,83 @@ int usb_wwan_tiocmset(struct tty_struct *tty, struct file *file,
123} 124}
124EXPORT_SYMBOL(usb_wwan_tiocmset); 125EXPORT_SYMBOL(usb_wwan_tiocmset);
125 126
127static int get_serial_info(struct usb_serial_port *port,
128 struct serial_struct __user *retinfo)
129{
130 struct serial_struct tmp;
131
132 if (!retinfo)
133 return -EFAULT;
134
135 memset(&tmp, 0, sizeof(tmp));
136 tmp.line = port->serial->minor;
137 tmp.port = port->number;
138 tmp.baud_base = tty_get_baud_rate(port->port.tty);
139 tmp.close_delay = port->port.close_delay / 10;
140 tmp.closing_wait = port->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
141 ASYNC_CLOSING_WAIT_NONE :
142 port->port.closing_wait / 10;
143
144 if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
145 return -EFAULT;
146 return 0;
147}
148
149static int set_serial_info(struct usb_serial_port *port,
150 struct serial_struct __user *newinfo)
151{
152 struct serial_struct new_serial;
153 unsigned int closing_wait, close_delay;
154 int retval = 0;
155
156 if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
157 return -EFAULT;
158
159 close_delay = new_serial.close_delay * 10;
160 closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
161 ASYNC_CLOSING_WAIT_NONE : new_serial.closing_wait * 10;
162
163 mutex_lock(&port->port.mutex);
164
165 if (!capable(CAP_SYS_ADMIN)) {
166 if ((close_delay != port->port.close_delay) ||
167 (closing_wait != port->port.closing_wait))
168 retval = -EPERM;
169 else
170 retval = -EOPNOTSUPP;
171 } else {
172 port->port.close_delay = close_delay;
173 port->port.closing_wait = closing_wait;
174 }
175
176 mutex_unlock(&port->port.mutex);
177 return retval;
178}
179
180int usb_wwan_ioctl(struct tty_struct *tty, struct file *file,
181 unsigned int cmd, unsigned long arg)
182{
183 struct usb_serial_port *port = tty->driver_data;
184
185 dbg("%s cmd 0x%04x", __func__, cmd);
186
187 switch (cmd) {
188 case TIOCGSERIAL:
189 return get_serial_info(port,
190 (struct serial_struct __user *) arg);
191 case TIOCSSERIAL:
192 return set_serial_info(port,
193 (struct serial_struct __user *) arg);
194 default:
195 break;
196 }
197
198 dbg("%s arg not supported", __func__);
199
200 return -ENOIOCTLCMD;
201}
202EXPORT_SYMBOL(usb_wwan_ioctl);
203
126/* Write */ 204/* Write */
127int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port, 205int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port,
128 const unsigned char *buf, int count) 206 const unsigned char *buf, int count)