blob: 3780362eb9f05198c4adb7c60ee20d3e0e1fed2f [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;
102 dbg("%s - minor base = %d", __FUNCTION__, *minor);
103 for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i)
104 serial_table[i] = serial;
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100105 spin_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106 return serial;
107 }
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100108 spin_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109 return NULL;
110}
111
112static void return_serial(struct usb_serial *serial)
113{
114 int i;
115
116 dbg("%s", __FUNCTION__);
117
118 if (serial == NULL)
119 return;
120
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100121 spin_lock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122 for (i = 0; i < serial->num_ports; ++i) {
123 serial_table[serial->minor + i] = NULL;
124 }
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100125 spin_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126}
127
128static void destroy_serial(struct kref *kref)
129{
130 struct usb_serial *serial;
131 struct usb_serial_port *port;
132 int i;
133
134 serial = to_usb_serial(kref);
135
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -0700136 dbg("%s - %s", __FUNCTION__, serial->type->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137
138 serial->type->shutdown(serial);
139
140 /* return the minor range that this device had */
141 return_serial(serial);
142
143 for (i = 0; i < serial->num_ports; ++i)
144 serial->port[i]->open_count = 0;
145
146 /* the ports are cleaned up and released in port_release() */
147 for (i = 0; i < serial->num_ports; ++i)
148 if (serial->port[i]->dev.parent != NULL) {
149 device_unregister(&serial->port[i]->dev);
150 serial->port[i] = NULL;
151 }
152
153 /* If this is a "fake" port, we have to clean it up here, as it will
154 * not get cleaned up in port_release() as it was never registered with
155 * the driver core */
156 if (serial->num_ports < serial->num_port_pointers) {
157 for (i = serial->num_ports; i < serial->num_port_pointers; ++i) {
158 port = serial->port[i];
159 if (!port)
160 continue;
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700161 port_free(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 }
163 }
164
165 usb_put_dev(serial->dev);
166
167 /* free up any memory that we allocated */
168 kfree (serial);
169}
170
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200171void usb_serial_put(struct usb_serial *serial)
172{
173 kref_put(&serial->kref, destroy_serial);
174}
175
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176/*****************************************************************************
177 * Driver tty interface functions
178 *****************************************************************************/
179static int serial_open (struct tty_struct *tty, struct file * filp)
180{
181 struct usb_serial *serial;
182 struct usb_serial_port *port;
183 unsigned int portNumber;
184 int retval;
185
186 dbg("%s", __FUNCTION__);
187
188 /* get the serial object associated with this tty pointer */
189 serial = usb_serial_get_by_index(tty->index);
190 if (!serial) {
191 tty->driver_data = NULL;
192 return -ENODEV;
193 }
194
195 portNumber = tty->index - serial->minor;
196 port = serial->port[portNumber];
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300197 if (!port) {
198 retval = -ENODEV;
199 goto bailout_kref_put;
200 }
Luiz Fernando Capitulino8a4613f2005-11-28 19:16:07 -0200201
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300202 if (mutex_lock_interruptible(&port->mutex)) {
203 retval = -ERESTARTSYS;
204 goto bailout_kref_put;
205 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206
207 ++port->open_count;
208
Paul Fulghumca854852006-04-13 22:28:17 +0200209 /* set up our port structure making the tty driver
210 * remember our port object, and us it */
211 tty->driver_data = port;
212 port->tty = tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213
Paul Fulghumca854852006-04-13 22:28:17 +0200214 if (port->open_count == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215
216 /* lock this module before we call it
217 * this may fail, which means we must bail out,
218 * safe because we are called with BKL held */
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700219 if (!try_module_get(serial->type->driver.owner)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 retval = -ENODEV;
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300221 goto bailout_mutex_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222 }
223
224 /* only call the device specific open if this
225 * is the first time the port is opened */
226 retval = serial->type->open(port, filp);
227 if (retval)
228 goto bailout_module_put;
229 }
230
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300231 mutex_unlock(&port->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232 return 0;
233
234bailout_module_put:
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700235 module_put(serial->type->driver.owner);
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300236bailout_mutex_unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 port->open_count = 0;
Frank Gevaertsb059c812006-06-14 15:52:05 +0200238 tty->driver_data = NULL;
239 port->tty = NULL;
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300240 mutex_unlock(&port->mutex);
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300241bailout_kref_put:
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200242 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 return retval;
244}
245
246static void serial_close(struct tty_struct *tty, struct file * filp)
247{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200248 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249
250 if (!port)
251 return;
252
253 dbg("%s - port %d", __FUNCTION__, port->number);
254
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300255 mutex_lock(&port->mutex);
Luiz Fernando Capitulino8a4613f2005-11-28 19:16:07 -0200256
Greg Kroah-Hartman91c0bce2006-03-06 13:25:52 -0800257 if (port->open_count == 0) {
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300258 mutex_unlock(&port->mutex);
Greg Kroah-Hartman91c0bce2006-03-06 13:25:52 -0800259 return;
260 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261
262 --port->open_count;
263 if (port->open_count == 0) {
264 /* only call the device specific close if this
265 * port is being closed by the last owner */
266 port->serial->type->close(port, filp);
267
268 if (port->tty) {
269 if (port->tty->driver_data)
270 port->tty->driver_data = NULL;
271 port->tty = NULL;
272 }
273
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700274 module_put(port->serial->type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 }
276
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300277 mutex_unlock(&port->mutex);
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200278 usb_serial_put(port->serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279}
280
281static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count)
282{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200283 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 int retval = -EINVAL;
285
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200286 if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED)
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200287 goto exit;
288
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289 dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count);
290
291 if (!port->open_count) {
292 dbg("%s - port not opened", __FUNCTION__);
293 goto exit;
294 }
295
296 /* pass on to the driver specific version of this function */
297 retval = port->serial->type->write(port, buf, count);
298
299exit:
300 return retval;
301}
302
303static int serial_write_room (struct tty_struct *tty)
304{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200305 struct usb_serial_port *port = tty->driver_data;
Luiz Fernando N. Capitulinodb54a532006-06-12 22:46:20 -0300306 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200308 if (!port)
309 goto exit;
310
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 dbg("%s - port %d", __FUNCTION__, port->number);
312
313 if (!port->open_count) {
314 dbg("%s - port not open", __FUNCTION__);
315 goto exit;
316 }
317
318 /* pass on to the driver specific version of this function */
319 retval = port->serial->type->write_room(port);
320
321exit:
322 return retval;
323}
324
325static int serial_chars_in_buffer (struct tty_struct *tty)
326{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200327 struct usb_serial_port *port = tty->driver_data;
Luiz Fernando N. Capitulinodb54a532006-06-12 22:46:20 -0300328 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200330 if (!port)
331 goto exit;
332
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 dbg("%s = port %d", __FUNCTION__, port->number);
334
335 if (!port->open_count) {
336 dbg("%s - port not open", __FUNCTION__);
337 goto exit;
338 }
339
340 /* pass on to the driver specific version of this function */
341 retval = port->serial->type->chars_in_buffer(port);
342
343exit:
344 return retval;
345}
346
347static void serial_throttle (struct tty_struct * tty)
348{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200349 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200351 if (!port)
352 return;
353
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354 dbg("%s - port %d", __FUNCTION__, port->number);
355
356 if (!port->open_count) {
357 dbg ("%s - port not open", __FUNCTION__);
358 return;
359 }
360
361 /* pass on to the driver specific version of this function */
362 if (port->serial->type->throttle)
363 port->serial->type->throttle(port);
364}
365
366static void serial_unthrottle (struct tty_struct * tty)
367{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200368 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200370 if (!port)
371 return;
372
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 dbg("%s - port %d", __FUNCTION__, port->number);
374
375 if (!port->open_count) {
376 dbg("%s - port not open", __FUNCTION__);
377 return;
378 }
379
380 /* pass on to the driver specific version of this function */
381 if (port->serial->type->unthrottle)
382 port->serial->type->unthrottle(port);
383}
384
385static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
386{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200387 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 int retval = -ENODEV;
389
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200390 if (!port)
391 goto exit;
392
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
394
395 if (!port->open_count) {
396 dbg ("%s - port not open", __FUNCTION__);
397 goto exit;
398 }
399
400 /* pass on to the driver specific version of this function if it is available */
401 if (port->serial->type->ioctl)
402 retval = port->serial->type->ioctl(port, file, cmd, arg);
403 else
404 retval = -ENOIOCTLCMD;
405
406exit:
407 return retval;
408}
409
Alan Cox606d0992006-12-08 02:38:45 -0800410static void serial_set_termios (struct tty_struct *tty, struct ktermios * old)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200412 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200414 if (!port)
415 return;
416
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 dbg("%s - port %d", __FUNCTION__, port->number);
418
419 if (!port->open_count) {
420 dbg("%s - port not open", __FUNCTION__);
421 return;
422 }
423
424 /* pass on to the driver specific version of this function if it is available */
425 if (port->serial->type->set_termios)
426 port->serial->type->set_termios(port, old);
427}
428
429static void serial_break (struct tty_struct *tty, int break_state)
430{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200431 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200433 if (!port)
434 return;
435
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 dbg("%s - port %d", __FUNCTION__, port->number);
437
438 if (!port->open_count) {
439 dbg("%s - port not open", __FUNCTION__);
440 return;
441 }
442
443 /* pass on to the driver specific version of this function if it is available */
444 if (port->serial->type->break_ctl)
445 port->serial->type->break_ctl(port, break_state);
446}
447
448static int serial_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data)
449{
450 struct usb_serial *serial;
451 int length = 0;
452 int i;
453 off_t begin = 0;
454 char tmp[40];
455
456 dbg("%s", __FUNCTION__);
Greg Kroah-Hartman17a882f2005-06-20 21:15:16 -0700457 length += sprintf (page, "usbserinfo:1.0 driver:2.0\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458 for (i = 0; i < SERIAL_TTY_MINORS && length < PAGE_SIZE; ++i) {
459 serial = usb_serial_get_by_index(i);
460 if (serial == NULL)
461 continue;
462
463 length += sprintf (page+length, "%d:", i);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700464 if (serial->type->driver.owner)
465 length += sprintf (page+length, " module:%s", module_name(serial->type->driver.owner));
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -0700466 length += sprintf (page+length, " name:\"%s\"", serial->type->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467 length += sprintf (page+length, " vendor:%04x product:%04x",
468 le16_to_cpu(serial->dev->descriptor.idVendor),
469 le16_to_cpu(serial->dev->descriptor.idProduct));
470 length += sprintf (page+length, " num_ports:%d", serial->num_ports);
471 length += sprintf (page+length, " port:%d", i - serial->minor + 1);
472
473 usb_make_path(serial->dev, tmp, sizeof(tmp));
474 length += sprintf (page+length, " path:%s", tmp);
475
476 length += sprintf (page+length, "\n");
Matthias Urlichs59925832006-09-11 12:35:20 +0200477 if ((length + begin) > (off + count)) {
478 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479 goto done;
Matthias Urlichs59925832006-09-11 12:35:20 +0200480 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 if ((length + begin) < off) {
482 begin += length;
483 length = 0;
484 }
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200485 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 }
487 *eof = 1;
488done:
489 if (off >= (length + begin))
490 return 0;
491 *start = page + (off-begin);
492 return ((count < begin+length-off) ? count : begin+length-off);
493}
494
495static int serial_tiocmget (struct tty_struct *tty, struct file *file)
496{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200497 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200499 if (!port)
Luiz Fernando N. Capitulinodb54a532006-06-12 22:46:20 -0300500 return -ENODEV;
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200501
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 dbg("%s - port %d", __FUNCTION__, port->number);
503
504 if (!port->open_count) {
505 dbg("%s - port not open", __FUNCTION__);
Luiz Fernando N. Capitulinodb54a532006-06-12 22:46:20 -0300506 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 }
508
509 if (port->serial->type->tiocmget)
510 return port->serial->type->tiocmget(port, file);
511
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512 return -EINVAL;
513}
514
515static int serial_tiocmset (struct tty_struct *tty, struct file *file,
516 unsigned int set, unsigned int clear)
517{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200518 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200520 if (!port)
Luiz Fernando N. Capitulinodb54a532006-06-12 22:46:20 -0300521 return -ENODEV;
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200522
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 dbg("%s - port %d", __FUNCTION__, port->number);
524
525 if (!port->open_count) {
526 dbg("%s - port not open", __FUNCTION__);
Luiz Fernando N. Capitulinodb54a532006-06-12 22:46:20 -0300527 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 }
529
530 if (port->serial->type->tiocmset)
531 return port->serial->type->tiocmset(port, file, set, clear);
532
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533 return -EINVAL;
534}
535
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700536/*
537 * We would be calling tty_wakeup here, but unfortunately some line
538 * disciplines have an annoying habit of calling tty->write from
539 * the write wakeup callback (e.g. n_hdlc.c).
540 */
541void usb_serial_port_softint(struct usb_serial_port *port)
542{
543 schedule_work(&port->work);
544}
545
David Howellsc4028952006-11-22 14:57:56 +0000546static void usb_serial_port_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547{
David Howellsc4028952006-11-22 14:57:56 +0000548 struct usb_serial_port *port =
549 container_of(work, struct usb_serial_port, work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 struct tty_struct *tty;
551
552 dbg("%s - port %d", __FUNCTION__, port->number);
553
554 if (!port)
555 return;
556
557 tty = port->tty;
558 if (!tty)
559 return;
560
561 tty_wakeup(tty);
562}
563
564static void port_release(struct device *dev)
565{
566 struct usb_serial_port *port = to_usb_serial_port(dev);
567
568 dbg ("%s - %s", __FUNCTION__, dev->bus_id);
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700569 port_free(port);
570}
571
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100572static void kill_traffic(struct usb_serial_port *port)
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700573{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 usb_kill_urb(port->write_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 usb_kill_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 usb_kill_urb(port->interrupt_out_urb);
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100578}
579
580static void port_free(struct usb_serial_port *port)
581{
582 kill_traffic(port);
583 usb_free_urb(port->read_urb);
584 usb_free_urb(port->write_urb);
585 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 usb_free_urb(port->interrupt_out_urb);
587 kfree(port->bulk_in_buffer);
588 kfree(port->bulk_out_buffer);
589 kfree(port->interrupt_in_buffer);
590 kfree(port->interrupt_out_buffer);
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700591 flush_scheduled_work(); /* port->work */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592 kfree(port);
593}
594
595static struct usb_serial * create_serial (struct usb_device *dev,
596 struct usb_interface *interface,
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700597 struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598{
599 struct usb_serial *serial;
600
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100601 serial = kzalloc(sizeof(*serial), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602 if (!serial) {
603 dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);
604 return NULL;
605 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 serial->dev = usb_get_dev(dev);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700607 serial->type = driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 serial->interface = interface;
609 kref_init(&serial->kref);
610
611 return serial;
612}
613
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100614static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf,
615 struct usb_serial_driver *drv)
616{
617 struct usb_dynid *dynid;
618
619 spin_lock(&drv->dynids.lock);
620 list_for_each_entry(dynid, &drv->dynids.list, node) {
621 if (usb_match_one_id(intf, &dynid->id)) {
622 spin_unlock(&drv->dynids.lock);
623 return &dynid->id;
624 }
625 }
626 spin_unlock(&drv->dynids.lock);
627 return NULL;
628}
629
630static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv,
631 struct usb_interface *intf)
632{
633 const struct usb_device_id *id;
634
635 id = usb_match_id(intf, drv->id_table);
636 if (id) {
637 dbg("static descriptor matches");
638 goto exit;
639 }
640 id = match_dynamic_id(intf, drv);
641 if (id)
642 dbg("dynamic descriptor matches");
643exit:
644 return id;
645}
646
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700647static struct usb_serial_driver *search_serial_device(struct usb_interface *iface)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648{
649 struct list_head *p;
650 const struct usb_device_id *id;
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700651 struct usb_serial_driver *t;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652
Adrian Bunk93b1fae2006-01-10 00:13:33 +0100653 /* Check if the usb id matches a known device */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 list_for_each(p, &usb_serial_driver_list) {
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700655 t = list_entry(p, struct usb_serial_driver, driver_list);
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100656 id = get_iface_id(t, iface);
657 if (id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 return t;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 }
660
661 return NULL;
662}
663
664int usb_serial_probe(struct usb_interface *interface,
665 const struct usb_device_id *id)
666{
667 struct usb_device *dev = interface_to_usbdev (interface);
668 struct usb_serial *serial = NULL;
669 struct usb_serial_port *port;
670 struct usb_host_interface *iface_desc;
671 struct usb_endpoint_descriptor *endpoint;
672 struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS];
673 struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS];
674 struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];
675 struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700676 struct usb_serial_driver *type = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 int retval;
678 int minor;
679 int buffer_size;
680 int i;
681 int num_interrupt_in = 0;
682 int num_interrupt_out = 0;
683 int num_bulk_in = 0;
684 int num_bulk_out = 0;
685 int num_ports = 0;
686 int max_endpoints;
687
688 type = search_serial_device(interface);
689 if (!type) {
690 dbg("none matched");
691 return -ENODEV;
692 }
693
694 serial = create_serial (dev, interface, type);
695 if (!serial) {
696 dev_err(&interface->dev, "%s - out of memory\n", __FUNCTION__);
697 return -ENOMEM;
698 }
699
700 /* if this device type has a probe function, call it */
701 if (type->probe) {
702 const struct usb_device_id *id;
703
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700704 if (!try_module_get(type->driver.owner)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 dev_err(&interface->dev, "module get failed, exiting\n");
706 kfree (serial);
707 return -EIO;
708 }
709
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100710 id = get_iface_id(type, interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711 retval = type->probe(serial, id);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700712 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713
714 if (retval) {
715 dbg ("sub driver rejected device");
716 kfree (serial);
717 return retval;
718 }
719 }
720
721 /* descriptor matches, let's find the endpoints needed */
722 /* check out the endpoints */
723 iface_desc = interface->cur_altsetting;
724 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
725 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700726
727 if (usb_endpoint_is_bulk_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 /* we found a bulk in endpoint */
729 dbg("found bulk in on endpoint %d", i);
730 bulk_in_endpoint[num_bulk_in] = endpoint;
731 ++num_bulk_in;
732 }
733
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700734 if (usb_endpoint_is_bulk_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 /* we found a bulk out endpoint */
736 dbg("found bulk out on endpoint %d", i);
737 bulk_out_endpoint[num_bulk_out] = endpoint;
738 ++num_bulk_out;
739 }
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700740
741 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 /* we found a interrupt in endpoint */
743 dbg("found interrupt in on endpoint %d", i);
744 interrupt_in_endpoint[num_interrupt_in] = endpoint;
745 ++num_interrupt_in;
746 }
747
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700748 if (usb_endpoint_is_int_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 /* we found an interrupt out endpoint */
750 dbg("found interrupt out on endpoint %d", i);
751 interrupt_out_endpoint[num_interrupt_out] = endpoint;
752 ++num_interrupt_out;
753 }
754 }
755
756#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
757 /* BEGIN HORRIBLE HACK FOR PL2303 */
758 /* this is needed due to the looney way its endpoints are set up */
759 if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&
760 (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||
761 ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) &&
Johannes Steingraeber8fd80132006-09-16 16:17:34 +0200762 (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) ||
763 ((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) &&
764 (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 if (interface != dev->actconfig->interface[0]) {
766 /* check out the endpoints of the other interface*/
767 iface_desc = dev->actconfig->interface[0]->cur_altsetting;
768 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
769 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700770 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 /* we found a interrupt in endpoint */
772 dbg("found interrupt in for Prolific device on separate interface");
773 interrupt_in_endpoint[num_interrupt_in] = endpoint;
774 ++num_interrupt_in;
775 }
776 }
777 }
778
779 /* Now make sure the PL-2303 is configured correctly.
780 * If not, give up now and hope this hack will work
781 * properly during a later invocation of usb_serial_probe
782 */
783 if (num_bulk_in == 0 || num_bulk_out == 0) {
784 dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
785 kfree (serial);
786 return -ENODEV;
787 }
788 }
789 /* END HORRIBLE HACK FOR PL2303 */
790#endif
791
792 /* found all that we need */
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -0700793 dev_info(&interface->dev, "%s converter detected\n", type->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794
795#ifdef CONFIG_USB_SERIAL_GENERIC
796 if (type == &usb_serial_generic_device) {
797 num_ports = num_bulk_out;
798 if (num_ports == 0) {
799 dev_err(&interface->dev, "Generic device with no bulk out, not allowed.\n");
800 kfree (serial);
801 return -EIO;
802 }
803 }
804#endif
805 if (!num_ports) {
806 /* if this device type has a calc_num_ports function, call it */
807 if (type->calc_num_ports) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700808 if (!try_module_get(type->driver.owner)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 dev_err(&interface->dev, "module get failed, exiting\n");
810 kfree (serial);
811 return -EIO;
812 }
813 num_ports = type->calc_num_ports (serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700814 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 }
816 if (!num_ports)
817 num_ports = type->num_ports;
818 }
819
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820 serial->minor = minor;
821 serial->num_ports = num_ports;
822 serial->num_bulk_in = num_bulk_in;
823 serial->num_bulk_out = num_bulk_out;
824 serial->num_interrupt_in = num_interrupt_in;
825 serial->num_interrupt_out = num_interrupt_out;
826
827 /* create our ports, we need as many as the max endpoints */
828 /* we don't use num_ports here cauz some devices have more endpoint pairs than ports */
829 max_endpoints = max(num_bulk_in, num_bulk_out);
830 max_endpoints = max(max_endpoints, num_interrupt_in);
831 max_endpoints = max(max_endpoints, num_interrupt_out);
832 max_endpoints = max(max_endpoints, (int)serial->num_ports);
833 serial->num_port_pointers = max_endpoints;
834 dbg("%s - setting up %d port structures for this device", __FUNCTION__, max_endpoints);
835 for (i = 0; i < max_endpoints; ++i) {
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100836 port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 if (!port)
838 goto probe_error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 port->number = i + serial->minor;
840 port->serial = serial;
Greg Kroah-Hartman507ca9b2005-04-23 12:49:16 -0700841 spin_lock_init(&port->lock);
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300842 mutex_init(&port->mutex);
David Howellsc4028952006-11-22 14:57:56 +0000843 INIT_WORK(&port->work, usb_serial_port_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 serial->port[i] = port;
845 }
846
847 /* set up the endpoint information */
848 for (i = 0; i < num_bulk_in; ++i) {
849 endpoint = bulk_in_endpoint[i];
850 port = serial->port[i];
851 port->read_urb = usb_alloc_urb (0, GFP_KERNEL);
852 if (!port->read_urb) {
853 dev_err(&interface->dev, "No free urbs available\n");
854 goto probe_error;
855 }
856 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
857 port->bulk_in_size = buffer_size;
858 port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
859 port->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
860 if (!port->bulk_in_buffer) {
861 dev_err(&interface->dev, "Couldn't allocate bulk_in_buffer\n");
862 goto probe_error;
863 }
864 usb_fill_bulk_urb (port->read_urb, dev,
865 usb_rcvbulkpipe (dev,
866 endpoint->bEndpointAddress),
867 port->bulk_in_buffer, buffer_size,
868 serial->type->read_bulk_callback,
869 port);
870 }
871
872 for (i = 0; i < num_bulk_out; ++i) {
873 endpoint = bulk_out_endpoint[i];
874 port = serial->port[i];
875 port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
876 if (!port->write_urb) {
877 dev_err(&interface->dev, "No free urbs available\n");
878 goto probe_error;
879 }
880 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
881 port->bulk_out_size = buffer_size;
882 port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
883 port->bulk_out_buffer = kmalloc (buffer_size, GFP_KERNEL);
884 if (!port->bulk_out_buffer) {
885 dev_err(&interface->dev, "Couldn't allocate bulk_out_buffer\n");
886 goto probe_error;
887 }
888 usb_fill_bulk_urb (port->write_urb, dev,
889 usb_sndbulkpipe (dev,
890 endpoint->bEndpointAddress),
891 port->bulk_out_buffer, buffer_size,
892 serial->type->write_bulk_callback,
893 port);
894 }
895
896 if (serial->type->read_int_callback) {
897 for (i = 0; i < num_interrupt_in; ++i) {
898 endpoint = interrupt_in_endpoint[i];
899 port = serial->port[i];
900 port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
901 if (!port->interrupt_in_urb) {
902 dev_err(&interface->dev, "No free urbs available\n");
903 goto probe_error;
904 }
905 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
906 port->interrupt_in_endpointAddress = endpoint->bEndpointAddress;
907 port->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
908 if (!port->interrupt_in_buffer) {
909 dev_err(&interface->dev, "Couldn't allocate interrupt_in_buffer\n");
910 goto probe_error;
911 }
912 usb_fill_int_urb (port->interrupt_in_urb, dev,
913 usb_rcvintpipe (dev,
914 endpoint->bEndpointAddress),
915 port->interrupt_in_buffer, buffer_size,
916 serial->type->read_int_callback, port,
917 endpoint->bInterval);
918 }
919 } else if (num_interrupt_in) {
920 dbg("the device claims to support interrupt in transfers, but read_int_callback is not defined");
921 }
922
923 if (serial->type->write_int_callback) {
924 for (i = 0; i < num_interrupt_out; ++i) {
925 endpoint = interrupt_out_endpoint[i];
926 port = serial->port[i];
927 port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
928 if (!port->interrupt_out_urb) {
929 dev_err(&interface->dev, "No free urbs available\n");
930 goto probe_error;
931 }
932 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
933 port->interrupt_out_size = buffer_size;
934 port->interrupt_out_endpointAddress = endpoint->bEndpointAddress;
935 port->interrupt_out_buffer = kmalloc (buffer_size, GFP_KERNEL);
936 if (!port->interrupt_out_buffer) {
937 dev_err(&interface->dev, "Couldn't allocate interrupt_out_buffer\n");
938 goto probe_error;
939 }
940 usb_fill_int_urb (port->interrupt_out_urb, dev,
941 usb_sndintpipe (dev,
942 endpoint->bEndpointAddress),
943 port->interrupt_out_buffer, buffer_size,
944 serial->type->write_int_callback, port,
945 endpoint->bInterval);
946 }
947 } else if (num_interrupt_out) {
948 dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined");
949 }
950
951 /* if this device type has an attach function, call it */
952 if (type->attach) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700953 if (!try_module_get(type->driver.owner)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 dev_err(&interface->dev, "module get failed, exiting\n");
955 goto probe_error;
956 }
957 retval = type->attach (serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700958 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959 if (retval < 0)
960 goto probe_error;
961 if (retval > 0) {
962 /* quietly accept this device, but don't bind to a serial port
963 * as it's about to disappear */
964 goto exit;
965 }
966 }
967
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100968 if (get_free_serial (serial, num_ports, &minor) == NULL) {
969 dev_err(&interface->dev, "No more free serial devices\n");
970 goto probe_error;
971 }
972
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973 /* register all of the individual ports with the driver core */
974 for (i = 0; i < num_ports; ++i) {
975 port = serial->port[i];
976 port->dev.parent = &interface->dev;
977 port->dev.driver = NULL;
978 port->dev.bus = &usb_serial_bus_type;
979 port->dev.release = &port_release;
980
981 snprintf (&port->dev.bus_id[0], sizeof(port->dev.bus_id), "ttyUSB%d", port->number);
982 dbg ("%s - registering %s", __FUNCTION__, port->dev.bus_id);
Greg Kroah-Hartman13f4db92006-08-28 11:43:25 -0700983 retval = device_register(&port->dev);
984 if (retval)
985 dev_err(&port->dev, "Error registering port device, "
986 "continuing\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 }
988
989 usb_serial_console_init (debug, minor);
990
991exit:
992 /* success */
993 usb_set_intfdata (interface, serial);
994 return 0;
995
996probe_error:
997 for (i = 0; i < num_bulk_in; ++i) {
998 port = serial->port[i];
999 if (!port)
1000 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001001 usb_free_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 kfree(port->bulk_in_buffer);
1003 }
1004 for (i = 0; i < num_bulk_out; ++i) {
1005 port = serial->port[i];
1006 if (!port)
1007 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001008 usb_free_urb(port->write_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 kfree(port->bulk_out_buffer);
1010 }
1011 for (i = 0; i < num_interrupt_in; ++i) {
1012 port = serial->port[i];
1013 if (!port)
1014 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001015 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 kfree(port->interrupt_in_buffer);
1017 }
1018 for (i = 0; i < num_interrupt_out; ++i) {
1019 port = serial->port[i];
1020 if (!port)
1021 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001022 usb_free_urb(port->interrupt_out_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 kfree(port->interrupt_out_buffer);
1024 }
1025
1026 /* return the minor range that this device had */
1027 return_serial (serial);
1028
1029 /* free up any memory that we allocated */
1030 for (i = 0; i < serial->num_port_pointers; ++i)
1031 kfree(serial->port[i]);
1032 kfree (serial);
1033 return -EIO;
1034}
1035
1036void usb_serial_disconnect(struct usb_interface *interface)
1037{
1038 int i;
1039 struct usb_serial *serial = usb_get_intfdata (interface);
1040 struct device *dev = &interface->dev;
1041 struct usb_serial_port *port;
1042
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +02001043 usb_serial_console_disconnect(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 dbg ("%s", __FUNCTION__);
1045
1046 usb_set_intfdata (interface, NULL);
1047 if (serial) {
1048 for (i = 0; i < serial->num_ports; ++i) {
1049 port = serial->port[i];
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001050 if (port) {
1051 if (port->tty)
1052 tty_hangup(port->tty);
1053 kill_traffic(port);
1054 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 }
1056 /* let the last holder of this object
1057 * cause it to be cleaned up */
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +02001058 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 }
1060 dev_info(dev, "device disconnected\n");
1061}
1062
Jeff Dikeb68e31d2006-10-02 02:17:18 -07001063static const struct tty_operations serial_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 .open = serial_open,
1065 .close = serial_close,
1066 .write = serial_write,
1067 .write_room = serial_write_room,
1068 .ioctl = serial_ioctl,
1069 .set_termios = serial_set_termios,
1070 .throttle = serial_throttle,
1071 .unthrottle = serial_unthrottle,
1072 .break_ctl = serial_break,
1073 .chars_in_buffer = serial_chars_in_buffer,
1074 .read_proc = serial_read_proc,
1075 .tiocmget = serial_tiocmget,
1076 .tiocmset = serial_tiocmset,
1077};
1078
1079struct tty_driver *usb_serial_tty_driver;
1080
1081static int __init usb_serial_init(void)
1082{
1083 int i;
1084 int result;
1085
1086 usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS);
1087 if (!usb_serial_tty_driver)
1088 return -ENOMEM;
1089
1090 /* Initialize our global data */
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001091 spin_lock_init(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
1093 serial_table[i] = NULL;
1094 }
1095
1096 result = bus_register(&usb_serial_bus_type);
1097 if (result) {
1098 err("%s - registering bus driver failed", __FUNCTION__);
1099 goto exit_bus;
1100 }
1101
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102 usb_serial_tty_driver->owner = THIS_MODULE;
1103 usb_serial_tty_driver->driver_name = "usbserial";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 usb_serial_tty_driver->name = "ttyUSB";
1105 usb_serial_tty_driver->major = SERIAL_TTY_MAJOR;
1106 usb_serial_tty_driver->minor_start = 0;
1107 usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
1108 usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
Greg Kroah-Hartman331b8312005-06-20 21:15:16 -07001109 usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 usb_serial_tty_driver->init_termios = tty_std_termios;
1111 usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
1112 tty_set_operations(usb_serial_tty_driver, &serial_ops);
1113 result = tty_register_driver(usb_serial_tty_driver);
1114 if (result) {
1115 err("%s - tty_register_driver failed", __FUNCTION__);
1116 goto exit_reg_driver;
1117 }
1118
1119 /* register the USB driver */
1120 result = usb_register(&usb_serial_driver);
1121 if (result < 0) {
1122 err("%s - usb_register failed", __FUNCTION__);
1123 goto exit_tty;
1124 }
1125
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001126 /* register the generic driver, if we should */
1127 result = usb_serial_generic_register(debug);
1128 if (result < 0) {
1129 err("%s - registering generic driver failed", __FUNCTION__);
1130 goto exit_generic;
1131 }
1132
Greg Kroah-Hartman17a882f2005-06-20 21:15:16 -07001133 info(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134
1135 return result;
1136
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001137exit_generic:
1138 usb_deregister(&usb_serial_driver);
1139
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140exit_tty:
1141 tty_unregister_driver(usb_serial_tty_driver);
1142
1143exit_reg_driver:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 bus_unregister(&usb_serial_bus_type);
1145
1146exit_bus:
1147 err ("%s - returning with error %d", __FUNCTION__, result);
1148 put_tty_driver(usb_serial_tty_driver);
1149 return result;
1150}
1151
1152
1153static void __exit usb_serial_exit(void)
1154{
1155 usb_serial_console_exit();
1156
1157 usb_serial_generic_deregister();
1158
1159 usb_deregister(&usb_serial_driver);
1160 tty_unregister_driver(usb_serial_tty_driver);
1161 put_tty_driver(usb_serial_tty_driver);
1162 bus_unregister(&usb_serial_bus_type);
1163}
1164
1165
1166module_init(usb_serial_init);
1167module_exit(usb_serial_exit);
1168
1169#define set_to_generic_if_null(type, function) \
1170 do { \
1171 if (!type->function) { \
1172 type->function = usb_serial_generic_##function; \
1173 dbg("Had to override the " #function \
1174 " usb serial operation with the generic one.");\
1175 } \
1176 } while (0)
1177
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001178static void fixup_generic(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179{
1180 set_to_generic_if_null(device, open);
1181 set_to_generic_if_null(device, write);
1182 set_to_generic_if_null(device, close);
1183 set_to_generic_if_null(device, write_room);
1184 set_to_generic_if_null(device, chars_in_buffer);
1185 set_to_generic_if_null(device, read_bulk_callback);
1186 set_to_generic_if_null(device, write_bulk_callback);
1187 set_to_generic_if_null(device, shutdown);
1188}
1189
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001190int usb_serial_register(struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191{
1192 int retval;
1193
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001194 fixup_generic(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001196 if (!driver->description)
1197 driver->description = driver->driver.name;
1198
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199 /* Add this device to our list of devices */
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001200 list_add(&driver->driver_list, &usb_serial_driver_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001202 retval = usb_serial_bus_register(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203 if (retval) {
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001204 err("problem %d when registering driver %s", retval, driver->description);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001205 list_del(&driver->driver_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 }
1207 else
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001208 info("USB Serial support registered for %s", driver->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209
1210 return retval;
1211}
1212
1213
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001214void usb_serial_deregister(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215{
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001216 info("USB Serial deregistering driver %s", device->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 list_del(&device->driver_list);
1218 usb_serial_bus_deregister(device);
1219}
1220
1221
1222
1223/* If the usb-serial core is built into the core, the usb-serial drivers
1224 need these symbols to load properly as modules. */
1225EXPORT_SYMBOL_GPL(usb_serial_register);
1226EXPORT_SYMBOL_GPL(usb_serial_deregister);
1227EXPORT_SYMBOL_GPL(usb_serial_probe);
1228EXPORT_SYMBOL_GPL(usb_serial_disconnect);
1229EXPORT_SYMBOL_GPL(usb_serial_port_softint);
1230
1231
1232/* Module information */
1233MODULE_AUTHOR( DRIVER_AUTHOR );
1234MODULE_DESCRIPTION( DRIVER_DESC );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235MODULE_LICENSE("GPL");
1236
1237module_param(debug, bool, S_IRUGO | S_IWUSR);
1238MODULE_PARM_DESC(debug, "Debug enabled or not");