blob: 8511352251f33ea3f551438913b9a778bf0158db [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>
31#include <linux/smp_lock.h>
32#include <asm/uaccess.h>
33#include <linux/usb.h>
Greg Kroah-Hartmana9698882006-07-11 21:22:58 -070034#include <linux/usb/serial.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include "pl2303.h"
36
37/*
38 * Version Information
39 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070040#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/"
41#define DRIVER_DESC "USB Serial Driver core"
42
Pete Zaitcev34f8e762006-06-21 15:00:45 -070043static void port_free(struct usb_serial_port *port);
44
Linus Torvalds1da177e2005-04-16 15:20:36 -070045/* Driver structure we register with the USB core */
46static struct usb_driver usb_serial_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070047 .name = "usbserial",
48 .probe = usb_serial_probe,
49 .disconnect = usb_serial_disconnect,
Greg Kroah-Hartmanba9dc652005-11-16 13:41:28 -080050 .no_dynamic_id = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -070051};
52
53/* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead
54 the MODULE_DEVICE_TABLE declarations in each serial driver
55 cause the "hotplug" program to pull in whatever module is necessary
56 via modprobe, and modprobe will load usbserial because the serial
57 drivers depend on it.
58*/
59
60static int debug;
61static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */
Oliver Neukum34ef50e2007-01-13 07:29:26 +010062static spinlock_t table_lock;
Linus Torvalds1da177e2005-04-16 15:20:36 -070063static LIST_HEAD(usb_serial_driver_list);
64
65struct usb_serial *usb_serial_get_by_index(unsigned index)
66{
Oliver Neukum34ef50e2007-01-13 07:29:26 +010067 struct usb_serial *serial;
68
69 spin_lock(&table_lock);
70 serial = serial_table[index];
Linus Torvalds1da177e2005-04-16 15:20:36 -070071
72 if (serial)
73 kref_get(&serial->kref);
Oliver Neukum34ef50e2007-01-13 07:29:26 +010074 spin_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070075 return serial;
76}
77
78static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_ports, unsigned int *minor)
79{
80 unsigned int i, j;
81 int good_spot;
82
83 dbg("%s %d", __FUNCTION__, num_ports);
84
85 *minor = 0;
Oliver Neukum34ef50e2007-01-13 07:29:26 +010086 spin_lock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070087 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
88 if (serial_table[i])
89 continue;
90
91 good_spot = 1;
92 for (j = 1; j <= num_ports-1; ++j)
93 if ((i+j >= SERIAL_TTY_MINORS) || (serial_table[i+j])) {
94 good_spot = 0;
95 i += j;
96 break;
97 }
98 if (good_spot == 0)
99 continue;
100
101 *minor = i;
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100102 j = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103 dbg("%s - minor base = %d", __FUNCTION__, *minor);
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100104 for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105 serial_table[i] = serial;
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100106 serial->port[j++]->number = i;
107 }
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100108 spin_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109 return serial;
110 }
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100111 spin_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 return NULL;
113}
114
115static void return_serial(struct usb_serial *serial)
116{
117 int i;
118
119 dbg("%s", __FUNCTION__);
120
121 if (serial == NULL)
122 return;
123
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100124 spin_lock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 for (i = 0; i < serial->num_ports; ++i) {
126 serial_table[serial->minor + i] = NULL;
127 }
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100128 spin_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129}
130
131static void destroy_serial(struct kref *kref)
132{
133 struct usb_serial *serial;
134 struct usb_serial_port *port;
135 int i;
136
137 serial = to_usb_serial(kref);
138
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -0700139 dbg("%s - %s", __FUNCTION__, serial->type->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141 for (i = 0; i < serial->num_ports; ++i)
142 serial->port[i]->open_count = 0;
143
144 /* the ports are cleaned up and released in port_release() */
145 for (i = 0; i < serial->num_ports; ++i)
146 if (serial->port[i]->dev.parent != NULL) {
147 device_unregister(&serial->port[i]->dev);
148 serial->port[i] = NULL;
149 }
150
Jim Radfordd9a7eca2007-02-28 08:14:13 -0800151 if (serial->type->shutdown)
152 serial->type->shutdown(serial);
153
154 /* return the minor range that this device had */
155 return_serial(serial);
156
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157 /* 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
Jeff Dikeb68e31d2006-10-02 02:17:18 -07001074static const struct tty_operations serial_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075 .open = serial_open,
1076 .close = serial_close,
1077 .write = serial_write,
1078 .write_room = serial_write_room,
1079 .ioctl = serial_ioctl,
1080 .set_termios = serial_set_termios,
1081 .throttle = serial_throttle,
1082 .unthrottle = serial_unthrottle,
1083 .break_ctl = serial_break,
1084 .chars_in_buffer = serial_chars_in_buffer,
1085 .read_proc = serial_read_proc,
1086 .tiocmget = serial_tiocmget,
1087 .tiocmset = serial_tiocmset,
1088};
1089
1090struct tty_driver *usb_serial_tty_driver;
1091
1092static int __init usb_serial_init(void)
1093{
1094 int i;
1095 int result;
1096
1097 usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS);
1098 if (!usb_serial_tty_driver)
1099 return -ENOMEM;
1100
1101 /* Initialize our global data */
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001102 spin_lock_init(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
1104 serial_table[i] = NULL;
1105 }
1106
1107 result = bus_register(&usb_serial_bus_type);
1108 if (result) {
1109 err("%s - registering bus driver failed", __FUNCTION__);
1110 goto exit_bus;
1111 }
1112
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 usb_serial_tty_driver->owner = THIS_MODULE;
1114 usb_serial_tty_driver->driver_name = "usbserial";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 usb_serial_tty_driver->name = "ttyUSB";
1116 usb_serial_tty_driver->major = SERIAL_TTY_MAJOR;
1117 usb_serial_tty_driver->minor_start = 0;
1118 usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
1119 usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
Greg Kroah-Hartman331b8312005-06-20 21:15:16 -07001120 usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 usb_serial_tty_driver->init_termios = tty_std_termios;
1122 usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
1123 tty_set_operations(usb_serial_tty_driver, &serial_ops);
1124 result = tty_register_driver(usb_serial_tty_driver);
1125 if (result) {
1126 err("%s - tty_register_driver failed", __FUNCTION__);
1127 goto exit_reg_driver;
1128 }
1129
1130 /* register the USB driver */
1131 result = usb_register(&usb_serial_driver);
1132 if (result < 0) {
1133 err("%s - usb_register failed", __FUNCTION__);
1134 goto exit_tty;
1135 }
1136
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001137 /* register the generic driver, if we should */
1138 result = usb_serial_generic_register(debug);
1139 if (result < 0) {
1140 err("%s - registering generic driver failed", __FUNCTION__);
1141 goto exit_generic;
1142 }
1143
Greg Kroah-Hartman17a882f2005-06-20 21:15:16 -07001144 info(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145
1146 return result;
1147
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001148exit_generic:
1149 usb_deregister(&usb_serial_driver);
1150
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151exit_tty:
1152 tty_unregister_driver(usb_serial_tty_driver);
1153
1154exit_reg_driver:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 bus_unregister(&usb_serial_bus_type);
1156
1157exit_bus:
1158 err ("%s - returning with error %d", __FUNCTION__, result);
1159 put_tty_driver(usb_serial_tty_driver);
1160 return result;
1161}
1162
1163
1164static void __exit usb_serial_exit(void)
1165{
1166 usb_serial_console_exit();
1167
1168 usb_serial_generic_deregister();
1169
1170 usb_deregister(&usb_serial_driver);
1171 tty_unregister_driver(usb_serial_tty_driver);
1172 put_tty_driver(usb_serial_tty_driver);
1173 bus_unregister(&usb_serial_bus_type);
1174}
1175
1176
1177module_init(usb_serial_init);
1178module_exit(usb_serial_exit);
1179
1180#define set_to_generic_if_null(type, function) \
1181 do { \
1182 if (!type->function) { \
1183 type->function = usb_serial_generic_##function; \
1184 dbg("Had to override the " #function \
1185 " usb serial operation with the generic one.");\
1186 } \
1187 } while (0)
1188
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001189static void fixup_generic(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190{
1191 set_to_generic_if_null(device, open);
1192 set_to_generic_if_null(device, write);
1193 set_to_generic_if_null(device, close);
1194 set_to_generic_if_null(device, write_room);
1195 set_to_generic_if_null(device, chars_in_buffer);
1196 set_to_generic_if_null(device, read_bulk_callback);
1197 set_to_generic_if_null(device, write_bulk_callback);
1198 set_to_generic_if_null(device, shutdown);
1199}
1200
Oliver Neukum4b10f0f2007-01-13 07:31:27 +01001201int usb_serial_register(struct usb_serial_driver *driver) /* must be called with BKL held */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202{
1203 int retval;
1204
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001205 fixup_generic(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001207 if (!driver->description)
1208 driver->description = driver->driver.name;
1209
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210 /* Add this device to our list of devices */
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001211 list_add(&driver->driver_list, &usb_serial_driver_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001213 retval = usb_serial_bus_register(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 if (retval) {
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001215 err("problem %d when registering driver %s", retval, driver->description);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001216 list_del(&driver->driver_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 }
1218 else
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001219 info("USB Serial support registered for %s", driver->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220
1221 return retval;
1222}
1223
1224
Oliver Neukum4b10f0f2007-01-13 07:31:27 +01001225void usb_serial_deregister(struct usb_serial_driver *device) /* must be called with BKL held */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226{
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001227 info("USB Serial deregistering driver %s", device->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 list_del(&device->driver_list);
1229 usb_serial_bus_deregister(device);
1230}
1231
1232
1233
1234/* If the usb-serial core is built into the core, the usb-serial drivers
1235 need these symbols to load properly as modules. */
1236EXPORT_SYMBOL_GPL(usb_serial_register);
1237EXPORT_SYMBOL_GPL(usb_serial_deregister);
1238EXPORT_SYMBOL_GPL(usb_serial_probe);
1239EXPORT_SYMBOL_GPL(usb_serial_disconnect);
1240EXPORT_SYMBOL_GPL(usb_serial_port_softint);
1241
1242
1243/* Module information */
1244MODULE_AUTHOR( DRIVER_AUTHOR );
1245MODULE_DESCRIPTION( DRIVER_DESC );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246MODULE_LICENSE("GPL");
1247
1248module_param(debug, bool, S_IRUGO | S_IWUSR);
1249MODULE_PARM_DESC(debug, "Debug enabled or not");