blob: e3e3728e16e320f300b818d062fb93b3ee28bf58 [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 Neukum34ef50e2007-01-13 07:29:26 +010063static spinlock_t 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
70 spin_lock(&table_lock);
71 serial = serial_table[index];
Linus Torvalds1da177e2005-04-16 15:20:36 -070072
73 if (serial)
74 kref_get(&serial->kref);
Oliver Neukum34ef50e2007-01-13 07:29:26 +010075 spin_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
84 dbg("%s %d", __FUNCTION__, num_ports);
85
86 *minor = 0;
Oliver Neukum34ef50e2007-01-13 07:29:26 +010087 spin_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;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104 dbg("%s - minor base = %d", __FUNCTION__, *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 Neukum34ef50e2007-01-13 07:29:26 +0100109 spin_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110 return serial;
111 }
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100112 spin_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
120 dbg("%s", __FUNCTION__);
121
122 if (serial == NULL)
123 return;
124
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100125 spin_lock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126 for (i = 0; i < serial->num_ports; ++i) {
127 serial_table[serial->minor + i] = NULL;
128 }
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100129 spin_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130}
131
132static void destroy_serial(struct kref *kref)
133{
134 struct usb_serial *serial;
135 struct usb_serial_port *port;
136 int i;
137
138 serial = to_usb_serial(kref);
139
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -0700140 dbg("%s - %s", __FUNCTION__, serial->type->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141
Jim Radford521b85a2007-03-13 08:30:50 -0700142 serial->type->shutdown(serial);
143
144 /* return the minor range that this device had */
145 return_serial(serial);
146
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147 for (i = 0; i < serial->num_ports; ++i)
148 serial->port[i]->open_count = 0;
149
150 /* the ports are cleaned up and released in port_release() */
151 for (i = 0; i < serial->num_ports; ++i)
152 if (serial->port[i]->dev.parent != NULL) {
153 device_unregister(&serial->port[i]->dev);
154 serial->port[i] = NULL;
155 }
156
157 /* If this is a "fake" port, we have to clean it up here, as it will
158 * not get cleaned up in port_release() as it was never registered with
159 * the driver core */
160 if (serial->num_ports < serial->num_port_pointers) {
161 for (i = serial->num_ports; i < serial->num_port_pointers; ++i) {
162 port = serial->port[i];
163 if (!port)
164 continue;
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700165 port_free(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 }
167 }
168
169 usb_put_dev(serial->dev);
170
171 /* free up any memory that we allocated */
172 kfree (serial);
173}
174
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200175void usb_serial_put(struct usb_serial *serial)
176{
177 kref_put(&serial->kref, destroy_serial);
178}
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
190 dbg("%s", __FUNCTION__);
191
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
228 /* only call the device specific open if this
229 * is the first time the port is opened */
230 retval = serial->type->open(port, filp);
231 if (retval)
232 goto bailout_module_put;
233 }
234
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300235 mutex_unlock(&port->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236 return 0;
237
238bailout_module_put:
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700239 module_put(serial->type->driver.owner);
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300240bailout_mutex_unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 port->open_count = 0;
Frank Gevaertsb059c812006-06-14 15:52:05 +0200242 tty->driver_data = NULL;
243 port->tty = NULL;
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300244 mutex_unlock(&port->mutex);
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300245bailout_kref_put:
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200246 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 return retval;
248}
249
250static void serial_close(struct tty_struct *tty, struct file * filp)
251{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200252 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253
254 if (!port)
255 return;
256
257 dbg("%s - port %d", __FUNCTION__, port->number);
258
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300259 mutex_lock(&port->mutex);
Luiz Fernando Capitulino8a4613f2005-11-28 19:16:07 -0200260
Greg Kroah-Hartman91c0bce2006-03-06 13:25:52 -0800261 if (port->open_count == 0) {
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300262 mutex_unlock(&port->mutex);
Greg Kroah-Hartman91c0bce2006-03-06 13:25:52 -0800263 return;
264 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265
266 --port->open_count;
267 if (port->open_count == 0) {
268 /* only call the device specific close if this
269 * port is being closed by the last owner */
270 port->serial->type->close(port, filp);
271
272 if (port->tty) {
273 if (port->tty->driver_data)
274 port->tty->driver_data = NULL;
275 port->tty = NULL;
276 }
277
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700278 module_put(port->serial->type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 }
280
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300281 mutex_unlock(&port->mutex);
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200282 usb_serial_put(port->serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283}
284
285static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count)
286{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200287 struct usb_serial_port *port = tty->driver_data;
Oliver Neukum3ff4fd92007-01-13 07:32:27 +0100288 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200290 if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED)
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200291 goto exit;
292
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count);
294
295 if (!port->open_count) {
Oliver Neukum3ff4fd92007-01-13 07:32:27 +0100296 retval = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 dbg("%s - port not opened", __FUNCTION__);
298 goto exit;
299 }
300
301 /* pass on to the driver specific version of this function */
302 retval = port->serial->type->write(port, buf, count);
303
304exit:
305 return retval;
306}
307
308static int serial_write_room (struct tty_struct *tty)
309{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200310 struct usb_serial_port *port = tty->driver_data;
Luiz Fernando N. Capitulinodb54a532006-06-12 22:46:20 -0300311 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200313 if (!port)
314 goto exit;
315
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316 dbg("%s - port %d", __FUNCTION__, port->number);
317
318 if (!port->open_count) {
319 dbg("%s - port not open", __FUNCTION__);
320 goto exit;
321 }
322
323 /* pass on to the driver specific version of this function */
324 retval = port->serial->type->write_room(port);
325
326exit:
327 return retval;
328}
329
330static int serial_chars_in_buffer (struct tty_struct *tty)
331{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200332 struct usb_serial_port *port = tty->driver_data;
Luiz Fernando N. Capitulinodb54a532006-06-12 22:46:20 -0300333 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200335 if (!port)
336 goto exit;
337
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 dbg("%s = port %d", __FUNCTION__, port->number);
339
340 if (!port->open_count) {
341 dbg("%s - port not open", __FUNCTION__);
342 goto exit;
343 }
344
345 /* pass on to the driver specific version of this function */
346 retval = port->serial->type->chars_in_buffer(port);
347
348exit:
349 return retval;
350}
351
352static void serial_throttle (struct tty_struct * tty)
353{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200354 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200356 if (!port)
357 return;
358
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 dbg("%s - port %d", __FUNCTION__, port->number);
360
361 if (!port->open_count) {
362 dbg ("%s - port not open", __FUNCTION__);
363 return;
364 }
365
366 /* pass on to the driver specific version of this function */
367 if (port->serial->type->throttle)
368 port->serial->type->throttle(port);
369}
370
371static void serial_unthrottle (struct tty_struct * tty)
372{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200373 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200375 if (!port)
376 return;
377
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 dbg("%s - port %d", __FUNCTION__, port->number);
379
380 if (!port->open_count) {
381 dbg("%s - port not open", __FUNCTION__);
382 return;
383 }
384
385 /* pass on to the driver specific version of this function */
386 if (port->serial->type->unthrottle)
387 port->serial->type->unthrottle(port);
388}
389
390static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
391{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200392 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 int retval = -ENODEV;
394
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200395 if (!port)
396 goto exit;
397
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
399
400 if (!port->open_count) {
401 dbg ("%s - port not open", __FUNCTION__);
402 goto exit;
403 }
404
405 /* pass on to the driver specific version of this function if it is available */
406 if (port->serial->type->ioctl)
407 retval = port->serial->type->ioctl(port, file, cmd, arg);
408 else
409 retval = -ENOIOCTLCMD;
410
411exit:
412 return retval;
413}
414
Alan Cox606d0992006-12-08 02:38:45 -0800415static void serial_set_termios (struct tty_struct *tty, struct ktermios * old)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200417 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200419 if (!port)
420 return;
421
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 dbg("%s - port %d", __FUNCTION__, port->number);
423
424 if (!port->open_count) {
425 dbg("%s - port not open", __FUNCTION__);
426 return;
427 }
428
429 /* pass on to the driver specific version of this function if it is available */
430 if (port->serial->type->set_termios)
431 port->serial->type->set_termios(port, old);
432}
433
434static void serial_break (struct tty_struct *tty, int break_state)
435{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200436 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200438 if (!port)
439 return;
440
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 dbg("%s - port %d", __FUNCTION__, port->number);
442
443 if (!port->open_count) {
444 dbg("%s - port not open", __FUNCTION__);
445 return;
446 }
447
448 /* pass on to the driver specific version of this function if it is available */
449 if (port->serial->type->break_ctl)
450 port->serial->type->break_ctl(port, break_state);
451}
452
453static int serial_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data)
454{
455 struct usb_serial *serial;
456 int length = 0;
457 int i;
458 off_t begin = 0;
459 char tmp[40];
460
461 dbg("%s", __FUNCTION__);
Greg Kroah-Hartman17a882f2005-06-20 21:15:16 -0700462 length += sprintf (page, "usbserinfo:1.0 driver:2.0\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463 for (i = 0; i < SERIAL_TTY_MINORS && length < PAGE_SIZE; ++i) {
464 serial = usb_serial_get_by_index(i);
465 if (serial == NULL)
466 continue;
467
468 length += sprintf (page+length, "%d:", i);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700469 if (serial->type->driver.owner)
470 length += sprintf (page+length, " module:%s", module_name(serial->type->driver.owner));
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -0700471 length += sprintf (page+length, " name:\"%s\"", serial->type->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 length += sprintf (page+length, " vendor:%04x product:%04x",
473 le16_to_cpu(serial->dev->descriptor.idVendor),
474 le16_to_cpu(serial->dev->descriptor.idProduct));
475 length += sprintf (page+length, " num_ports:%d", serial->num_ports);
476 length += sprintf (page+length, " port:%d", i - serial->minor + 1);
477
478 usb_make_path(serial->dev, tmp, sizeof(tmp));
479 length += sprintf (page+length, " path:%s", tmp);
480
481 length += sprintf (page+length, "\n");
Matthias Urlichs59925832006-09-11 12:35:20 +0200482 if ((length + begin) > (off + count)) {
483 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 goto done;
Matthias Urlichs59925832006-09-11 12:35:20 +0200485 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 if ((length + begin) < off) {
487 begin += length;
488 length = 0;
489 }
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200490 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491 }
492 *eof = 1;
493done:
494 if (off >= (length + begin))
495 return 0;
496 *start = page + (off-begin);
497 return ((count < begin+length-off) ? count : begin+length-off);
498}
499
500static int serial_tiocmget (struct tty_struct *tty, struct file *file)
501{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200502 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200504 if (!port)
Luiz Fernando N. Capitulinodb54a532006-06-12 22:46:20 -0300505 return -ENODEV;
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200506
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 dbg("%s - port %d", __FUNCTION__, port->number);
508
509 if (!port->open_count) {
510 dbg("%s - port not open", __FUNCTION__);
Luiz Fernando N. Capitulinodb54a532006-06-12 22:46:20 -0300511 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512 }
513
514 if (port->serial->type->tiocmget)
515 return port->serial->type->tiocmget(port, file);
516
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 return -EINVAL;
518}
519
520static int serial_tiocmset (struct tty_struct *tty, struct file *file,
521 unsigned int set, unsigned int clear)
522{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200523 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200525 if (!port)
Luiz Fernando N. Capitulinodb54a532006-06-12 22:46:20 -0300526 return -ENODEV;
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200527
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 dbg("%s - port %d", __FUNCTION__, port->number);
529
530 if (!port->open_count) {
531 dbg("%s - port not open", __FUNCTION__);
Luiz Fernando N. Capitulinodb54a532006-06-12 22:46:20 -0300532 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533 }
534
535 if (port->serial->type->tiocmset)
536 return port->serial->type->tiocmset(port, file, set, clear);
537
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 return -EINVAL;
539}
540
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700541/*
542 * We would be calling tty_wakeup here, but unfortunately some line
543 * disciplines have an annoying habit of calling tty->write from
544 * the write wakeup callback (e.g. n_hdlc.c).
545 */
546void usb_serial_port_softint(struct usb_serial_port *port)
547{
548 schedule_work(&port->work);
549}
550
David Howellsc4028952006-11-22 14:57:56 +0000551static void usb_serial_port_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552{
David Howellsc4028952006-11-22 14:57:56 +0000553 struct usb_serial_port *port =
554 container_of(work, struct usb_serial_port, work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 struct tty_struct *tty;
556
557 dbg("%s - port %d", __FUNCTION__, port->number);
558
559 if (!port)
560 return;
561
562 tty = port->tty;
563 if (!tty)
564 return;
565
566 tty_wakeup(tty);
567}
568
569static void port_release(struct device *dev)
570{
571 struct usb_serial_port *port = to_usb_serial_port(dev);
572
573 dbg ("%s - %s", __FUNCTION__, dev->bus_id);
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700574 port_free(port);
575}
576
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100577static void kill_traffic(struct usb_serial_port *port)
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700578{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 usb_kill_urb(port->write_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 usb_kill_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582 usb_kill_urb(port->interrupt_out_urb);
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100583}
584
585static void port_free(struct usb_serial_port *port)
586{
587 kill_traffic(port);
588 usb_free_urb(port->read_urb);
589 usb_free_urb(port->write_urb);
590 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 usb_free_urb(port->interrupt_out_urb);
592 kfree(port->bulk_in_buffer);
593 kfree(port->bulk_out_buffer);
594 kfree(port->interrupt_in_buffer);
595 kfree(port->interrupt_out_buffer);
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700596 flush_scheduled_work(); /* port->work */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 kfree(port);
598}
599
600static struct usb_serial * create_serial (struct usb_device *dev,
601 struct usb_interface *interface,
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700602 struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603{
604 struct usb_serial *serial;
605
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100606 serial = kzalloc(sizeof(*serial), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 if (!serial) {
608 dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);
609 return NULL;
610 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 serial->dev = usb_get_dev(dev);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700612 serial->type = driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 serial->interface = interface;
614 kref_init(&serial->kref);
615
616 return serial;
617}
618
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100619static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf,
620 struct usb_serial_driver *drv)
621{
622 struct usb_dynid *dynid;
623
624 spin_lock(&drv->dynids.lock);
625 list_for_each_entry(dynid, &drv->dynids.list, node) {
626 if (usb_match_one_id(intf, &dynid->id)) {
627 spin_unlock(&drv->dynids.lock);
628 return &dynid->id;
629 }
630 }
631 spin_unlock(&drv->dynids.lock);
632 return NULL;
633}
634
635static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv,
636 struct usb_interface *intf)
637{
638 const struct usb_device_id *id;
639
640 id = usb_match_id(intf, drv->id_table);
641 if (id) {
642 dbg("static descriptor matches");
643 goto exit;
644 }
645 id = match_dynamic_id(intf, drv);
646 if (id)
647 dbg("dynamic descriptor matches");
648exit:
649 return id;
650}
651
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700652static struct usb_serial_driver *search_serial_device(struct usb_interface *iface)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653{
654 struct list_head *p;
655 const struct usb_device_id *id;
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700656 struct usb_serial_driver *t;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657
Adrian Bunk93b1fae2006-01-10 00:13:33 +0100658 /* Check if the usb id matches a known device */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 list_for_each(p, &usb_serial_driver_list) {
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700660 t = list_entry(p, struct usb_serial_driver, driver_list);
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100661 id = get_iface_id(t, iface);
662 if (id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 return t;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 }
665
666 return NULL;
667}
668
669int usb_serial_probe(struct usb_interface *interface,
670 const struct usb_device_id *id)
671{
672 struct usb_device *dev = interface_to_usbdev (interface);
673 struct usb_serial *serial = NULL;
674 struct usb_serial_port *port;
675 struct usb_host_interface *iface_desc;
676 struct usb_endpoint_descriptor *endpoint;
677 struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS];
678 struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS];
679 struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];
680 struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700681 struct usb_serial_driver *type = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 int retval;
683 int minor;
684 int buffer_size;
685 int i;
686 int num_interrupt_in = 0;
687 int num_interrupt_out = 0;
688 int num_bulk_in = 0;
689 int num_bulk_out = 0;
690 int num_ports = 0;
691 int max_endpoints;
692
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100693 lock_kernel(); /* guard against unloading a serial driver module */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 type = search_serial_device(interface);
695 if (!type) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100696 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 dbg("none matched");
698 return -ENODEV;
699 }
700
701 serial = create_serial (dev, interface, type);
702 if (!serial) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100703 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704 dev_err(&interface->dev, "%s - out of memory\n", __FUNCTION__);
705 return -ENOMEM;
706 }
707
708 /* if this device type has a probe function, call it */
709 if (type->probe) {
710 const struct usb_device_id *id;
711
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700712 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100713 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714 dev_err(&interface->dev, "module get failed, exiting\n");
715 kfree (serial);
716 return -EIO;
717 }
718
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100719 id = get_iface_id(type, interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720 retval = type->probe(serial, id);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700721 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722
723 if (retval) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100724 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 dbg ("sub driver rejected device");
726 kfree (serial);
727 return retval;
728 }
729 }
730
731 /* descriptor matches, let's find the endpoints needed */
732 /* check out the endpoints */
733 iface_desc = interface->cur_altsetting;
734 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
735 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700736
737 if (usb_endpoint_is_bulk_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738 /* we found a bulk in endpoint */
739 dbg("found bulk in on endpoint %d", i);
740 bulk_in_endpoint[num_bulk_in] = endpoint;
741 ++num_bulk_in;
742 }
743
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700744 if (usb_endpoint_is_bulk_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 /* we found a bulk out endpoint */
746 dbg("found bulk out on endpoint %d", i);
747 bulk_out_endpoint[num_bulk_out] = endpoint;
748 ++num_bulk_out;
749 }
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700750
751 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 /* we found a interrupt in endpoint */
753 dbg("found interrupt in on endpoint %d", i);
754 interrupt_in_endpoint[num_interrupt_in] = endpoint;
755 ++num_interrupt_in;
756 }
757
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700758 if (usb_endpoint_is_int_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 /* we found an interrupt out endpoint */
760 dbg("found interrupt out on endpoint %d", i);
761 interrupt_out_endpoint[num_interrupt_out] = endpoint;
762 ++num_interrupt_out;
763 }
764 }
765
766#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
767 /* BEGIN HORRIBLE HACK FOR PL2303 */
768 /* this is needed due to the looney way its endpoints are set up */
769 if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&
770 (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||
771 ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) &&
Johannes Steingraeber8fd80132006-09-16 16:17:34 +0200772 (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) ||
773 ((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) &&
774 (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775 if (interface != dev->actconfig->interface[0]) {
776 /* check out the endpoints of the other interface*/
777 iface_desc = dev->actconfig->interface[0]->cur_altsetting;
778 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
779 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700780 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 /* we found a interrupt in endpoint */
782 dbg("found interrupt in for Prolific device on separate interface");
783 interrupt_in_endpoint[num_interrupt_in] = endpoint;
784 ++num_interrupt_in;
785 }
786 }
787 }
788
789 /* Now make sure the PL-2303 is configured correctly.
790 * If not, give up now and hope this hack will work
791 * properly during a later invocation of usb_serial_probe
792 */
793 if (num_bulk_in == 0 || num_bulk_out == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100794 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
796 kfree (serial);
797 return -ENODEV;
798 }
799 }
800 /* END HORRIBLE HACK FOR PL2303 */
801#endif
802
803 /* found all that we need */
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -0700804 dev_info(&interface->dev, "%s converter detected\n", type->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805
806#ifdef CONFIG_USB_SERIAL_GENERIC
807 if (type == &usb_serial_generic_device) {
808 num_ports = num_bulk_out;
809 if (num_ports == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100810 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 dev_err(&interface->dev, "Generic device with no bulk out, not allowed.\n");
812 kfree (serial);
813 return -EIO;
814 }
815 }
816#endif
817 if (!num_ports) {
818 /* if this device type has a calc_num_ports function, call it */
819 if (type->calc_num_ports) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700820 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100821 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 dev_err(&interface->dev, "module get failed, exiting\n");
823 kfree (serial);
824 return -EIO;
825 }
826 num_ports = type->calc_num_ports (serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700827 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828 }
829 if (!num_ports)
830 num_ports = type->num_ports;
831 }
832
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 serial->num_ports = num_ports;
834 serial->num_bulk_in = num_bulk_in;
835 serial->num_bulk_out = num_bulk_out;
836 serial->num_interrupt_in = num_interrupt_in;
837 serial->num_interrupt_out = num_interrupt_out;
838
839 /* create our ports, we need as many as the max endpoints */
840 /* we don't use num_ports here cauz some devices have more endpoint pairs than ports */
841 max_endpoints = max(num_bulk_in, num_bulk_out);
842 max_endpoints = max(max_endpoints, num_interrupt_in);
843 max_endpoints = max(max_endpoints, num_interrupt_out);
844 max_endpoints = max(max_endpoints, (int)serial->num_ports);
845 serial->num_port_pointers = max_endpoints;
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100846 unlock_kernel();
847
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 dbg("%s - setting up %d port structures for this device", __FUNCTION__, max_endpoints);
849 for (i = 0; i < max_endpoints; ++i) {
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100850 port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 if (!port)
852 goto probe_error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 port->serial = serial;
Greg Kroah-Hartman507ca9b2005-04-23 12:49:16 -0700854 spin_lock_init(&port->lock);
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300855 mutex_init(&port->mutex);
David Howellsc4028952006-11-22 14:57:56 +0000856 INIT_WORK(&port->work, usb_serial_port_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857 serial->port[i] = port;
858 }
859
860 /* set up the endpoint information */
861 for (i = 0; i < num_bulk_in; ++i) {
862 endpoint = bulk_in_endpoint[i];
863 port = serial->port[i];
864 port->read_urb = usb_alloc_urb (0, GFP_KERNEL);
865 if (!port->read_urb) {
866 dev_err(&interface->dev, "No free urbs available\n");
867 goto probe_error;
868 }
869 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
870 port->bulk_in_size = buffer_size;
871 port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
872 port->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
873 if (!port->bulk_in_buffer) {
874 dev_err(&interface->dev, "Couldn't allocate bulk_in_buffer\n");
875 goto probe_error;
876 }
877 usb_fill_bulk_urb (port->read_urb, dev,
878 usb_rcvbulkpipe (dev,
879 endpoint->bEndpointAddress),
880 port->bulk_in_buffer, buffer_size,
881 serial->type->read_bulk_callback,
882 port);
883 }
884
885 for (i = 0; i < num_bulk_out; ++i) {
886 endpoint = bulk_out_endpoint[i];
887 port = serial->port[i];
888 port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
889 if (!port->write_urb) {
890 dev_err(&interface->dev, "No free urbs available\n");
891 goto probe_error;
892 }
893 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
894 port->bulk_out_size = buffer_size;
895 port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
896 port->bulk_out_buffer = kmalloc (buffer_size, GFP_KERNEL);
897 if (!port->bulk_out_buffer) {
898 dev_err(&interface->dev, "Couldn't allocate bulk_out_buffer\n");
899 goto probe_error;
900 }
901 usb_fill_bulk_urb (port->write_urb, dev,
902 usb_sndbulkpipe (dev,
903 endpoint->bEndpointAddress),
904 port->bulk_out_buffer, buffer_size,
905 serial->type->write_bulk_callback,
906 port);
907 }
908
909 if (serial->type->read_int_callback) {
910 for (i = 0; i < num_interrupt_in; ++i) {
911 endpoint = interrupt_in_endpoint[i];
912 port = serial->port[i];
913 port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
914 if (!port->interrupt_in_urb) {
915 dev_err(&interface->dev, "No free urbs available\n");
916 goto probe_error;
917 }
918 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
919 port->interrupt_in_endpointAddress = endpoint->bEndpointAddress;
920 port->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
921 if (!port->interrupt_in_buffer) {
922 dev_err(&interface->dev, "Couldn't allocate interrupt_in_buffer\n");
923 goto probe_error;
924 }
925 usb_fill_int_urb (port->interrupt_in_urb, dev,
926 usb_rcvintpipe (dev,
927 endpoint->bEndpointAddress),
928 port->interrupt_in_buffer, buffer_size,
929 serial->type->read_int_callback, port,
930 endpoint->bInterval);
931 }
932 } else if (num_interrupt_in) {
933 dbg("the device claims to support interrupt in transfers, but read_int_callback is not defined");
934 }
935
936 if (serial->type->write_int_callback) {
937 for (i = 0; i < num_interrupt_out; ++i) {
938 endpoint = interrupt_out_endpoint[i];
939 port = serial->port[i];
940 port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
941 if (!port->interrupt_out_urb) {
942 dev_err(&interface->dev, "No free urbs available\n");
943 goto probe_error;
944 }
945 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
946 port->interrupt_out_size = buffer_size;
947 port->interrupt_out_endpointAddress = endpoint->bEndpointAddress;
948 port->interrupt_out_buffer = kmalloc (buffer_size, GFP_KERNEL);
949 if (!port->interrupt_out_buffer) {
950 dev_err(&interface->dev, "Couldn't allocate interrupt_out_buffer\n");
951 goto probe_error;
952 }
953 usb_fill_int_urb (port->interrupt_out_urb, dev,
954 usb_sndintpipe (dev,
955 endpoint->bEndpointAddress),
956 port->interrupt_out_buffer, buffer_size,
957 serial->type->write_int_callback, port,
958 endpoint->bInterval);
959 }
960 } else if (num_interrupt_out) {
961 dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined");
962 }
963
964 /* if this device type has an attach function, call it */
965 if (type->attach) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700966 if (!try_module_get(type->driver.owner)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 dev_err(&interface->dev, "module get failed, exiting\n");
968 goto probe_error;
969 }
970 retval = type->attach (serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700971 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 if (retval < 0)
973 goto probe_error;
974 if (retval > 0) {
975 /* quietly accept this device, but don't bind to a serial port
976 * as it's about to disappear */
977 goto exit;
978 }
979 }
980
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100981 if (get_free_serial (serial, num_ports, &minor) == NULL) {
982 dev_err(&interface->dev, "No more free serial devices\n");
983 goto probe_error;
984 }
Oliver Neukumc744f992007-02-26 15:43:00 +0100985 serial->minor = minor;
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100986
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 /* register all of the individual ports with the driver core */
988 for (i = 0; i < num_ports; ++i) {
989 port = serial->port[i];
990 port->dev.parent = &interface->dev;
991 port->dev.driver = NULL;
992 port->dev.bus = &usb_serial_bus_type;
993 port->dev.release = &port_release;
994
995 snprintf (&port->dev.bus_id[0], sizeof(port->dev.bus_id), "ttyUSB%d", port->number);
996 dbg ("%s - registering %s", __FUNCTION__, port->dev.bus_id);
Greg Kroah-Hartman13f4db92006-08-28 11:43:25 -0700997 retval = device_register(&port->dev);
998 if (retval)
999 dev_err(&port->dev, "Error registering port device, "
1000 "continuing\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 }
1002
1003 usb_serial_console_init (debug, minor);
1004
1005exit:
1006 /* success */
1007 usb_set_intfdata (interface, serial);
1008 return 0;
1009
1010probe_error:
1011 for (i = 0; i < num_bulk_in; ++i) {
1012 port = serial->port[i];
1013 if (!port)
1014 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001015 usb_free_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 kfree(port->bulk_in_buffer);
1017 }
1018 for (i = 0; i < num_bulk_out; ++i) {
1019 port = serial->port[i];
1020 if (!port)
1021 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001022 usb_free_urb(port->write_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 kfree(port->bulk_out_buffer);
1024 }
1025 for (i = 0; i < num_interrupt_in; ++i) {
1026 port = serial->port[i];
1027 if (!port)
1028 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001029 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 kfree(port->interrupt_in_buffer);
1031 }
1032 for (i = 0; i < num_interrupt_out; ++i) {
1033 port = serial->port[i];
1034 if (!port)
1035 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001036 usb_free_urb(port->interrupt_out_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 kfree(port->interrupt_out_buffer);
1038 }
1039
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 /* free up any memory that we allocated */
1041 for (i = 0; i < serial->num_port_pointers; ++i)
1042 kfree(serial->port[i]);
1043 kfree (serial);
1044 return -EIO;
1045}
1046
1047void usb_serial_disconnect(struct usb_interface *interface)
1048{
1049 int i;
1050 struct usb_serial *serial = usb_get_intfdata (interface);
1051 struct device *dev = &interface->dev;
1052 struct usb_serial_port *port;
1053
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +02001054 usb_serial_console_disconnect(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 dbg ("%s", __FUNCTION__);
1056
1057 usb_set_intfdata (interface, NULL);
1058 if (serial) {
1059 for (i = 0; i < serial->num_ports; ++i) {
1060 port = serial->port[i];
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001061 if (port) {
1062 if (port->tty)
1063 tty_hangup(port->tty);
1064 kill_traffic(port);
1065 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 }
1067 /* let the last holder of this object
1068 * cause it to be cleaned up */
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +02001069 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 }
1071 dev_info(dev, "device disconnected\n");
1072}
1073
Oliver Neukumec225592007-04-27 20:54:57 +02001074int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
1075{
1076 struct usb_serial *serial = usb_get_intfdata(intf);
1077 struct usb_serial_port *port;
1078 int i, r = 0;
1079
1080 if (serial) {
1081 for (i = 0; i < serial->num_ports; ++i) {
1082 port = serial->port[i];
1083 if (port)
1084 kill_traffic(port);
1085 }
1086 }
1087
1088 if (serial->type->suspend)
1089 serial->type->suspend(serial, message);
1090
1091 return r;
1092}
1093EXPORT_SYMBOL(usb_serial_suspend);
1094
1095int usb_serial_resume(struct usb_interface *intf)
1096{
1097 struct usb_serial *serial = usb_get_intfdata(intf);
1098
1099 return serial->type->resume(serial);
1100}
1101EXPORT_SYMBOL(usb_serial_resume);
1102
Jeff Dikeb68e31d2006-10-02 02:17:18 -07001103static const struct tty_operations serial_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 .open = serial_open,
1105 .close = serial_close,
1106 .write = serial_write,
1107 .write_room = serial_write_room,
1108 .ioctl = serial_ioctl,
1109 .set_termios = serial_set_termios,
1110 .throttle = serial_throttle,
1111 .unthrottle = serial_unthrottle,
1112 .break_ctl = serial_break,
1113 .chars_in_buffer = serial_chars_in_buffer,
1114 .read_proc = serial_read_proc,
1115 .tiocmget = serial_tiocmget,
1116 .tiocmset = serial_tiocmset,
1117};
1118
1119struct tty_driver *usb_serial_tty_driver;
1120
1121static int __init usb_serial_init(void)
1122{
1123 int i;
1124 int result;
1125
1126 usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS);
1127 if (!usb_serial_tty_driver)
1128 return -ENOMEM;
1129
1130 /* Initialize our global data */
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001131 spin_lock_init(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
1133 serial_table[i] = NULL;
1134 }
1135
1136 result = bus_register(&usb_serial_bus_type);
1137 if (result) {
1138 err("%s - registering bus driver failed", __FUNCTION__);
1139 goto exit_bus;
1140 }
1141
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142 usb_serial_tty_driver->owner = THIS_MODULE;
1143 usb_serial_tty_driver->driver_name = "usbserial";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 usb_serial_tty_driver->name = "ttyUSB";
1145 usb_serial_tty_driver->major = SERIAL_TTY_MAJOR;
1146 usb_serial_tty_driver->minor_start = 0;
1147 usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
1148 usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
Greg Kroah-Hartman331b8312005-06-20 21:15:16 -07001149 usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 usb_serial_tty_driver->init_termios = tty_std_termios;
1151 usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
1152 tty_set_operations(usb_serial_tty_driver, &serial_ops);
1153 result = tty_register_driver(usb_serial_tty_driver);
1154 if (result) {
1155 err("%s - tty_register_driver failed", __FUNCTION__);
1156 goto exit_reg_driver;
1157 }
1158
1159 /* register the USB driver */
1160 result = usb_register(&usb_serial_driver);
1161 if (result < 0) {
1162 err("%s - usb_register failed", __FUNCTION__);
1163 goto exit_tty;
1164 }
1165
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001166 /* register the generic driver, if we should */
1167 result = usb_serial_generic_register(debug);
1168 if (result < 0) {
1169 err("%s - registering generic driver failed", __FUNCTION__);
1170 goto exit_generic;
1171 }
1172
Greg Kroah-Hartman17a882f2005-06-20 21:15:16 -07001173 info(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174
1175 return result;
1176
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001177exit_generic:
1178 usb_deregister(&usb_serial_driver);
1179
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180exit_tty:
1181 tty_unregister_driver(usb_serial_tty_driver);
1182
1183exit_reg_driver:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 bus_unregister(&usb_serial_bus_type);
1185
1186exit_bus:
1187 err ("%s - returning with error %d", __FUNCTION__, result);
1188 put_tty_driver(usb_serial_tty_driver);
1189 return result;
1190}
1191
1192
1193static void __exit usb_serial_exit(void)
1194{
1195 usb_serial_console_exit();
1196
1197 usb_serial_generic_deregister();
1198
1199 usb_deregister(&usb_serial_driver);
1200 tty_unregister_driver(usb_serial_tty_driver);
1201 put_tty_driver(usb_serial_tty_driver);
1202 bus_unregister(&usb_serial_bus_type);
1203}
1204
1205
1206module_init(usb_serial_init);
1207module_exit(usb_serial_exit);
1208
1209#define set_to_generic_if_null(type, function) \
1210 do { \
1211 if (!type->function) { \
1212 type->function = usb_serial_generic_##function; \
1213 dbg("Had to override the " #function \
1214 " usb serial operation with the generic one.");\
1215 } \
1216 } while (0)
1217
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001218static void fixup_generic(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219{
1220 set_to_generic_if_null(device, open);
1221 set_to_generic_if_null(device, write);
1222 set_to_generic_if_null(device, close);
1223 set_to_generic_if_null(device, write_room);
1224 set_to_generic_if_null(device, chars_in_buffer);
1225 set_to_generic_if_null(device, read_bulk_callback);
1226 set_to_generic_if_null(device, write_bulk_callback);
1227 set_to_generic_if_null(device, shutdown);
1228}
1229
Oliver Neukum4b10f0f2007-01-13 07:31:27 +01001230int usb_serial_register(struct usb_serial_driver *driver) /* must be called with BKL held */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231{
1232 int retval;
1233
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001234 fixup_generic(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001236 if (!driver->description)
1237 driver->description = driver->driver.name;
1238
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239 /* Add this device to our list of devices */
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001240 list_add(&driver->driver_list, &usb_serial_driver_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001242 retval = usb_serial_bus_register(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243 if (retval) {
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001244 err("problem %d when registering driver %s", retval, driver->description);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001245 list_del(&driver->driver_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246 }
1247 else
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001248 info("USB Serial support registered for %s", driver->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249
1250 return retval;
1251}
1252
1253
Oliver Neukum4b10f0f2007-01-13 07:31:27 +01001254void usb_serial_deregister(struct usb_serial_driver *device) /* must be called with BKL held */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255{
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001256 info("USB Serial deregistering driver %s", device->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257 list_del(&device->driver_list);
1258 usb_serial_bus_deregister(device);
1259}
1260
1261
1262
1263/* If the usb-serial core is built into the core, the usb-serial drivers
1264 need these symbols to load properly as modules. */
1265EXPORT_SYMBOL_GPL(usb_serial_register);
1266EXPORT_SYMBOL_GPL(usb_serial_deregister);
1267EXPORT_SYMBOL_GPL(usb_serial_probe);
1268EXPORT_SYMBOL_GPL(usb_serial_disconnect);
1269EXPORT_SYMBOL_GPL(usb_serial_port_softint);
1270
1271
1272/* Module information */
1273MODULE_AUTHOR( DRIVER_AUTHOR );
1274MODULE_DESCRIPTION( DRIVER_DESC );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275MODULE_LICENSE("GPL");
1276
1277module_param(debug, bool, S_IRUGO | S_IWUSR);
1278MODULE_PARM_DESC(debug, "Debug enabled or not");