blob: a9934a3f984591700cfa64e8dce7d31900035c64 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * USB Serial Converter driver
3 *
Greg Kroah-Hartman502b95c2005-06-20 21:15:16 -07004 * Copyright (C) 1999 - 2005 Greg Kroah-Hartman (greg@kroah.com)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 * Copyright (C) 2000 Peter Berger (pberger@brimson.com)
6 * Copyright (C) 2000 Al Borchers (borchers@steinerpoint.com)
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version
10 * 2 as published by the Free Software Foundation.
11 *
Greg Kroah-Hartman502b95c2005-06-20 21:15:16 -070012 * This driver was originally based on the ACM driver by Armin Fuerst (which was
Linus Torvalds1da177e2005-04-16 15:20:36 -070013 * based on a driver by Brad Keryan)
14 *
15 * See Documentation/usb/usb-serial.txt for more information on using this driver
16 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070017 */
18
Linus Torvalds1da177e2005-04-16 15:20:36 -070019#include <linux/kernel.h>
20#include <linux/errno.h>
21#include <linux/init.h>
22#include <linux/slab.h>
23#include <linux/tty.h>
24#include <linux/tty_driver.h>
25#include <linux/tty_flip.h>
26#include <linux/module.h>
27#include <linux/moduleparam.h>
28#include <linux/spinlock.h>
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -030029#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <linux/list.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <asm/uaccess.h>
32#include <linux/usb.h>
Greg Kroah-Hartmana9698882006-07-11 21:22:58 -070033#include <linux/usb/serial.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include "pl2303.h"
35
36/*
37 * Version Information
38 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070039#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/"
40#define DRIVER_DESC "USB Serial Driver core"
41
Pete Zaitcev34f8e762006-06-21 15:00:45 -070042static void port_free(struct usb_serial_port *port);
43
Linus Torvalds1da177e2005-04-16 15:20:36 -070044/* Driver structure we register with the USB core */
45static struct usb_driver usb_serial_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070046 .name = "usbserial",
47 .probe = usb_serial_probe,
48 .disconnect = usb_serial_disconnect,
Oliver Neukumec225592007-04-27 20:54:57 +020049 .suspend = usb_serial_suspend,
50 .resume = usb_serial_resume,
Greg Kroah-Hartmanba9dc652005-11-16 13:41:28 -080051 .no_dynamic_id = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -070052};
53
54/* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead
55 the MODULE_DEVICE_TABLE declarations in each serial driver
56 cause the "hotplug" program to pull in whatever module is necessary
57 via modprobe, and modprobe will load usbserial because the serial
58 drivers depend on it.
59*/
60
61static int debug;
62static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */
Oliver Neukum3ddad822007-07-24 15:13:42 +020063static DEFINE_MUTEX(table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070064static LIST_HEAD(usb_serial_driver_list);
65
66struct usb_serial *usb_serial_get_by_index(unsigned index)
67{
Oliver Neukum34ef50e2007-01-13 07:29:26 +010068 struct usb_serial *serial;
69
Oliver Neukum3ddad822007-07-24 15:13:42 +020070 mutex_lock(&table_lock);
Oliver Neukum34ef50e2007-01-13 07:29:26 +010071 serial = serial_table[index];
Linus Torvalds1da177e2005-04-16 15:20:36 -070072
73 if (serial)
74 kref_get(&serial->kref);
Oliver Neukum3ddad822007-07-24 15:13:42 +020075 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070076 return serial;
77}
78
79static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_ports, unsigned int *minor)
80{
81 unsigned int i, j;
82 int good_spot;
83
Harvey Harrison441b62c2008-03-03 16:08:34 -080084 dbg("%s %d", __func__, num_ports);
Linus Torvalds1da177e2005-04-16 15:20:36 -070085
86 *minor = 0;
Oliver Neukum3ddad822007-07-24 15:13:42 +020087 mutex_lock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070088 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
89 if (serial_table[i])
90 continue;
91
92 good_spot = 1;
93 for (j = 1; j <= num_ports-1; ++j)
94 if ((i+j >= SERIAL_TTY_MINORS) || (serial_table[i+j])) {
95 good_spot = 0;
96 i += j;
97 break;
98 }
99 if (good_spot == 0)
100 continue;
101
102 *minor = i;
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100103 j = 0;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800104 dbg("%s - minor base = %d", __func__, *minor);
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100105 for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106 serial_table[i] = serial;
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100107 serial->port[j++]->number = i;
108 }
Oliver Neukum3ddad822007-07-24 15:13:42 +0200109 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110 return serial;
111 }
Oliver Neukum3ddad822007-07-24 15:13:42 +0200112 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113 return NULL;
114}
115
116static void return_serial(struct usb_serial *serial)
117{
118 int i;
119
Harvey Harrison441b62c2008-03-03 16:08:34 -0800120 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121
122 if (serial == NULL)
123 return;
124
125 for (i = 0; i < serial->num_ports; ++i) {
126 serial_table[serial->minor + i] = NULL;
127 }
128}
129
130static void destroy_serial(struct kref *kref)
131{
132 struct usb_serial *serial;
133 struct usb_serial_port *port;
134 int i;
135
136 serial = to_usb_serial(kref);
137
Harvey Harrison441b62c2008-03-03 16:08:34 -0800138 dbg("%s - %s", __func__, serial->type->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139
Jim Radford521b85a2007-03-13 08:30:50 -0700140 serial->type->shutdown(serial);
141
142 /* return the minor range that this device had */
143 return_serial(serial);
144
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145 for (i = 0; i < serial->num_ports; ++i)
146 serial->port[i]->open_count = 0;
147
148 /* the ports are cleaned up and released in port_release() */
149 for (i = 0; i < serial->num_ports; ++i)
150 if (serial->port[i]->dev.parent != NULL) {
151 device_unregister(&serial->port[i]->dev);
152 serial->port[i] = NULL;
153 }
154
155 /* If this is a "fake" port, we have to clean it up here, as it will
156 * not get cleaned up in port_release() as it was never registered with
157 * the driver core */
158 if (serial->num_ports < serial->num_port_pointers) {
159 for (i = serial->num_ports; i < serial->num_port_pointers; ++i) {
160 port = serial->port[i];
161 if (!port)
162 continue;
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700163 port_free(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164 }
165 }
166
167 usb_put_dev(serial->dev);
168
169 /* free up any memory that we allocated */
170 kfree (serial);
171}
172
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200173void usb_serial_put(struct usb_serial *serial)
174{
Oliver Neukum3ddad822007-07-24 15:13:42 +0200175 mutex_lock(&table_lock);
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200176 kref_put(&serial->kref, destroy_serial);
Oliver Neukum3ddad822007-07-24 15:13:42 +0200177 mutex_unlock(&table_lock);
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200178}
179
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180/*****************************************************************************
181 * Driver tty interface functions
182 *****************************************************************************/
183static int serial_open (struct tty_struct *tty, struct file * filp)
184{
185 struct usb_serial *serial;
186 struct usb_serial_port *port;
187 unsigned int portNumber;
188 int retval;
189
Harvey Harrison441b62c2008-03-03 16:08:34 -0800190 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191
192 /* get the serial object associated with this tty pointer */
193 serial = usb_serial_get_by_index(tty->index);
194 if (!serial) {
195 tty->driver_data = NULL;
196 return -ENODEV;
197 }
198
199 portNumber = tty->index - serial->minor;
200 port = serial->port[portNumber];
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300201 if (!port) {
202 retval = -ENODEV;
203 goto bailout_kref_put;
204 }
Luiz Fernando Capitulino8a4613f2005-11-28 19:16:07 -0200205
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300206 if (mutex_lock_interruptible(&port->mutex)) {
207 retval = -ERESTARTSYS;
208 goto bailout_kref_put;
209 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210
211 ++port->open_count;
212
Paul Fulghumca854852006-04-13 22:28:17 +0200213 /* set up our port structure making the tty driver
214 * remember our port object, and us it */
215 tty->driver_data = port;
216 port->tty = tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217
Paul Fulghumca854852006-04-13 22:28:17 +0200218 if (port->open_count == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219
220 /* lock this module before we call it
221 * this may fail, which means we must bail out,
222 * safe because we are called with BKL held */
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700223 if (!try_module_get(serial->type->driver.owner)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 retval = -ENODEV;
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300225 goto bailout_mutex_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226 }
227
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800228 retval = usb_autopm_get_interface(serial->interface);
229 if (retval)
230 goto bailout_module_put;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231 /* only call the device specific open if this
232 * is the first time the port is opened */
233 retval = serial->type->open(port, filp);
234 if (retval)
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800235 goto bailout_interface_put;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236 }
237
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300238 mutex_unlock(&port->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 return 0;
240
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800241bailout_interface_put:
242 usb_autopm_put_interface(serial->interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243bailout_module_put:
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700244 module_put(serial->type->driver.owner);
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300245bailout_mutex_unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246 port->open_count = 0;
Frank Gevaertsb059c812006-06-14 15:52:05 +0200247 tty->driver_data = NULL;
248 port->tty = NULL;
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300249 mutex_unlock(&port->mutex);
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300250bailout_kref_put:
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200251 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 return retval;
253}
254
255static void serial_close(struct tty_struct *tty, struct file * filp)
256{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200257 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258
259 if (!port)
260 return;
261
Harvey Harrison441b62c2008-03-03 16:08:34 -0800262 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300264 mutex_lock(&port->mutex);
Luiz Fernando Capitulino8a4613f2005-11-28 19:16:07 -0200265
Greg Kroah-Hartman91c0bce2006-03-06 13:25:52 -0800266 if (port->open_count == 0) {
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300267 mutex_unlock(&port->mutex);
Greg Kroah-Hartman91c0bce2006-03-06 13:25:52 -0800268 return;
269 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270
271 --port->open_count;
Aristeu Rozanski9a6b1ef2007-11-12 15:15:02 -0500272 if (port->open_count == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 /* only call the device specific close if this
274 * port is being closed by the last owner */
275 port->serial->type->close(port, filp);
276
Aristeu Rozanski9a6b1ef2007-11-12 15:15:02 -0500277 if (port->open_count == (port->console? 1 : 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 if (port->tty) {
279 if (port->tty->driver_data)
280 port->tty->driver_data = NULL;
281 port->tty = NULL;
282 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 }
284
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800285 if (port->open_count == 0) {
286 usb_autopm_put_interface(port->serial->interface);
Aristeu Rozanski9a6b1ef2007-11-12 15:15:02 -0500287 module_put(port->serial->type->driver.owner);
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800288 }
Aristeu Rozanski9a6b1ef2007-11-12 15:15:02 -0500289
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300290 mutex_unlock(&port->mutex);
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200291 usb_serial_put(port->serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292}
293
294static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count)
295{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200296 struct usb_serial_port *port = tty->driver_data;
Oliver Neukum3ff4fd92007-01-13 07:32:27 +0100297 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200299 if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED)
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200300 goto exit;
301
Harvey Harrison441b62c2008-03-03 16:08:34 -0800302 dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303
304 if (!port->open_count) {
Oliver Neukum3ff4fd92007-01-13 07:32:27 +0100305 retval = -EINVAL;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800306 dbg("%s - port not opened", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 goto exit;
308 }
309
310 /* pass on to the driver specific version of this function */
311 retval = port->serial->type->write(port, buf, count);
312
313exit:
314 return retval;
315}
316
317static int serial_write_room (struct tty_struct *tty)
318{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200319 struct usb_serial_port *port = tty->driver_data;
Luiz Fernando N. Capitulinodb54a532006-06-12 22:46:20 -0300320 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200322 if (!port)
323 goto exit;
324
Harvey Harrison441b62c2008-03-03 16:08:34 -0800325 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326
327 if (!port->open_count) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800328 dbg("%s - port not open", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 goto exit;
330 }
331
332 /* pass on to the driver specific version of this function */
333 retval = port->serial->type->write_room(port);
334
335exit:
336 return retval;
337}
338
339static int serial_chars_in_buffer (struct tty_struct *tty)
340{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200341 struct usb_serial_port *port = tty->driver_data;
Luiz Fernando N. Capitulinodb54a532006-06-12 22:46:20 -0300342 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200344 if (!port)
345 goto exit;
346
Harvey Harrison441b62c2008-03-03 16:08:34 -0800347 dbg("%s = port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348
349 if (!port->open_count) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800350 dbg("%s - port not open", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 goto exit;
352 }
353
354 /* pass on to the driver specific version of this function */
355 retval = port->serial->type->chars_in_buffer(port);
356
357exit:
358 return retval;
359}
360
361static void serial_throttle (struct tty_struct * tty)
362{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200363 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200365 if (!port)
366 return;
367
Harvey Harrison441b62c2008-03-03 16:08:34 -0800368 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369
370 if (!port->open_count) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800371 dbg ("%s - port not open", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 return;
373 }
374
375 /* pass on to the driver specific version of this function */
376 if (port->serial->type->throttle)
377 port->serial->type->throttle(port);
378}
379
380static void serial_unthrottle (struct tty_struct * tty)
381{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200382 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200384 if (!port)
385 return;
386
Harvey Harrison441b62c2008-03-03 16:08:34 -0800387 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388
389 if (!port->open_count) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800390 dbg("%s - port not open", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 return;
392 }
393
394 /* pass on to the driver specific version of this function */
395 if (port->serial->type->unthrottle)
396 port->serial->type->unthrottle(port);
397}
398
399static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
400{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200401 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 int retval = -ENODEV;
403
Alan Cox20978902008-02-20 20:47:56 +0000404 lock_kernel();
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200405 if (!port)
406 goto exit;
407
Harvey Harrison441b62c2008-03-03 16:08:34 -0800408 dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409
Alan Cox20978902008-02-20 20:47:56 +0000410 /* Caution - port->open_count is BKL protected */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 if (!port->open_count) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800412 dbg ("%s - port not open", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 goto exit;
414 }
415
416 /* pass on to the driver specific version of this function if it is available */
417 if (port->serial->type->ioctl)
418 retval = port->serial->type->ioctl(port, file, cmd, arg);
419 else
420 retval = -ENOIOCTLCMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421exit:
Alan Cox20978902008-02-20 20:47:56 +0000422 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 return retval;
424}
425
Alan Cox606d0992006-12-08 02:38:45 -0800426static void serial_set_termios (struct tty_struct *tty, struct ktermios * old)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200428 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200430 if (!port)
431 return;
432
Harvey Harrison441b62c2008-03-03 16:08:34 -0800433 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434
435 if (!port->open_count) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800436 dbg("%s - port not open", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 return;
438 }
439
440 /* pass on to the driver specific version of this function if it is available */
441 if (port->serial->type->set_termios)
442 port->serial->type->set_termios(port, old);
Alan Cox33785092007-10-18 01:24:22 -0700443 else
444 tty_termios_copy_hw(tty->termios, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445}
446
447static void serial_break (struct tty_struct *tty, int break_state)
448{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200449 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450
Alan Cox20978902008-02-20 20:47:56 +0000451 lock_kernel();
452 if (!port) {
453 unlock_kernel();
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200454 return;
Alan Cox20978902008-02-20 20:47:56 +0000455 }
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200456
Harvey Harrison441b62c2008-03-03 16:08:34 -0800457 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458
459 if (!port->open_count) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800460 dbg("%s - port not open", __func__);
Alan Cox20978902008-02-20 20:47:56 +0000461 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 return;
463 }
464
465 /* pass on to the driver specific version of this function if it is available */
466 if (port->serial->type->break_ctl)
467 port->serial->type->break_ctl(port, break_state);
Alan Cox20978902008-02-20 20:47:56 +0000468 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469}
470
471static int serial_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data)
472{
473 struct usb_serial *serial;
474 int length = 0;
475 int i;
476 off_t begin = 0;
477 char tmp[40];
478
Harvey Harrison441b62c2008-03-03 16:08:34 -0800479 dbg("%s", __func__);
Greg Kroah-Hartman17a882f2005-06-20 21:15:16 -0700480 length += sprintf (page, "usbserinfo:1.0 driver:2.0\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 for (i = 0; i < SERIAL_TTY_MINORS && length < PAGE_SIZE; ++i) {
482 serial = usb_serial_get_by_index(i);
483 if (serial == NULL)
484 continue;
485
486 length += sprintf (page+length, "%d:", i);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700487 if (serial->type->driver.owner)
488 length += sprintf (page+length, " module:%s", module_name(serial->type->driver.owner));
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -0700489 length += sprintf (page+length, " name:\"%s\"", serial->type->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 length += sprintf (page+length, " vendor:%04x product:%04x",
491 le16_to_cpu(serial->dev->descriptor.idVendor),
492 le16_to_cpu(serial->dev->descriptor.idProduct));
493 length += sprintf (page+length, " num_ports:%d", serial->num_ports);
494 length += sprintf (page+length, " port:%d", i - serial->minor + 1);
495
496 usb_make_path(serial->dev, tmp, sizeof(tmp));
497 length += sprintf (page+length, " path:%s", tmp);
498
499 length += sprintf (page+length, "\n");
Matthias Urlichs59925832006-09-11 12:35:20 +0200500 if ((length + begin) > (off + count)) {
501 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 goto done;
Matthias Urlichs59925832006-09-11 12:35:20 +0200503 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 if ((length + begin) < off) {
505 begin += length;
506 length = 0;
507 }
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200508 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 }
510 *eof = 1;
511done:
512 if (off >= (length + begin))
513 return 0;
514 *start = page + (off-begin);
515 return ((count < begin+length-off) ? count : begin+length-off);
516}
517
518static int serial_tiocmget (struct tty_struct *tty, struct file *file)
519{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200520 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200522 if (!port)
Luiz Fernando N. Capitulinodb54a532006-06-12 22:46:20 -0300523 return -ENODEV;
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200524
Harvey Harrison441b62c2008-03-03 16:08:34 -0800525 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526
527 if (!port->open_count) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800528 dbg("%s - port not open", __func__);
Luiz Fernando N. Capitulinodb54a532006-06-12 22:46:20 -0300529 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 }
531
532 if (port->serial->type->tiocmget)
533 return port->serial->type->tiocmget(port, file);
534
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 return -EINVAL;
536}
537
538static int serial_tiocmset (struct tty_struct *tty, struct file *file,
539 unsigned int set, unsigned int clear)
540{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200541 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200543 if (!port)
Luiz Fernando N. Capitulinodb54a532006-06-12 22:46:20 -0300544 return -ENODEV;
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200545
Harvey Harrison441b62c2008-03-03 16:08:34 -0800546 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547
548 if (!port->open_count) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800549 dbg("%s - port not open", __func__);
Luiz Fernando N. Capitulinodb54a532006-06-12 22:46:20 -0300550 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 }
552
553 if (port->serial->type->tiocmset)
554 return port->serial->type->tiocmset(port, file, set, clear);
555
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556 return -EINVAL;
557}
558
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700559/*
560 * We would be calling tty_wakeup here, but unfortunately some line
561 * disciplines have an annoying habit of calling tty->write from
562 * the write wakeup callback (e.g. n_hdlc.c).
563 */
564void usb_serial_port_softint(struct usb_serial_port *port)
565{
566 schedule_work(&port->work);
567}
568
David Howellsc4028952006-11-22 14:57:56 +0000569static void usb_serial_port_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570{
David Howellsc4028952006-11-22 14:57:56 +0000571 struct usb_serial_port *port =
572 container_of(work, struct usb_serial_port, work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 struct tty_struct *tty;
574
Harvey Harrison441b62c2008-03-03 16:08:34 -0800575 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576
577 if (!port)
578 return;
579
580 tty = port->tty;
581 if (!tty)
582 return;
583
584 tty_wakeup(tty);
585}
586
587static void port_release(struct device *dev)
588{
589 struct usb_serial_port *port = to_usb_serial_port(dev);
590
Harvey Harrison441b62c2008-03-03 16:08:34 -0800591 dbg ("%s - %s", __func__, dev->bus_id);
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700592 port_free(port);
593}
594
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100595static void kill_traffic(struct usb_serial_port *port)
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700596{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598 usb_kill_urb(port->write_urb);
Oliver Neukum5adceac2007-08-17 14:01:38 +0200599 /*
600 * This is tricky.
601 * Some drivers submit the read_urb in the
602 * handler for the write_urb or vice versa
603 * this order determines the order in which
604 * usb_kill_urb() must be used to reliably
605 * kill the URBs. As it is unknown here,
606 * both orders must be used in turn.
607 * The call below is not redundant.
608 */
609 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610 usb_kill_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 usb_kill_urb(port->interrupt_out_urb);
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100612}
613
614static void port_free(struct usb_serial_port *port)
615{
616 kill_traffic(port);
617 usb_free_urb(port->read_urb);
618 usb_free_urb(port->write_urb);
619 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 usb_free_urb(port->interrupt_out_urb);
621 kfree(port->bulk_in_buffer);
622 kfree(port->bulk_out_buffer);
623 kfree(port->interrupt_in_buffer);
624 kfree(port->interrupt_out_buffer);
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700625 flush_scheduled_work(); /* port->work */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 kfree(port);
627}
628
629static struct usb_serial * create_serial (struct usb_device *dev,
630 struct usb_interface *interface,
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700631 struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632{
633 struct usb_serial *serial;
634
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100635 serial = kzalloc(sizeof(*serial), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 if (!serial) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800637 dev_err(&dev->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 return NULL;
639 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 serial->dev = usb_get_dev(dev);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700641 serial->type = driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642 serial->interface = interface;
643 kref_init(&serial->kref);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +0100644 mutex_init(&serial->disc_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645
646 return serial;
647}
648
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100649static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf,
650 struct usb_serial_driver *drv)
651{
652 struct usb_dynid *dynid;
653
654 spin_lock(&drv->dynids.lock);
655 list_for_each_entry(dynid, &drv->dynids.list, node) {
656 if (usb_match_one_id(intf, &dynid->id)) {
657 spin_unlock(&drv->dynids.lock);
658 return &dynid->id;
659 }
660 }
661 spin_unlock(&drv->dynids.lock);
662 return NULL;
663}
664
665static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv,
666 struct usb_interface *intf)
667{
668 const struct usb_device_id *id;
669
670 id = usb_match_id(intf, drv->id_table);
671 if (id) {
672 dbg("static descriptor matches");
673 goto exit;
674 }
675 id = match_dynamic_id(intf, drv);
676 if (id)
677 dbg("dynamic descriptor matches");
678exit:
679 return id;
680}
681
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700682static struct usb_serial_driver *search_serial_device(struct usb_interface *iface)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 const struct usb_device_id *id;
Alan Stern063a2da2007-10-10 16:24:06 -0400685 struct usb_serial_driver *drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686
Adrian Bunk93b1fae2006-01-10 00:13:33 +0100687 /* Check if the usb id matches a known device */
Alan Stern063a2da2007-10-10 16:24:06 -0400688 list_for_each_entry(drv, &usb_serial_driver_list, driver_list) {
689 id = get_iface_id(drv, iface);
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100690 if (id)
Alan Stern063a2da2007-10-10 16:24:06 -0400691 return drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692 }
693
694 return NULL;
695}
696
697int usb_serial_probe(struct usb_interface *interface,
698 const struct usb_device_id *id)
699{
700 struct usb_device *dev = interface_to_usbdev (interface);
701 struct usb_serial *serial = NULL;
702 struct usb_serial_port *port;
703 struct usb_host_interface *iface_desc;
704 struct usb_endpoint_descriptor *endpoint;
705 struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS];
706 struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS];
707 struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];
708 struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700709 struct usb_serial_driver *type = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710 int retval;
711 int minor;
712 int buffer_size;
713 int i;
714 int num_interrupt_in = 0;
715 int num_interrupt_out = 0;
716 int num_bulk_in = 0;
717 int num_bulk_out = 0;
718 int num_ports = 0;
719 int max_endpoints;
720
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100721 lock_kernel(); /* guard against unloading a serial driver module */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 type = search_serial_device(interface);
723 if (!type) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100724 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 dbg("none matched");
726 return -ENODEV;
727 }
728
729 serial = create_serial (dev, interface, type);
730 if (!serial) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100731 unlock_kernel();
Harvey Harrison441b62c2008-03-03 16:08:34 -0800732 dev_err(&interface->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 return -ENOMEM;
734 }
735
736 /* if this device type has a probe function, call it */
737 if (type->probe) {
738 const struct usb_device_id *id;
739
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700740 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100741 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 dev_err(&interface->dev, "module get failed, exiting\n");
743 kfree (serial);
744 return -EIO;
745 }
746
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100747 id = get_iface_id(type, interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 retval = type->probe(serial, id);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700749 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750
751 if (retval) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100752 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 dbg ("sub driver rejected device");
754 kfree (serial);
755 return retval;
756 }
757 }
758
759 /* descriptor matches, let's find the endpoints needed */
760 /* check out the endpoints */
761 iface_desc = interface->cur_altsetting;
762 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
763 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700764
765 if (usb_endpoint_is_bulk_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 /* we found a bulk in endpoint */
767 dbg("found bulk in on endpoint %d", i);
768 bulk_in_endpoint[num_bulk_in] = endpoint;
769 ++num_bulk_in;
770 }
771
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700772 if (usb_endpoint_is_bulk_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 /* we found a bulk out endpoint */
774 dbg("found bulk out on endpoint %d", i);
775 bulk_out_endpoint[num_bulk_out] = endpoint;
776 ++num_bulk_out;
777 }
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700778
779 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 /* we found a interrupt in endpoint */
781 dbg("found interrupt in on endpoint %d", i);
782 interrupt_in_endpoint[num_interrupt_in] = endpoint;
783 ++num_interrupt_in;
784 }
785
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700786 if (usb_endpoint_is_int_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 /* we found an interrupt out endpoint */
788 dbg("found interrupt out on endpoint %d", i);
789 interrupt_out_endpoint[num_interrupt_out] = endpoint;
790 ++num_interrupt_out;
791 }
792 }
793
794#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
795 /* BEGIN HORRIBLE HACK FOR PL2303 */
796 /* this is needed due to the looney way its endpoints are set up */
797 if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&
798 (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||
799 ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) &&
Johannes Steingraeber8fd80132006-09-16 16:17:34 +0200800 (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) ||
801 ((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) &&
802 (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 if (interface != dev->actconfig->interface[0]) {
804 /* check out the endpoints of the other interface*/
805 iface_desc = dev->actconfig->interface[0]->cur_altsetting;
806 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
807 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700808 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 /* we found a interrupt in endpoint */
810 dbg("found interrupt in for Prolific device on separate interface");
811 interrupt_in_endpoint[num_interrupt_in] = endpoint;
812 ++num_interrupt_in;
813 }
814 }
815 }
816
817 /* Now make sure the PL-2303 is configured correctly.
818 * If not, give up now and hope this hack will work
819 * properly during a later invocation of usb_serial_probe
820 */
821 if (num_bulk_in == 0 || num_bulk_out == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100822 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
824 kfree (serial);
825 return -ENODEV;
826 }
827 }
828 /* END HORRIBLE HACK FOR PL2303 */
829#endif
830
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831#ifdef CONFIG_USB_SERIAL_GENERIC
832 if (type == &usb_serial_generic_device) {
833 num_ports = num_bulk_out;
834 if (num_ports == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100835 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 dev_err(&interface->dev, "Generic device with no bulk out, not allowed.\n");
837 kfree (serial);
838 return -EIO;
839 }
840 }
841#endif
842 if (!num_ports) {
843 /* if this device type has a calc_num_ports function, call it */
844 if (type->calc_num_ports) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700845 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100846 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 dev_err(&interface->dev, "module get failed, exiting\n");
848 kfree (serial);
849 return -EIO;
850 }
851 num_ports = type->calc_num_ports (serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700852 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 }
854 if (!num_ports)
855 num_ports = type->num_ports;
856 }
857
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 serial->num_ports = num_ports;
859 serial->num_bulk_in = num_bulk_in;
860 serial->num_bulk_out = num_bulk_out;
861 serial->num_interrupt_in = num_interrupt_in;
862 serial->num_interrupt_out = num_interrupt_out;
863
Alan Stern063a2da2007-10-10 16:24:06 -0400864 /* found all that we need */
865 dev_info(&interface->dev, "%s converter detected\n",
866 type->description);
867
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 /* create our ports, we need as many as the max endpoints */
869 /* we don't use num_ports here cauz some devices have more endpoint pairs than ports */
870 max_endpoints = max(num_bulk_in, num_bulk_out);
871 max_endpoints = max(max_endpoints, num_interrupt_in);
872 max_endpoints = max(max_endpoints, num_interrupt_out);
873 max_endpoints = max(max_endpoints, (int)serial->num_ports);
874 serial->num_port_pointers = max_endpoints;
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100875 unlock_kernel();
876
Harvey Harrison441b62c2008-03-03 16:08:34 -0800877 dbg("%s - setting up %d port structures for this device", __func__, max_endpoints);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878 for (i = 0; i < max_endpoints; ++i) {
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100879 port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 if (!port)
881 goto probe_error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 port->serial = serial;
Greg Kroah-Hartman507ca9b2005-04-23 12:49:16 -0700883 spin_lock_init(&port->lock);
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300884 mutex_init(&port->mutex);
David Howellsc4028952006-11-22 14:57:56 +0000885 INIT_WORK(&port->work, usb_serial_port_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 serial->port[i] = port;
887 }
888
889 /* set up the endpoint information */
890 for (i = 0; i < num_bulk_in; ++i) {
891 endpoint = bulk_in_endpoint[i];
892 port = serial->port[i];
893 port->read_urb = usb_alloc_urb (0, GFP_KERNEL);
894 if (!port->read_urb) {
895 dev_err(&interface->dev, "No free urbs available\n");
896 goto probe_error;
897 }
898 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
899 port->bulk_in_size = buffer_size;
900 port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
901 port->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
902 if (!port->bulk_in_buffer) {
903 dev_err(&interface->dev, "Couldn't allocate bulk_in_buffer\n");
904 goto probe_error;
905 }
906 usb_fill_bulk_urb (port->read_urb, dev,
907 usb_rcvbulkpipe (dev,
908 endpoint->bEndpointAddress),
909 port->bulk_in_buffer, buffer_size,
910 serial->type->read_bulk_callback,
911 port);
912 }
913
914 for (i = 0; i < num_bulk_out; ++i) {
915 endpoint = bulk_out_endpoint[i];
916 port = serial->port[i];
917 port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
918 if (!port->write_urb) {
919 dev_err(&interface->dev, "No free urbs available\n");
920 goto probe_error;
921 }
922 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
923 port->bulk_out_size = buffer_size;
924 port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
925 port->bulk_out_buffer = kmalloc (buffer_size, GFP_KERNEL);
926 if (!port->bulk_out_buffer) {
927 dev_err(&interface->dev, "Couldn't allocate bulk_out_buffer\n");
928 goto probe_error;
929 }
930 usb_fill_bulk_urb (port->write_urb, dev,
931 usb_sndbulkpipe (dev,
932 endpoint->bEndpointAddress),
933 port->bulk_out_buffer, buffer_size,
934 serial->type->write_bulk_callback,
935 port);
936 }
937
938 if (serial->type->read_int_callback) {
939 for (i = 0; i < num_interrupt_in; ++i) {
940 endpoint = interrupt_in_endpoint[i];
941 port = serial->port[i];
942 port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
943 if (!port->interrupt_in_urb) {
944 dev_err(&interface->dev, "No free urbs available\n");
945 goto probe_error;
946 }
947 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
948 port->interrupt_in_endpointAddress = endpoint->bEndpointAddress;
949 port->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
950 if (!port->interrupt_in_buffer) {
951 dev_err(&interface->dev, "Couldn't allocate interrupt_in_buffer\n");
952 goto probe_error;
953 }
954 usb_fill_int_urb (port->interrupt_in_urb, dev,
955 usb_rcvintpipe (dev,
956 endpoint->bEndpointAddress),
957 port->interrupt_in_buffer, buffer_size,
958 serial->type->read_int_callback, port,
959 endpoint->bInterval);
960 }
961 } else if (num_interrupt_in) {
962 dbg("the device claims to support interrupt in transfers, but read_int_callback is not defined");
963 }
964
965 if (serial->type->write_int_callback) {
966 for (i = 0; i < num_interrupt_out; ++i) {
967 endpoint = interrupt_out_endpoint[i];
968 port = serial->port[i];
969 port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
970 if (!port->interrupt_out_urb) {
971 dev_err(&interface->dev, "No free urbs available\n");
972 goto probe_error;
973 }
974 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
975 port->interrupt_out_size = buffer_size;
976 port->interrupt_out_endpointAddress = endpoint->bEndpointAddress;
977 port->interrupt_out_buffer = kmalloc (buffer_size, GFP_KERNEL);
978 if (!port->interrupt_out_buffer) {
979 dev_err(&interface->dev, "Couldn't allocate interrupt_out_buffer\n");
980 goto probe_error;
981 }
982 usb_fill_int_urb (port->interrupt_out_urb, dev,
983 usb_sndintpipe (dev,
984 endpoint->bEndpointAddress),
985 port->interrupt_out_buffer, buffer_size,
986 serial->type->write_int_callback, port,
987 endpoint->bInterval);
988 }
989 } else if (num_interrupt_out) {
990 dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined");
991 }
992
993 /* if this device type has an attach function, call it */
994 if (type->attach) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700995 if (!try_module_get(type->driver.owner)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 dev_err(&interface->dev, "module get failed, exiting\n");
997 goto probe_error;
998 }
999 retval = type->attach (serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -07001000 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 if (retval < 0)
1002 goto probe_error;
1003 if (retval > 0) {
1004 /* quietly accept this device, but don't bind to a serial port
1005 * as it's about to disappear */
1006 goto exit;
1007 }
1008 }
1009
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001010 if (get_free_serial (serial, num_ports, &minor) == NULL) {
1011 dev_err(&interface->dev, "No more free serial devices\n");
1012 goto probe_error;
1013 }
Oliver Neukumc744f992007-02-26 15:43:00 +01001014 serial->minor = minor;
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001015
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 /* register all of the individual ports with the driver core */
1017 for (i = 0; i < num_ports; ++i) {
1018 port = serial->port[i];
1019 port->dev.parent = &interface->dev;
1020 port->dev.driver = NULL;
1021 port->dev.bus = &usb_serial_bus_type;
1022 port->dev.release = &port_release;
1023
1024 snprintf (&port->dev.bus_id[0], sizeof(port->dev.bus_id), "ttyUSB%d", port->number);
Harvey Harrison441b62c2008-03-03 16:08:34 -08001025 dbg ("%s - registering %s", __func__, port->dev.bus_id);
Greg Kroah-Hartman13f4db92006-08-28 11:43:25 -07001026 retval = device_register(&port->dev);
1027 if (retval)
1028 dev_err(&port->dev, "Error registering port device, "
1029 "continuing\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 }
1031
1032 usb_serial_console_init (debug, minor);
1033
1034exit:
1035 /* success */
1036 usb_set_intfdata (interface, serial);
1037 return 0;
1038
1039probe_error:
1040 for (i = 0; i < num_bulk_in; ++i) {
1041 port = serial->port[i];
1042 if (!port)
1043 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001044 usb_free_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 kfree(port->bulk_in_buffer);
1046 }
1047 for (i = 0; i < num_bulk_out; ++i) {
1048 port = serial->port[i];
1049 if (!port)
1050 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001051 usb_free_urb(port->write_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 kfree(port->bulk_out_buffer);
1053 }
1054 for (i = 0; i < num_interrupt_in; ++i) {
1055 port = serial->port[i];
1056 if (!port)
1057 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001058 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 kfree(port->interrupt_in_buffer);
1060 }
1061 for (i = 0; i < num_interrupt_out; ++i) {
1062 port = serial->port[i];
1063 if (!port)
1064 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001065 usb_free_urb(port->interrupt_out_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 kfree(port->interrupt_out_buffer);
1067 }
1068
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 /* free up any memory that we allocated */
1070 for (i = 0; i < serial->num_port_pointers; ++i)
1071 kfree(serial->port[i]);
1072 kfree (serial);
1073 return -EIO;
1074}
1075
1076void usb_serial_disconnect(struct usb_interface *interface)
1077{
1078 int i;
1079 struct usb_serial *serial = usb_get_intfdata (interface);
1080 struct device *dev = &interface->dev;
1081 struct usb_serial_port *port;
1082
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +02001083 usb_serial_console_disconnect(serial);
Harvey Harrison441b62c2008-03-03 16:08:34 -08001084 dbg ("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001086 mutex_lock(&serial->disc_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 usb_set_intfdata (interface, NULL);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001088 /* must set a flag, to signal subdrivers */
1089 serial->disconnected = 1;
1090 for (i = 0; i < serial->num_ports; ++i) {
1091 port = serial->port[i];
1092 if (port) {
1093 if (port->tty)
1094 tty_hangup(port->tty);
1095 kill_traffic(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 }
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001098 /* let the last holder of this object
1099 * cause it to be cleaned up */
1100 mutex_unlock(&serial->disc_mutex);
1101 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102 dev_info(dev, "device disconnected\n");
1103}
1104
Oliver Neukumec225592007-04-27 20:54:57 +02001105int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
1106{
1107 struct usb_serial *serial = usb_get_intfdata(intf);
1108 struct usb_serial_port *port;
1109 int i, r = 0;
1110
Oliver Neukume31c1882007-07-23 08:58:39 +02001111 for (i = 0; i < serial->num_ports; ++i) {
1112 port = serial->port[i];
1113 if (port)
1114 kill_traffic(port);
Oliver Neukumec225592007-04-27 20:54:57 +02001115 }
1116
1117 if (serial->type->suspend)
Oliver Neukume31c1882007-07-23 08:58:39 +02001118 r = serial->type->suspend(serial, message);
Oliver Neukumec225592007-04-27 20:54:57 +02001119
1120 return r;
1121}
1122EXPORT_SYMBOL(usb_serial_suspend);
1123
1124int usb_serial_resume(struct usb_interface *intf)
1125{
1126 struct usb_serial *serial = usb_get_intfdata(intf);
1127
Sarah Sharp8abaee22007-10-25 10:58:43 -07001128 if (serial->type->resume)
1129 return serial->type->resume(serial);
1130 return 0;
Oliver Neukumec225592007-04-27 20:54:57 +02001131}
1132EXPORT_SYMBOL(usb_serial_resume);
1133
Jeff Dikeb68e31d2006-10-02 02:17:18 -07001134static const struct tty_operations serial_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 .open = serial_open,
1136 .close = serial_close,
1137 .write = serial_write,
1138 .write_room = serial_write_room,
1139 .ioctl = serial_ioctl,
1140 .set_termios = serial_set_termios,
1141 .throttle = serial_throttle,
1142 .unthrottle = serial_unthrottle,
1143 .break_ctl = serial_break,
1144 .chars_in_buffer = serial_chars_in_buffer,
1145 .read_proc = serial_read_proc,
1146 .tiocmget = serial_tiocmget,
1147 .tiocmset = serial_tiocmset,
1148};
1149
1150struct tty_driver *usb_serial_tty_driver;
1151
1152static int __init usb_serial_init(void)
1153{
1154 int i;
1155 int result;
1156
1157 usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS);
1158 if (!usb_serial_tty_driver)
1159 return -ENOMEM;
1160
1161 /* Initialize our global data */
1162 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
1163 serial_table[i] = NULL;
1164 }
1165
1166 result = bus_register(&usb_serial_bus_type);
1167 if (result) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001168 err("%s - registering bus driver failed", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 goto exit_bus;
1170 }
1171
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172 usb_serial_tty_driver->owner = THIS_MODULE;
1173 usb_serial_tty_driver->driver_name = "usbserial";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 usb_serial_tty_driver->name = "ttyUSB";
1175 usb_serial_tty_driver->major = SERIAL_TTY_MAJOR;
1176 usb_serial_tty_driver->minor_start = 0;
1177 usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
1178 usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
Greg Kroah-Hartman331b8312005-06-20 21:15:16 -07001179 usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180 usb_serial_tty_driver->init_termios = tty_std_termios;
1181 usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
Alan Coxa5b6f602008-04-08 17:16:06 +01001182 usb_serial_tty_driver->init_termios.c_ispeed = 9600;
1183 usb_serial_tty_driver->init_termios.c_ospeed = 9600;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 tty_set_operations(usb_serial_tty_driver, &serial_ops);
1185 result = tty_register_driver(usb_serial_tty_driver);
1186 if (result) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001187 err("%s - tty_register_driver failed", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 goto exit_reg_driver;
1189 }
1190
1191 /* register the USB driver */
1192 result = usb_register(&usb_serial_driver);
1193 if (result < 0) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001194 err("%s - usb_register failed", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195 goto exit_tty;
1196 }
1197
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001198 /* register the generic driver, if we should */
1199 result = usb_serial_generic_register(debug);
1200 if (result < 0) {
Harvey Harrison441b62c2008-03-03 16:08:34 -08001201 err("%s - registering generic driver failed", __func__);
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001202 goto exit_generic;
1203 }
1204
Greg Kroah-Hartman17a882f2005-06-20 21:15:16 -07001205 info(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206
1207 return result;
1208
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001209exit_generic:
1210 usb_deregister(&usb_serial_driver);
1211
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212exit_tty:
1213 tty_unregister_driver(usb_serial_tty_driver);
1214
1215exit_reg_driver:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216 bus_unregister(&usb_serial_bus_type);
1217
1218exit_bus:
Harvey Harrison441b62c2008-03-03 16:08:34 -08001219 err ("%s - returning with error %d", __func__, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 put_tty_driver(usb_serial_tty_driver);
1221 return result;
1222}
1223
1224
1225static void __exit usb_serial_exit(void)
1226{
1227 usb_serial_console_exit();
1228
1229 usb_serial_generic_deregister();
1230
1231 usb_deregister(&usb_serial_driver);
1232 tty_unregister_driver(usb_serial_tty_driver);
1233 put_tty_driver(usb_serial_tty_driver);
1234 bus_unregister(&usb_serial_bus_type);
1235}
1236
1237
1238module_init(usb_serial_init);
1239module_exit(usb_serial_exit);
1240
1241#define set_to_generic_if_null(type, function) \
1242 do { \
1243 if (!type->function) { \
1244 type->function = usb_serial_generic_##function; \
1245 dbg("Had to override the " #function \
1246 " usb serial operation with the generic one.");\
1247 } \
1248 } while (0)
1249
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001250static void fixup_generic(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251{
1252 set_to_generic_if_null(device, open);
1253 set_to_generic_if_null(device, write);
1254 set_to_generic_if_null(device, close);
1255 set_to_generic_if_null(device, write_room);
1256 set_to_generic_if_null(device, chars_in_buffer);
1257 set_to_generic_if_null(device, read_bulk_callback);
1258 set_to_generic_if_null(device, write_bulk_callback);
1259 set_to_generic_if_null(device, shutdown);
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -08001260 set_to_generic_if_null(device, resume);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261}
1262
Oliver Neukum4b10f0f2007-01-13 07:31:27 +01001263int usb_serial_register(struct usb_serial_driver *driver) /* must be called with BKL held */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264{
1265 int retval;
1266
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001267 fixup_generic(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001269 if (!driver->description)
1270 driver->description = driver->driver.name;
1271
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272 /* Add this device to our list of devices */
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001273 list_add(&driver->driver_list, &usb_serial_driver_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001275 retval = usb_serial_bus_register(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 if (retval) {
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001277 err("problem %d when registering driver %s", retval, driver->description);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001278 list_del(&driver->driver_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279 }
1280 else
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001281 info("USB Serial support registered for %s", driver->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282
1283 return retval;
1284}
1285
1286
Oliver Neukum4b10f0f2007-01-13 07:31:27 +01001287void usb_serial_deregister(struct usb_serial_driver *device) /* must be called with BKL held */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288{
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001289 info("USB Serial deregistering driver %s", device->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290 list_del(&device->driver_list);
1291 usb_serial_bus_deregister(device);
1292}
1293
1294
1295
1296/* If the usb-serial core is built into the core, the usb-serial drivers
1297 need these symbols to load properly as modules. */
1298EXPORT_SYMBOL_GPL(usb_serial_register);
1299EXPORT_SYMBOL_GPL(usb_serial_deregister);
1300EXPORT_SYMBOL_GPL(usb_serial_probe);
1301EXPORT_SYMBOL_GPL(usb_serial_disconnect);
1302EXPORT_SYMBOL_GPL(usb_serial_port_softint);
1303
1304
1305/* Module information */
1306MODULE_AUTHOR( DRIVER_AUTHOR );
1307MODULE_DESCRIPTION( DRIVER_DESC );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308MODULE_LICENSE("GPL");
1309
1310module_param(debug, bool, S_IRUGO | S_IWUSR);
1311MODULE_PARM_DESC(debug, "Debug enabled or not");