blob: 7639022cdf84af83a74bcf5550abf5e642e527d6 [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
Jim Radford521b85a2007-03-13 08:30:50 -0700141 serial->type->shutdown(serial);
142
143 /* return the minor range that this device had */
144 return_serial(serial);
145
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146 for (i = 0; i < serial->num_ports; ++i)
147 serial->port[i]->open_count = 0;
148
149 /* the ports are cleaned up and released in port_release() */
150 for (i = 0; i < serial->num_ports; ++i)
151 if (serial->port[i]->dev.parent != NULL) {
152 device_unregister(&serial->port[i]->dev);
153 serial->port[i] = NULL;
154 }
155
156 /* If this is a "fake" port, we have to clean it up here, as it will
157 * not get cleaned up in port_release() as it was never registered with
158 * the driver core */
159 if (serial->num_ports < serial->num_port_pointers) {
160 for (i = serial->num_ports; i < serial->num_port_pointers; ++i) {
161 port = serial->port[i];
162 if (!port)
163 continue;
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700164 port_free(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165 }
166 }
167
168 usb_put_dev(serial->dev);
169
170 /* free up any memory that we allocated */
171 kfree (serial);
172}
173
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200174void usb_serial_put(struct usb_serial *serial)
175{
176 kref_put(&serial->kref, destroy_serial);
177}
178
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179/*****************************************************************************
180 * Driver tty interface functions
181 *****************************************************************************/
182static int serial_open (struct tty_struct *tty, struct file * filp)
183{
184 struct usb_serial *serial;
185 struct usb_serial_port *port;
186 unsigned int portNumber;
187 int retval;
188
189 dbg("%s", __FUNCTION__);
190
191 /* get the serial object associated with this tty pointer */
192 serial = usb_serial_get_by_index(tty->index);
193 if (!serial) {
194 tty->driver_data = NULL;
195 return -ENODEV;
196 }
197
198 portNumber = tty->index - serial->minor;
199 port = serial->port[portNumber];
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300200 if (!port) {
201 retval = -ENODEV;
202 goto bailout_kref_put;
203 }
Luiz Fernando Capitulino8a4613f2005-11-28 19:16:07 -0200204
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300205 if (mutex_lock_interruptible(&port->mutex)) {
206 retval = -ERESTARTSYS;
207 goto bailout_kref_put;
208 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209
210 ++port->open_count;
211
Paul Fulghumca854852006-04-13 22:28:17 +0200212 /* set up our port structure making the tty driver
213 * remember our port object, and us it */
214 tty->driver_data = port;
215 port->tty = tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216
Paul Fulghumca854852006-04-13 22:28:17 +0200217 if (port->open_count == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218
219 /* lock this module before we call it
220 * this may fail, which means we must bail out,
221 * safe because we are called with BKL held */
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700222 if (!try_module_get(serial->type->driver.owner)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223 retval = -ENODEV;
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300224 goto bailout_mutex_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225 }
226
227 /* only call the device specific open if this
228 * is the first time the port is opened */
229 retval = serial->type->open(port, filp);
230 if (retval)
231 goto bailout_module_put;
232 }
233
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300234 mutex_unlock(&port->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 return 0;
236
237bailout_module_put:
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700238 module_put(serial->type->driver.owner);
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300239bailout_mutex_unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 port->open_count = 0;
Frank Gevaertsb059c812006-06-14 15:52:05 +0200241 tty->driver_data = NULL;
242 port->tty = NULL;
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300243 mutex_unlock(&port->mutex);
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300244bailout_kref_put:
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200245 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246 return retval;
247}
248
249static void serial_close(struct tty_struct *tty, struct file * filp)
250{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200251 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252
253 if (!port)
254 return;
255
256 dbg("%s - port %d", __FUNCTION__, port->number);
257
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300258 mutex_lock(&port->mutex);
Luiz Fernando Capitulino8a4613f2005-11-28 19:16:07 -0200259
Greg Kroah-Hartman91c0bce2006-03-06 13:25:52 -0800260 if (port->open_count == 0) {
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300261 mutex_unlock(&port->mutex);
Greg Kroah-Hartman91c0bce2006-03-06 13:25:52 -0800262 return;
263 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264
265 --port->open_count;
266 if (port->open_count == 0) {
267 /* only call the device specific close if this
268 * port is being closed by the last owner */
269 port->serial->type->close(port, filp);
270
271 if (port->tty) {
272 if (port->tty->driver_data)
273 port->tty->driver_data = NULL;
274 port->tty = NULL;
275 }
276
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700277 module_put(port->serial->type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 }
279
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300280 mutex_unlock(&port->mutex);
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200281 usb_serial_put(port->serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282}
283
284static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count)
285{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200286 struct usb_serial_port *port = tty->driver_data;
Oliver Neukum3ff4fd92007-01-13 07:32:27 +0100287 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200289 if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED)
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200290 goto exit;
291
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count);
293
294 if (!port->open_count) {
Oliver Neukum3ff4fd92007-01-13 07:32:27 +0100295 retval = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 dbg("%s - port not opened", __FUNCTION__);
297 goto exit;
298 }
299
300 /* pass on to the driver specific version of this function */
301 retval = port->serial->type->write(port, buf, count);
302
303exit:
304 return retval;
305}
306
307static int serial_write_room (struct tty_struct *tty)
308{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200309 struct usb_serial_port *port = tty->driver_data;
Luiz Fernando N. Capitulinodb54a532006-06-12 22:46:20 -0300310 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200312 if (!port)
313 goto exit;
314
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315 dbg("%s - port %d", __FUNCTION__, port->number);
316
317 if (!port->open_count) {
318 dbg("%s - port not open", __FUNCTION__);
319 goto exit;
320 }
321
322 /* pass on to the driver specific version of this function */
323 retval = port->serial->type->write_room(port);
324
325exit:
326 return retval;
327}
328
329static int serial_chars_in_buffer (struct tty_struct *tty)
330{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200331 struct usb_serial_port *port = tty->driver_data;
Luiz Fernando N. Capitulinodb54a532006-06-12 22:46:20 -0300332 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200334 if (!port)
335 goto exit;
336
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 dbg("%s = port %d", __FUNCTION__, port->number);
338
339 if (!port->open_count) {
340 dbg("%s - port not open", __FUNCTION__);
341 goto exit;
342 }
343
344 /* pass on to the driver specific version of this function */
345 retval = port->serial->type->chars_in_buffer(port);
346
347exit:
348 return retval;
349}
350
351static void serial_throttle (struct tty_struct * tty)
352{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200353 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200355 if (!port)
356 return;
357
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358 dbg("%s - port %d", __FUNCTION__, port->number);
359
360 if (!port->open_count) {
361 dbg ("%s - port not open", __FUNCTION__);
362 return;
363 }
364
365 /* pass on to the driver specific version of this function */
366 if (port->serial->type->throttle)
367 port->serial->type->throttle(port);
368}
369
370static void serial_unthrottle (struct tty_struct * tty)
371{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200372 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200374 if (!port)
375 return;
376
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 dbg("%s - port %d", __FUNCTION__, port->number);
378
379 if (!port->open_count) {
380 dbg("%s - port not open", __FUNCTION__);
381 return;
382 }
383
384 /* pass on to the driver specific version of this function */
385 if (port->serial->type->unthrottle)
386 port->serial->type->unthrottle(port);
387}
388
389static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
390{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200391 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 int retval = -ENODEV;
393
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200394 if (!port)
395 goto exit;
396
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
398
399 if (!port->open_count) {
400 dbg ("%s - port not open", __FUNCTION__);
401 goto exit;
402 }
403
404 /* pass on to the driver specific version of this function if it is available */
405 if (port->serial->type->ioctl)
406 retval = port->serial->type->ioctl(port, file, cmd, arg);
407 else
408 retval = -ENOIOCTLCMD;
409
410exit:
411 return retval;
412}
413
Alan Cox606d0992006-12-08 02:38:45 -0800414static void serial_set_termios (struct tty_struct *tty, struct ktermios * old)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200416 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200418 if (!port)
419 return;
420
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421 dbg("%s - port %d", __FUNCTION__, port->number);
422
423 if (!port->open_count) {
424 dbg("%s - port not open", __FUNCTION__);
425 return;
426 }
427
428 /* pass on to the driver specific version of this function if it is available */
429 if (port->serial->type->set_termios)
430 port->serial->type->set_termios(port, old);
431}
432
433static void serial_break (struct tty_struct *tty, int break_state)
434{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200435 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200437 if (!port)
438 return;
439
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 dbg("%s - port %d", __FUNCTION__, port->number);
441
442 if (!port->open_count) {
443 dbg("%s - port not open", __FUNCTION__);
444 return;
445 }
446
447 /* pass on to the driver specific version of this function if it is available */
448 if (port->serial->type->break_ctl)
449 port->serial->type->break_ctl(port, break_state);
450}
451
452static int serial_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data)
453{
454 struct usb_serial *serial;
455 int length = 0;
456 int i;
457 off_t begin = 0;
458 char tmp[40];
459
460 dbg("%s", __FUNCTION__);
Greg Kroah-Hartman17a882f2005-06-20 21:15:16 -0700461 length += sprintf (page, "usbserinfo:1.0 driver:2.0\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 for (i = 0; i < SERIAL_TTY_MINORS && length < PAGE_SIZE; ++i) {
463 serial = usb_serial_get_by_index(i);
464 if (serial == NULL)
465 continue;
466
467 length += sprintf (page+length, "%d:", i);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700468 if (serial->type->driver.owner)
469 length += sprintf (page+length, " module:%s", module_name(serial->type->driver.owner));
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -0700470 length += sprintf (page+length, " name:\"%s\"", serial->type->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 length += sprintf (page+length, " vendor:%04x product:%04x",
472 le16_to_cpu(serial->dev->descriptor.idVendor),
473 le16_to_cpu(serial->dev->descriptor.idProduct));
474 length += sprintf (page+length, " num_ports:%d", serial->num_ports);
475 length += sprintf (page+length, " port:%d", i - serial->minor + 1);
476
477 usb_make_path(serial->dev, tmp, sizeof(tmp));
478 length += sprintf (page+length, " path:%s", tmp);
479
480 length += sprintf (page+length, "\n");
Matthias Urlichs59925832006-09-11 12:35:20 +0200481 if ((length + begin) > (off + count)) {
482 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 goto done;
Matthias Urlichs59925832006-09-11 12:35:20 +0200484 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 if ((length + begin) < off) {
486 begin += length;
487 length = 0;
488 }
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200489 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 }
491 *eof = 1;
492done:
493 if (off >= (length + begin))
494 return 0;
495 *start = page + (off-begin);
496 return ((count < begin+length-off) ? count : begin+length-off);
497}
498
499static int serial_tiocmget (struct tty_struct *tty, struct file *file)
500{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200501 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200503 if (!port)
Luiz Fernando N. Capitulinodb54a532006-06-12 22:46:20 -0300504 return -ENODEV;
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200505
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 dbg("%s - port %d", __FUNCTION__, port->number);
507
508 if (!port->open_count) {
509 dbg("%s - port not open", __FUNCTION__);
Luiz Fernando N. Capitulinodb54a532006-06-12 22:46:20 -0300510 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511 }
512
513 if (port->serial->type->tiocmget)
514 return port->serial->type->tiocmget(port, file);
515
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 return -EINVAL;
517}
518
519static int serial_tiocmset (struct tty_struct *tty, struct file *file,
520 unsigned int set, unsigned int clear)
521{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200522 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200524 if (!port)
Luiz Fernando N. Capitulinodb54a532006-06-12 22:46:20 -0300525 return -ENODEV;
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200526
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 dbg("%s - port %d", __FUNCTION__, port->number);
528
529 if (!port->open_count) {
530 dbg("%s - port not open", __FUNCTION__);
Luiz Fernando N. Capitulinodb54a532006-06-12 22:46:20 -0300531 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 }
533
534 if (port->serial->type->tiocmset)
535 return port->serial->type->tiocmset(port, file, set, clear);
536
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 return -EINVAL;
538}
539
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700540/*
541 * We would be calling tty_wakeup here, but unfortunately some line
542 * disciplines have an annoying habit of calling tty->write from
543 * the write wakeup callback (e.g. n_hdlc.c).
544 */
545void usb_serial_port_softint(struct usb_serial_port *port)
546{
547 schedule_work(&port->work);
548}
549
David Howellsc4028952006-11-22 14:57:56 +0000550static void usb_serial_port_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551{
David Howellsc4028952006-11-22 14:57:56 +0000552 struct usb_serial_port *port =
553 container_of(work, struct usb_serial_port, work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 struct tty_struct *tty;
555
556 dbg("%s - port %d", __FUNCTION__, port->number);
557
558 if (!port)
559 return;
560
561 tty = port->tty;
562 if (!tty)
563 return;
564
565 tty_wakeup(tty);
566}
567
568static void port_release(struct device *dev)
569{
570 struct usb_serial_port *port = to_usb_serial_port(dev);
571
572 dbg ("%s - %s", __FUNCTION__, dev->bus_id);
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700573 port_free(port);
574}
575
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100576static void kill_traffic(struct usb_serial_port *port)
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700577{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579 usb_kill_urb(port->write_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 usb_kill_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 usb_kill_urb(port->interrupt_out_urb);
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100582}
583
584static void port_free(struct usb_serial_port *port)
585{
586 kill_traffic(port);
587 usb_free_urb(port->read_urb);
588 usb_free_urb(port->write_urb);
589 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 usb_free_urb(port->interrupt_out_urb);
591 kfree(port->bulk_in_buffer);
592 kfree(port->bulk_out_buffer);
593 kfree(port->interrupt_in_buffer);
594 kfree(port->interrupt_out_buffer);
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700595 flush_scheduled_work(); /* port->work */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596 kfree(port);
597}
598
599static struct usb_serial * create_serial (struct usb_device *dev,
600 struct usb_interface *interface,
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700601 struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602{
603 struct usb_serial *serial;
604
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100605 serial = kzalloc(sizeof(*serial), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 if (!serial) {
607 dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);
608 return NULL;
609 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610 serial->dev = usb_get_dev(dev);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700611 serial->type = driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612 serial->interface = interface;
613 kref_init(&serial->kref);
614
615 return serial;
616}
617
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100618static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf,
619 struct usb_serial_driver *drv)
620{
621 struct usb_dynid *dynid;
622
623 spin_lock(&drv->dynids.lock);
624 list_for_each_entry(dynid, &drv->dynids.list, node) {
625 if (usb_match_one_id(intf, &dynid->id)) {
626 spin_unlock(&drv->dynids.lock);
627 return &dynid->id;
628 }
629 }
630 spin_unlock(&drv->dynids.lock);
631 return NULL;
632}
633
634static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv,
635 struct usb_interface *intf)
636{
637 const struct usb_device_id *id;
638
639 id = usb_match_id(intf, drv->id_table);
640 if (id) {
641 dbg("static descriptor matches");
642 goto exit;
643 }
644 id = match_dynamic_id(intf, drv);
645 if (id)
646 dbg("dynamic descriptor matches");
647exit:
648 return id;
649}
650
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700651static struct usb_serial_driver *search_serial_device(struct usb_interface *iface)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652{
653 struct list_head *p;
654 const struct usb_device_id *id;
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700655 struct usb_serial_driver *t;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656
Adrian Bunk93b1fae2006-01-10 00:13:33 +0100657 /* Check if the usb id matches a known device */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 list_for_each(p, &usb_serial_driver_list) {
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700659 t = list_entry(p, struct usb_serial_driver, driver_list);
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100660 id = get_iface_id(t, iface);
661 if (id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 return t;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 }
664
665 return NULL;
666}
667
668int usb_serial_probe(struct usb_interface *interface,
669 const struct usb_device_id *id)
670{
671 struct usb_device *dev = interface_to_usbdev (interface);
672 struct usb_serial *serial = NULL;
673 struct usb_serial_port *port;
674 struct usb_host_interface *iface_desc;
675 struct usb_endpoint_descriptor *endpoint;
676 struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS];
677 struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS];
678 struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];
679 struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700680 struct usb_serial_driver *type = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681 int retval;
682 int minor;
683 int buffer_size;
684 int i;
685 int num_interrupt_in = 0;
686 int num_interrupt_out = 0;
687 int num_bulk_in = 0;
688 int num_bulk_out = 0;
689 int num_ports = 0;
690 int max_endpoints;
691
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100692 lock_kernel(); /* guard against unloading a serial driver module */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693 type = search_serial_device(interface);
694 if (!type) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100695 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 dbg("none matched");
697 return -ENODEV;
698 }
699
700 serial = create_serial (dev, interface, type);
701 if (!serial) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100702 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 dev_err(&interface->dev, "%s - out of memory\n", __FUNCTION__);
704 return -ENOMEM;
705 }
706
707 /* if this device type has a probe function, call it */
708 if (type->probe) {
709 const struct usb_device_id *id;
710
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700711 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100712 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713 dev_err(&interface->dev, "module get failed, exiting\n");
714 kfree (serial);
715 return -EIO;
716 }
717
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100718 id = get_iface_id(type, interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 retval = type->probe(serial, id);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700720 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721
722 if (retval) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100723 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 dbg ("sub driver rejected device");
725 kfree (serial);
726 return retval;
727 }
728 }
729
730 /* descriptor matches, let's find the endpoints needed */
731 /* check out the endpoints */
732 iface_desc = interface->cur_altsetting;
733 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
734 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700735
736 if (usb_endpoint_is_bulk_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 /* we found a bulk in endpoint */
738 dbg("found bulk in on endpoint %d", i);
739 bulk_in_endpoint[num_bulk_in] = endpoint;
740 ++num_bulk_in;
741 }
742
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700743 if (usb_endpoint_is_bulk_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 /* we found a bulk out endpoint */
745 dbg("found bulk out on endpoint %d", i);
746 bulk_out_endpoint[num_bulk_out] = endpoint;
747 ++num_bulk_out;
748 }
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700749
750 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 /* we found a interrupt in endpoint */
752 dbg("found interrupt in on endpoint %d", i);
753 interrupt_in_endpoint[num_interrupt_in] = endpoint;
754 ++num_interrupt_in;
755 }
756
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700757 if (usb_endpoint_is_int_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 /* we found an interrupt out endpoint */
759 dbg("found interrupt out on endpoint %d", i);
760 interrupt_out_endpoint[num_interrupt_out] = endpoint;
761 ++num_interrupt_out;
762 }
763 }
764
765#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
766 /* BEGIN HORRIBLE HACK FOR PL2303 */
767 /* this is needed due to the looney way its endpoints are set up */
768 if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&
769 (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||
770 ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) &&
Johannes Steingraeber8fd80132006-09-16 16:17:34 +0200771 (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) ||
772 ((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) &&
773 (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 if (interface != dev->actconfig->interface[0]) {
775 /* check out the endpoints of the other interface*/
776 iface_desc = dev->actconfig->interface[0]->cur_altsetting;
777 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
778 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700779 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 /* we found a interrupt in endpoint */
781 dbg("found interrupt in for Prolific device on separate interface");
782 interrupt_in_endpoint[num_interrupt_in] = endpoint;
783 ++num_interrupt_in;
784 }
785 }
786 }
787
788 /* Now make sure the PL-2303 is configured correctly.
789 * If not, give up now and hope this hack will work
790 * properly during a later invocation of usb_serial_probe
791 */
792 if (num_bulk_in == 0 || num_bulk_out == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100793 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
795 kfree (serial);
796 return -ENODEV;
797 }
798 }
799 /* END HORRIBLE HACK FOR PL2303 */
800#endif
801
802 /* found all that we need */
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -0700803 dev_info(&interface->dev, "%s converter detected\n", type->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804
805#ifdef CONFIG_USB_SERIAL_GENERIC
806 if (type == &usb_serial_generic_device) {
807 num_ports = num_bulk_out;
808 if (num_ports == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100809 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 dev_err(&interface->dev, "Generic device with no bulk out, not allowed.\n");
811 kfree (serial);
812 return -EIO;
813 }
814 }
815#endif
816 if (!num_ports) {
817 /* if this device type has a calc_num_ports function, call it */
818 if (type->calc_num_ports) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700819 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100820 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 dev_err(&interface->dev, "module get failed, exiting\n");
822 kfree (serial);
823 return -EIO;
824 }
825 num_ports = type->calc_num_ports (serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700826 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 }
828 if (!num_ports)
829 num_ports = type->num_ports;
830 }
831
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 serial->num_ports = num_ports;
833 serial->num_bulk_in = num_bulk_in;
834 serial->num_bulk_out = num_bulk_out;
835 serial->num_interrupt_in = num_interrupt_in;
836 serial->num_interrupt_out = num_interrupt_out;
837
838 /* create our ports, we need as many as the max endpoints */
839 /* we don't use num_ports here cauz some devices have more endpoint pairs than ports */
840 max_endpoints = max(num_bulk_in, num_bulk_out);
841 max_endpoints = max(max_endpoints, num_interrupt_in);
842 max_endpoints = max(max_endpoints, num_interrupt_out);
843 max_endpoints = max(max_endpoints, (int)serial->num_ports);
844 serial->num_port_pointers = max_endpoints;
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100845 unlock_kernel();
846
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 dbg("%s - setting up %d port structures for this device", __FUNCTION__, max_endpoints);
848 for (i = 0; i < max_endpoints; ++i) {
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100849 port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 if (!port)
851 goto probe_error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 port->serial = serial;
Greg Kroah-Hartman507ca9b2005-04-23 12:49:16 -0700853 spin_lock_init(&port->lock);
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300854 mutex_init(&port->mutex);
David Howellsc4028952006-11-22 14:57:56 +0000855 INIT_WORK(&port->work, usb_serial_port_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 serial->port[i] = port;
857 }
858
859 /* set up the endpoint information */
860 for (i = 0; i < num_bulk_in; ++i) {
861 endpoint = bulk_in_endpoint[i];
862 port = serial->port[i];
863 port->read_urb = usb_alloc_urb (0, GFP_KERNEL);
864 if (!port->read_urb) {
865 dev_err(&interface->dev, "No free urbs available\n");
866 goto probe_error;
867 }
868 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
869 port->bulk_in_size = buffer_size;
870 port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
871 port->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
872 if (!port->bulk_in_buffer) {
873 dev_err(&interface->dev, "Couldn't allocate bulk_in_buffer\n");
874 goto probe_error;
875 }
876 usb_fill_bulk_urb (port->read_urb, dev,
877 usb_rcvbulkpipe (dev,
878 endpoint->bEndpointAddress),
879 port->bulk_in_buffer, buffer_size,
880 serial->type->read_bulk_callback,
881 port);
882 }
883
884 for (i = 0; i < num_bulk_out; ++i) {
885 endpoint = bulk_out_endpoint[i];
886 port = serial->port[i];
887 port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
888 if (!port->write_urb) {
889 dev_err(&interface->dev, "No free urbs available\n");
890 goto probe_error;
891 }
892 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
893 port->bulk_out_size = buffer_size;
894 port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
895 port->bulk_out_buffer = kmalloc (buffer_size, GFP_KERNEL);
896 if (!port->bulk_out_buffer) {
897 dev_err(&interface->dev, "Couldn't allocate bulk_out_buffer\n");
898 goto probe_error;
899 }
900 usb_fill_bulk_urb (port->write_urb, dev,
901 usb_sndbulkpipe (dev,
902 endpoint->bEndpointAddress),
903 port->bulk_out_buffer, buffer_size,
904 serial->type->write_bulk_callback,
905 port);
906 }
907
908 if (serial->type->read_int_callback) {
909 for (i = 0; i < num_interrupt_in; ++i) {
910 endpoint = interrupt_in_endpoint[i];
911 port = serial->port[i];
912 port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
913 if (!port->interrupt_in_urb) {
914 dev_err(&interface->dev, "No free urbs available\n");
915 goto probe_error;
916 }
917 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
918 port->interrupt_in_endpointAddress = endpoint->bEndpointAddress;
919 port->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
920 if (!port->interrupt_in_buffer) {
921 dev_err(&interface->dev, "Couldn't allocate interrupt_in_buffer\n");
922 goto probe_error;
923 }
924 usb_fill_int_urb (port->interrupt_in_urb, dev,
925 usb_rcvintpipe (dev,
926 endpoint->bEndpointAddress),
927 port->interrupt_in_buffer, buffer_size,
928 serial->type->read_int_callback, port,
929 endpoint->bInterval);
930 }
931 } else if (num_interrupt_in) {
932 dbg("the device claims to support interrupt in transfers, but read_int_callback is not defined");
933 }
934
935 if (serial->type->write_int_callback) {
936 for (i = 0; i < num_interrupt_out; ++i) {
937 endpoint = interrupt_out_endpoint[i];
938 port = serial->port[i];
939 port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
940 if (!port->interrupt_out_urb) {
941 dev_err(&interface->dev, "No free urbs available\n");
942 goto probe_error;
943 }
944 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
945 port->interrupt_out_size = buffer_size;
946 port->interrupt_out_endpointAddress = endpoint->bEndpointAddress;
947 port->interrupt_out_buffer = kmalloc (buffer_size, GFP_KERNEL);
948 if (!port->interrupt_out_buffer) {
949 dev_err(&interface->dev, "Couldn't allocate interrupt_out_buffer\n");
950 goto probe_error;
951 }
952 usb_fill_int_urb (port->interrupt_out_urb, dev,
953 usb_sndintpipe (dev,
954 endpoint->bEndpointAddress),
955 port->interrupt_out_buffer, buffer_size,
956 serial->type->write_int_callback, port,
957 endpoint->bInterval);
958 }
959 } else if (num_interrupt_out) {
960 dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined");
961 }
962
963 /* if this device type has an attach function, call it */
964 if (type->attach) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700965 if (!try_module_get(type->driver.owner)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966 dev_err(&interface->dev, "module get failed, exiting\n");
967 goto probe_error;
968 }
969 retval = type->attach (serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700970 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971 if (retval < 0)
972 goto probe_error;
973 if (retval > 0) {
974 /* quietly accept this device, but don't bind to a serial port
975 * as it's about to disappear */
976 goto exit;
977 }
978 }
979
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100980 if (get_free_serial (serial, num_ports, &minor) == NULL) {
981 dev_err(&interface->dev, "No more free serial devices\n");
982 goto probe_error;
983 }
Oliver Neukumc744f992007-02-26 15:43:00 +0100984 serial->minor = minor;
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100985
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986 /* register all of the individual ports with the driver core */
987 for (i = 0; i < num_ports; ++i) {
988 port = serial->port[i];
989 port->dev.parent = &interface->dev;
990 port->dev.driver = NULL;
991 port->dev.bus = &usb_serial_bus_type;
992 port->dev.release = &port_release;
993
994 snprintf (&port->dev.bus_id[0], sizeof(port->dev.bus_id), "ttyUSB%d", port->number);
995 dbg ("%s - registering %s", __FUNCTION__, port->dev.bus_id);
Greg Kroah-Hartman13f4db92006-08-28 11:43:25 -0700996 retval = device_register(&port->dev);
997 if (retval)
998 dev_err(&port->dev, "Error registering port device, "
999 "continuing\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 }
1001
1002 usb_serial_console_init (debug, minor);
1003
1004exit:
1005 /* success */
1006 usb_set_intfdata (interface, serial);
1007 return 0;
1008
1009probe_error:
1010 for (i = 0; i < num_bulk_in; ++i) {
1011 port = serial->port[i];
1012 if (!port)
1013 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001014 usb_free_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 kfree(port->bulk_in_buffer);
1016 }
1017 for (i = 0; i < num_bulk_out; ++i) {
1018 port = serial->port[i];
1019 if (!port)
1020 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001021 usb_free_urb(port->write_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 kfree(port->bulk_out_buffer);
1023 }
1024 for (i = 0; i < num_interrupt_in; ++i) {
1025 port = serial->port[i];
1026 if (!port)
1027 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001028 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 kfree(port->interrupt_in_buffer);
1030 }
1031 for (i = 0; i < num_interrupt_out; ++i) {
1032 port = serial->port[i];
1033 if (!port)
1034 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001035 usb_free_urb(port->interrupt_out_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 kfree(port->interrupt_out_buffer);
1037 }
1038
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 /* free up any memory that we allocated */
1040 for (i = 0; i < serial->num_port_pointers; ++i)
1041 kfree(serial->port[i]);
1042 kfree (serial);
1043 return -EIO;
1044}
1045
1046void usb_serial_disconnect(struct usb_interface *interface)
1047{
1048 int i;
1049 struct usb_serial *serial = usb_get_intfdata (interface);
1050 struct device *dev = &interface->dev;
1051 struct usb_serial_port *port;
1052
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +02001053 usb_serial_console_disconnect(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 dbg ("%s", __FUNCTION__);
1055
1056 usb_set_intfdata (interface, NULL);
1057 if (serial) {
1058 for (i = 0; i < serial->num_ports; ++i) {
1059 port = serial->port[i];
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001060 if (port) {
1061 if (port->tty)
1062 tty_hangup(port->tty);
1063 kill_traffic(port);
1064 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065 }
1066 /* let the last holder of this object
1067 * cause it to be cleaned up */
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +02001068 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 }
1070 dev_info(dev, "device disconnected\n");
1071}
1072
Jeff Dikeb68e31d2006-10-02 02:17:18 -07001073static const struct tty_operations serial_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 .open = serial_open,
1075 .close = serial_close,
1076 .write = serial_write,
1077 .write_room = serial_write_room,
1078 .ioctl = serial_ioctl,
1079 .set_termios = serial_set_termios,
1080 .throttle = serial_throttle,
1081 .unthrottle = serial_unthrottle,
1082 .break_ctl = serial_break,
1083 .chars_in_buffer = serial_chars_in_buffer,
1084 .read_proc = serial_read_proc,
1085 .tiocmget = serial_tiocmget,
1086 .tiocmset = serial_tiocmset,
1087};
1088
1089struct tty_driver *usb_serial_tty_driver;
1090
1091static int __init usb_serial_init(void)
1092{
1093 int i;
1094 int result;
1095
1096 usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS);
1097 if (!usb_serial_tty_driver)
1098 return -ENOMEM;
1099
1100 /* Initialize our global data */
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001101 spin_lock_init(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
1103 serial_table[i] = NULL;
1104 }
1105
1106 result = bus_register(&usb_serial_bus_type);
1107 if (result) {
1108 err("%s - registering bus driver failed", __FUNCTION__);
1109 goto exit_bus;
1110 }
1111
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 usb_serial_tty_driver->owner = THIS_MODULE;
1113 usb_serial_tty_driver->driver_name = "usbserial";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114 usb_serial_tty_driver->name = "ttyUSB";
1115 usb_serial_tty_driver->major = SERIAL_TTY_MAJOR;
1116 usb_serial_tty_driver->minor_start = 0;
1117 usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
1118 usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
Greg Kroah-Hartman331b8312005-06-20 21:15:16 -07001119 usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 usb_serial_tty_driver->init_termios = tty_std_termios;
1121 usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
1122 tty_set_operations(usb_serial_tty_driver, &serial_ops);
1123 result = tty_register_driver(usb_serial_tty_driver);
1124 if (result) {
1125 err("%s - tty_register_driver failed", __FUNCTION__);
1126 goto exit_reg_driver;
1127 }
1128
1129 /* register the USB driver */
1130 result = usb_register(&usb_serial_driver);
1131 if (result < 0) {
1132 err("%s - usb_register failed", __FUNCTION__);
1133 goto exit_tty;
1134 }
1135
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001136 /* register the generic driver, if we should */
1137 result = usb_serial_generic_register(debug);
1138 if (result < 0) {
1139 err("%s - registering generic driver failed", __FUNCTION__);
1140 goto exit_generic;
1141 }
1142
Greg Kroah-Hartman17a882f2005-06-20 21:15:16 -07001143 info(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144
1145 return result;
1146
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001147exit_generic:
1148 usb_deregister(&usb_serial_driver);
1149
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150exit_tty:
1151 tty_unregister_driver(usb_serial_tty_driver);
1152
1153exit_reg_driver:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154 bus_unregister(&usb_serial_bus_type);
1155
1156exit_bus:
1157 err ("%s - returning with error %d", __FUNCTION__, result);
1158 put_tty_driver(usb_serial_tty_driver);
1159 return result;
1160}
1161
1162
1163static void __exit usb_serial_exit(void)
1164{
1165 usb_serial_console_exit();
1166
1167 usb_serial_generic_deregister();
1168
1169 usb_deregister(&usb_serial_driver);
1170 tty_unregister_driver(usb_serial_tty_driver);
1171 put_tty_driver(usb_serial_tty_driver);
1172 bus_unregister(&usb_serial_bus_type);
1173}
1174
1175
1176module_init(usb_serial_init);
1177module_exit(usb_serial_exit);
1178
1179#define set_to_generic_if_null(type, function) \
1180 do { \
1181 if (!type->function) { \
1182 type->function = usb_serial_generic_##function; \
1183 dbg("Had to override the " #function \
1184 " usb serial operation with the generic one.");\
1185 } \
1186 } while (0)
1187
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001188static void fixup_generic(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189{
1190 set_to_generic_if_null(device, open);
1191 set_to_generic_if_null(device, write);
1192 set_to_generic_if_null(device, close);
1193 set_to_generic_if_null(device, write_room);
1194 set_to_generic_if_null(device, chars_in_buffer);
1195 set_to_generic_if_null(device, read_bulk_callback);
1196 set_to_generic_if_null(device, write_bulk_callback);
1197 set_to_generic_if_null(device, shutdown);
1198}
1199
Oliver Neukum4b10f0f2007-01-13 07:31:27 +01001200int usb_serial_register(struct usb_serial_driver *driver) /* must be called with BKL held */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201{
1202 int retval;
1203
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001204 fixup_generic(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001206 if (!driver->description)
1207 driver->description = driver->driver.name;
1208
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 /* Add this device to our list of devices */
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001210 list_add(&driver->driver_list, &usb_serial_driver_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001212 retval = usb_serial_bus_register(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 if (retval) {
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001214 err("problem %d when registering driver %s", retval, driver->description);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001215 list_del(&driver->driver_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216 }
1217 else
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001218 info("USB Serial support registered for %s", driver->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219
1220 return retval;
1221}
1222
1223
Oliver Neukum4b10f0f2007-01-13 07:31:27 +01001224void usb_serial_deregister(struct usb_serial_driver *device) /* must be called with BKL held */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225{
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001226 info("USB Serial deregistering driver %s", device->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 list_del(&device->driver_list);
1228 usb_serial_bus_deregister(device);
1229}
1230
1231
1232
1233/* If the usb-serial core is built into the core, the usb-serial drivers
1234 need these symbols to load properly as modules. */
1235EXPORT_SYMBOL_GPL(usb_serial_register);
1236EXPORT_SYMBOL_GPL(usb_serial_deregister);
1237EXPORT_SYMBOL_GPL(usb_serial_probe);
1238EXPORT_SYMBOL_GPL(usb_serial_disconnect);
1239EXPORT_SYMBOL_GPL(usb_serial_port_softint);
1240
1241
1242/* Module information */
1243MODULE_AUTHOR( DRIVER_AUTHOR );
1244MODULE_DESCRIPTION( DRIVER_DESC );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245MODULE_LICENSE("GPL");
1246
1247module_param(debug, bool, S_IRUGO | S_IWUSR);
1248MODULE_PARM_DESC(debug, "Debug enabled or not");