blob: 9dbd1fa84e88391225dc6d1ca817e72ff73f4f2a [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
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138 for (i = 0; i < serial->num_ports; ++i)
139 serial->port[i]->open_count = 0;
140
141 /* the ports are cleaned up and released in port_release() */
142 for (i = 0; i < serial->num_ports; ++i)
143 if (serial->port[i]->dev.parent != NULL) {
144 device_unregister(&serial->port[i]->dev);
145 serial->port[i] = NULL;
146 }
147
Jim Radfordd9a7eca2007-02-28 08:14:13 -0800148 if (serial->type->shutdown)
149 serial->type->shutdown(serial);
150
151 /* return the minor range that this device had */
152 return_serial(serial);
153
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154 /* If this is a "fake" port, we have to clean it up here, as it will
155 * not get cleaned up in port_release() as it was never registered with
156 * the driver core */
157 if (serial->num_ports < serial->num_port_pointers) {
158 for (i = serial->num_ports; i < serial->num_port_pointers; ++i) {
159 port = serial->port[i];
160 if (!port)
161 continue;
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700162 port_free(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163 }
164 }
165
166 usb_put_dev(serial->dev);
167
168 /* free up any memory that we allocated */
169 kfree (serial);
170}
171
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200172void usb_serial_put(struct usb_serial *serial)
173{
174 kref_put(&serial->kref, destroy_serial);
175}
176
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177/*****************************************************************************
178 * Driver tty interface functions
179 *****************************************************************************/
180static int serial_open (struct tty_struct *tty, struct file * filp)
181{
182 struct usb_serial *serial;
183 struct usb_serial_port *port;
184 unsigned int portNumber;
185 int retval;
186
187 dbg("%s", __FUNCTION__);
188
189 /* get the serial object associated with this tty pointer */
190 serial = usb_serial_get_by_index(tty->index);
191 if (!serial) {
192 tty->driver_data = NULL;
193 return -ENODEV;
194 }
195
196 portNumber = tty->index - serial->minor;
197 port = serial->port[portNumber];
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300198 if (!port) {
199 retval = -ENODEV;
200 goto bailout_kref_put;
201 }
Luiz Fernando Capitulino8a4613f2005-11-28 19:16:07 -0200202
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300203 if (mutex_lock_interruptible(&port->mutex)) {
204 retval = -ERESTARTSYS;
205 goto bailout_kref_put;
206 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207
208 ++port->open_count;
209
Paul Fulghumca854852006-04-13 22:28:17 +0200210 /* set up our port structure making the tty driver
211 * remember our port object, and us it */
212 tty->driver_data = port;
213 port->tty = tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214
Paul Fulghumca854852006-04-13 22:28:17 +0200215 if (port->open_count == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216
217 /* lock this module before we call it
218 * this may fail, which means we must bail out,
219 * safe because we are called with BKL held */
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700220 if (!try_module_get(serial->type->driver.owner)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221 retval = -ENODEV;
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300222 goto bailout_mutex_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223 }
224
225 /* only call the device specific open if this
226 * is the first time the port is opened */
227 retval = serial->type->open(port, filp);
228 if (retval)
229 goto bailout_module_put;
230 }
231
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300232 mutex_unlock(&port->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 return 0;
234
235bailout_module_put:
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700236 module_put(serial->type->driver.owner);
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300237bailout_mutex_unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 port->open_count = 0;
Frank Gevaertsb059c812006-06-14 15:52:05 +0200239 tty->driver_data = NULL;
240 port->tty = NULL;
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300241 mutex_unlock(&port->mutex);
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300242bailout_kref_put:
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200243 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 return retval;
245}
246
247static void serial_close(struct tty_struct *tty, struct file * filp)
248{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200249 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250
251 if (!port)
252 return;
253
254 dbg("%s - port %d", __FUNCTION__, port->number);
255
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300256 mutex_lock(&port->mutex);
Luiz Fernando Capitulino8a4613f2005-11-28 19:16:07 -0200257
Greg Kroah-Hartman91c0bce2006-03-06 13:25:52 -0800258 if (port->open_count == 0) {
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300259 mutex_unlock(&port->mutex);
Greg Kroah-Hartman91c0bce2006-03-06 13:25:52 -0800260 return;
261 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262
263 --port->open_count;
264 if (port->open_count == 0) {
265 /* only call the device specific close if this
266 * port is being closed by the last owner */
267 port->serial->type->close(port, filp);
268
269 if (port->tty) {
270 if (port->tty->driver_data)
271 port->tty->driver_data = NULL;
272 port->tty = NULL;
273 }
274
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700275 module_put(port->serial->type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276 }
277
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300278 mutex_unlock(&port->mutex);
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200279 usb_serial_put(port->serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280}
281
282static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count)
283{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200284 struct usb_serial_port *port = tty->driver_data;
Oliver Neukum3ff4fd92007-01-13 07:32:27 +0100285 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200287 if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED)
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200288 goto exit;
289
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count);
291
292 if (!port->open_count) {
Oliver Neukum3ff4fd92007-01-13 07:32:27 +0100293 retval = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 dbg("%s - port not opened", __FUNCTION__);
295 goto exit;
296 }
297
298 /* pass on to the driver specific version of this function */
299 retval = port->serial->type->write(port, buf, count);
300
301exit:
302 return retval;
303}
304
305static int serial_write_room (struct tty_struct *tty)
306{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200307 struct usb_serial_port *port = tty->driver_data;
Luiz Fernando N. Capitulinodb54a532006-06-12 22:46:20 -0300308 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200310 if (!port)
311 goto exit;
312
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313 dbg("%s - port %d", __FUNCTION__, port->number);
314
315 if (!port->open_count) {
316 dbg("%s - port not open", __FUNCTION__);
317 goto exit;
318 }
319
320 /* pass on to the driver specific version of this function */
321 retval = port->serial->type->write_room(port);
322
323exit:
324 return retval;
325}
326
327static int serial_chars_in_buffer (struct tty_struct *tty)
328{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200329 struct usb_serial_port *port = tty->driver_data;
Luiz Fernando N. Capitulinodb54a532006-06-12 22:46:20 -0300330 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200332 if (!port)
333 goto exit;
334
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335 dbg("%s = port %d", __FUNCTION__, port->number);
336
337 if (!port->open_count) {
338 dbg("%s - port not open", __FUNCTION__);
339 goto exit;
340 }
341
342 /* pass on to the driver specific version of this function */
343 retval = port->serial->type->chars_in_buffer(port);
344
345exit:
346 return retval;
347}
348
349static void serial_throttle (struct tty_struct * tty)
350{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200351 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200353 if (!port)
354 return;
355
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 dbg("%s - port %d", __FUNCTION__, port->number);
357
358 if (!port->open_count) {
359 dbg ("%s - port not open", __FUNCTION__);
360 return;
361 }
362
363 /* pass on to the driver specific version of this function */
364 if (port->serial->type->throttle)
365 port->serial->type->throttle(port);
366}
367
368static void serial_unthrottle (struct tty_struct * tty)
369{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200370 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200372 if (!port)
373 return;
374
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 dbg("%s - port %d", __FUNCTION__, port->number);
376
377 if (!port->open_count) {
378 dbg("%s - port not open", __FUNCTION__);
379 return;
380 }
381
382 /* pass on to the driver specific version of this function */
383 if (port->serial->type->unthrottle)
384 port->serial->type->unthrottle(port);
385}
386
387static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
388{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200389 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 int retval = -ENODEV;
391
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200392 if (!port)
393 goto exit;
394
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395 dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
396
397 if (!port->open_count) {
398 dbg ("%s - port not open", __FUNCTION__);
399 goto exit;
400 }
401
402 /* pass on to the driver specific version of this function if it is available */
403 if (port->serial->type->ioctl)
404 retval = port->serial->type->ioctl(port, file, cmd, arg);
405 else
406 retval = -ENOIOCTLCMD;
407
408exit:
409 return retval;
410}
411
Alan Cox606d0992006-12-08 02:38:45 -0800412static void serial_set_termios (struct tty_struct *tty, struct ktermios * old)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200414 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200416 if (!port)
417 return;
418
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 dbg("%s - port %d", __FUNCTION__, port->number);
420
421 if (!port->open_count) {
422 dbg("%s - port not open", __FUNCTION__);
423 return;
424 }
425
426 /* pass on to the driver specific version of this function if it is available */
427 if (port->serial->type->set_termios)
428 port->serial->type->set_termios(port, old);
429}
430
431static void serial_break (struct tty_struct *tty, int break_state)
432{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200433 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200435 if (!port)
436 return;
437
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438 dbg("%s - port %d", __FUNCTION__, port->number);
439
440 if (!port->open_count) {
441 dbg("%s - port not open", __FUNCTION__);
442 return;
443 }
444
445 /* pass on to the driver specific version of this function if it is available */
446 if (port->serial->type->break_ctl)
447 port->serial->type->break_ctl(port, break_state);
448}
449
450static int serial_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data)
451{
452 struct usb_serial *serial;
453 int length = 0;
454 int i;
455 off_t begin = 0;
456 char tmp[40];
457
458 dbg("%s", __FUNCTION__);
Greg Kroah-Hartman17a882f2005-06-20 21:15:16 -0700459 length += sprintf (page, "usbserinfo:1.0 driver:2.0\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 for (i = 0; i < SERIAL_TTY_MINORS && length < PAGE_SIZE; ++i) {
461 serial = usb_serial_get_by_index(i);
462 if (serial == NULL)
463 continue;
464
465 length += sprintf (page+length, "%d:", i);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700466 if (serial->type->driver.owner)
467 length += sprintf (page+length, " module:%s", module_name(serial->type->driver.owner));
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -0700468 length += sprintf (page+length, " name:\"%s\"", serial->type->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 length += sprintf (page+length, " vendor:%04x product:%04x",
470 le16_to_cpu(serial->dev->descriptor.idVendor),
471 le16_to_cpu(serial->dev->descriptor.idProduct));
472 length += sprintf (page+length, " num_ports:%d", serial->num_ports);
473 length += sprintf (page+length, " port:%d", i - serial->minor + 1);
474
475 usb_make_path(serial->dev, tmp, sizeof(tmp));
476 length += sprintf (page+length, " path:%s", tmp);
477
478 length += sprintf (page+length, "\n");
Matthias Urlichs59925832006-09-11 12:35:20 +0200479 if ((length + begin) > (off + count)) {
480 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 goto done;
Matthias Urlichs59925832006-09-11 12:35:20 +0200482 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 if ((length + begin) < off) {
484 begin += length;
485 length = 0;
486 }
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200487 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 }
489 *eof = 1;
490done:
491 if (off >= (length + begin))
492 return 0;
493 *start = page + (off-begin);
494 return ((count < begin+length-off) ? count : begin+length-off);
495}
496
497static int serial_tiocmget (struct tty_struct *tty, struct file *file)
498{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200499 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200501 if (!port)
Luiz Fernando N. Capitulinodb54a532006-06-12 22:46:20 -0300502 return -ENODEV;
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200503
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 dbg("%s - port %d", __FUNCTION__, port->number);
505
506 if (!port->open_count) {
507 dbg("%s - port not open", __FUNCTION__);
Luiz Fernando N. Capitulinodb54a532006-06-12 22:46:20 -0300508 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 }
510
511 if (port->serial->type->tiocmget)
512 return port->serial->type->tiocmget(port, file);
513
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 return -EINVAL;
515}
516
517static int serial_tiocmset (struct tty_struct *tty, struct file *file,
518 unsigned int set, unsigned int clear)
519{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200520 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200522 if (!port)
Luiz Fernando N. Capitulinodb54a532006-06-12 22:46:20 -0300523 return -ENODEV;
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200524
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 dbg("%s - port %d", __FUNCTION__, port->number);
526
527 if (!port->open_count) {
528 dbg("%s - port not open", __FUNCTION__);
Luiz Fernando N. Capitulinodb54a532006-06-12 22:46:20 -0300529 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 }
531
532 if (port->serial->type->tiocmset)
533 return port->serial->type->tiocmset(port, file, set, clear);
534
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 return -EINVAL;
536}
537
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700538/*
539 * We would be calling tty_wakeup here, but unfortunately some line
540 * disciplines have an annoying habit of calling tty->write from
541 * the write wakeup callback (e.g. n_hdlc.c).
542 */
543void usb_serial_port_softint(struct usb_serial_port *port)
544{
545 schedule_work(&port->work);
546}
547
David Howellsc4028952006-11-22 14:57:56 +0000548static void usb_serial_port_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549{
David Howellsc4028952006-11-22 14:57:56 +0000550 struct usb_serial_port *port =
551 container_of(work, struct usb_serial_port, work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 struct tty_struct *tty;
553
554 dbg("%s - port %d", __FUNCTION__, port->number);
555
556 if (!port)
557 return;
558
559 tty = port->tty;
560 if (!tty)
561 return;
562
563 tty_wakeup(tty);
564}
565
566static void port_release(struct device *dev)
567{
568 struct usb_serial_port *port = to_usb_serial_port(dev);
569
570 dbg ("%s - %s", __FUNCTION__, dev->bus_id);
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700571 port_free(port);
572}
573
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100574static void kill_traffic(struct usb_serial_port *port)
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700575{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 usb_kill_urb(port->write_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578 usb_kill_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579 usb_kill_urb(port->interrupt_out_urb);
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100580}
581
582static void port_free(struct usb_serial_port *port)
583{
584 kill_traffic(port);
585 usb_free_urb(port->read_urb);
586 usb_free_urb(port->write_urb);
587 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 usb_free_urb(port->interrupt_out_urb);
589 kfree(port->bulk_in_buffer);
590 kfree(port->bulk_out_buffer);
591 kfree(port->interrupt_in_buffer);
592 kfree(port->interrupt_out_buffer);
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700593 flush_scheduled_work(); /* port->work */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 kfree(port);
595}
596
597static struct usb_serial * create_serial (struct usb_device *dev,
598 struct usb_interface *interface,
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700599 struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600{
601 struct usb_serial *serial;
602
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100603 serial = kzalloc(sizeof(*serial), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 if (!serial) {
605 dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);
606 return NULL;
607 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 serial->dev = usb_get_dev(dev);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700609 serial->type = driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610 serial->interface = interface;
611 kref_init(&serial->kref);
612
613 return serial;
614}
615
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100616static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf,
617 struct usb_serial_driver *drv)
618{
619 struct usb_dynid *dynid;
620
621 spin_lock(&drv->dynids.lock);
622 list_for_each_entry(dynid, &drv->dynids.list, node) {
623 if (usb_match_one_id(intf, &dynid->id)) {
624 spin_unlock(&drv->dynids.lock);
625 return &dynid->id;
626 }
627 }
628 spin_unlock(&drv->dynids.lock);
629 return NULL;
630}
631
632static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv,
633 struct usb_interface *intf)
634{
635 const struct usb_device_id *id;
636
637 id = usb_match_id(intf, drv->id_table);
638 if (id) {
639 dbg("static descriptor matches");
640 goto exit;
641 }
642 id = match_dynamic_id(intf, drv);
643 if (id)
644 dbg("dynamic descriptor matches");
645exit:
646 return id;
647}
648
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700649static struct usb_serial_driver *search_serial_device(struct usb_interface *iface)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650{
651 struct list_head *p;
652 const struct usb_device_id *id;
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700653 struct usb_serial_driver *t;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654
Adrian Bunk93b1fae2006-01-10 00:13:33 +0100655 /* Check if the usb id matches a known device */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 list_for_each(p, &usb_serial_driver_list) {
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700657 t = list_entry(p, struct usb_serial_driver, driver_list);
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100658 id = get_iface_id(t, iface);
659 if (id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660 return t;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 }
662
663 return NULL;
664}
665
666int usb_serial_probe(struct usb_interface *interface,
667 const struct usb_device_id *id)
668{
669 struct usb_device *dev = interface_to_usbdev (interface);
670 struct usb_serial *serial = NULL;
671 struct usb_serial_port *port;
672 struct usb_host_interface *iface_desc;
673 struct usb_endpoint_descriptor *endpoint;
674 struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS];
675 struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS];
676 struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];
677 struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700678 struct usb_serial_driver *type = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679 int retval;
680 int minor;
681 int buffer_size;
682 int i;
683 int num_interrupt_in = 0;
684 int num_interrupt_out = 0;
685 int num_bulk_in = 0;
686 int num_bulk_out = 0;
687 int num_ports = 0;
688 int max_endpoints;
689
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100690 lock_kernel(); /* guard against unloading a serial driver module */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691 type = search_serial_device(interface);
692 if (!type) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100693 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 dbg("none matched");
695 return -ENODEV;
696 }
697
698 serial = create_serial (dev, interface, type);
699 if (!serial) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100700 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 dev_err(&interface->dev, "%s - out of memory\n", __FUNCTION__);
702 return -ENOMEM;
703 }
704
705 /* if this device type has a probe function, call it */
706 if (type->probe) {
707 const struct usb_device_id *id;
708
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700709 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100710 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711 dev_err(&interface->dev, "module get failed, exiting\n");
712 kfree (serial);
713 return -EIO;
714 }
715
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100716 id = get_iface_id(type, interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717 retval = type->probe(serial, id);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700718 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719
720 if (retval) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100721 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 dbg ("sub driver rejected device");
723 kfree (serial);
724 return retval;
725 }
726 }
727
728 /* descriptor matches, let's find the endpoints needed */
729 /* check out the endpoints */
730 iface_desc = interface->cur_altsetting;
731 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
732 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700733
734 if (usb_endpoint_is_bulk_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 /* we found a bulk in endpoint */
736 dbg("found bulk in on endpoint %d", i);
737 bulk_in_endpoint[num_bulk_in] = endpoint;
738 ++num_bulk_in;
739 }
740
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700741 if (usb_endpoint_is_bulk_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 /* we found a bulk out endpoint */
743 dbg("found bulk out on endpoint %d", i);
744 bulk_out_endpoint[num_bulk_out] = endpoint;
745 ++num_bulk_out;
746 }
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700747
748 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 /* we found a interrupt in endpoint */
750 dbg("found interrupt in on endpoint %d", i);
751 interrupt_in_endpoint[num_interrupt_in] = endpoint;
752 ++num_interrupt_in;
753 }
754
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700755 if (usb_endpoint_is_int_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 /* we found an interrupt out endpoint */
757 dbg("found interrupt out on endpoint %d", i);
758 interrupt_out_endpoint[num_interrupt_out] = endpoint;
759 ++num_interrupt_out;
760 }
761 }
762
763#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
764 /* BEGIN HORRIBLE HACK FOR PL2303 */
765 /* this is needed due to the looney way its endpoints are set up */
766 if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&
767 (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||
768 ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) &&
Johannes Steingraeber8fd80132006-09-16 16:17:34 +0200769 (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) ||
770 ((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) &&
771 (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 if (interface != dev->actconfig->interface[0]) {
773 /* check out the endpoints of the other interface*/
774 iface_desc = dev->actconfig->interface[0]->cur_altsetting;
775 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
776 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700777 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 /* we found a interrupt in endpoint */
779 dbg("found interrupt in for Prolific device on separate interface");
780 interrupt_in_endpoint[num_interrupt_in] = endpoint;
781 ++num_interrupt_in;
782 }
783 }
784 }
785
786 /* Now make sure the PL-2303 is configured correctly.
787 * If not, give up now and hope this hack will work
788 * properly during a later invocation of usb_serial_probe
789 */
790 if (num_bulk_in == 0 || num_bulk_out == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100791 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
793 kfree (serial);
794 return -ENODEV;
795 }
796 }
797 /* END HORRIBLE HACK FOR PL2303 */
798#endif
799
800 /* found all that we need */
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -0700801 dev_info(&interface->dev, "%s converter detected\n", type->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802
803#ifdef CONFIG_USB_SERIAL_GENERIC
804 if (type == &usb_serial_generic_device) {
805 num_ports = num_bulk_out;
806 if (num_ports == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100807 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 dev_err(&interface->dev, "Generic device with no bulk out, not allowed.\n");
809 kfree (serial);
810 return -EIO;
811 }
812 }
813#endif
814 if (!num_ports) {
815 /* if this device type has a calc_num_ports function, call it */
816 if (type->calc_num_ports) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700817 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100818 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 dev_err(&interface->dev, "module get failed, exiting\n");
820 kfree (serial);
821 return -EIO;
822 }
823 num_ports = type->calc_num_ports (serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700824 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 }
826 if (!num_ports)
827 num_ports = type->num_ports;
828 }
829
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 serial->num_ports = num_ports;
831 serial->num_bulk_in = num_bulk_in;
832 serial->num_bulk_out = num_bulk_out;
833 serial->num_interrupt_in = num_interrupt_in;
834 serial->num_interrupt_out = num_interrupt_out;
835
836 /* create our ports, we need as many as the max endpoints */
837 /* we don't use num_ports here cauz some devices have more endpoint pairs than ports */
838 max_endpoints = max(num_bulk_in, num_bulk_out);
839 max_endpoints = max(max_endpoints, num_interrupt_in);
840 max_endpoints = max(max_endpoints, num_interrupt_out);
841 max_endpoints = max(max_endpoints, (int)serial->num_ports);
842 serial->num_port_pointers = max_endpoints;
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100843 unlock_kernel();
844
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 dbg("%s - setting up %d port structures for this device", __FUNCTION__, max_endpoints);
846 for (i = 0; i < max_endpoints; ++i) {
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100847 port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 if (!port)
849 goto probe_error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 port->number = i + serial->minor;
851 port->serial = serial;
Greg Kroah-Hartman507ca9b2005-04-23 12:49:16 -0700852 spin_lock_init(&port->lock);
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300853 mutex_init(&port->mutex);
David Howellsc4028952006-11-22 14:57:56 +0000854 INIT_WORK(&port->work, usb_serial_port_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 serial->port[i] = port;
856 }
857
858 /* set up the endpoint information */
859 for (i = 0; i < num_bulk_in; ++i) {
860 endpoint = bulk_in_endpoint[i];
861 port = serial->port[i];
862 port->read_urb = usb_alloc_urb (0, GFP_KERNEL);
863 if (!port->read_urb) {
864 dev_err(&interface->dev, "No free urbs available\n");
865 goto probe_error;
866 }
867 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
868 port->bulk_in_size = buffer_size;
869 port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
870 port->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
871 if (!port->bulk_in_buffer) {
872 dev_err(&interface->dev, "Couldn't allocate bulk_in_buffer\n");
873 goto probe_error;
874 }
875 usb_fill_bulk_urb (port->read_urb, dev,
876 usb_rcvbulkpipe (dev,
877 endpoint->bEndpointAddress),
878 port->bulk_in_buffer, buffer_size,
879 serial->type->read_bulk_callback,
880 port);
881 }
882
883 for (i = 0; i < num_bulk_out; ++i) {
884 endpoint = bulk_out_endpoint[i];
885 port = serial->port[i];
886 port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
887 if (!port->write_urb) {
888 dev_err(&interface->dev, "No free urbs available\n");
889 goto probe_error;
890 }
891 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
892 port->bulk_out_size = buffer_size;
893 port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
894 port->bulk_out_buffer = kmalloc (buffer_size, GFP_KERNEL);
895 if (!port->bulk_out_buffer) {
896 dev_err(&interface->dev, "Couldn't allocate bulk_out_buffer\n");
897 goto probe_error;
898 }
899 usb_fill_bulk_urb (port->write_urb, dev,
900 usb_sndbulkpipe (dev,
901 endpoint->bEndpointAddress),
902 port->bulk_out_buffer, buffer_size,
903 serial->type->write_bulk_callback,
904 port);
905 }
906
907 if (serial->type->read_int_callback) {
908 for (i = 0; i < num_interrupt_in; ++i) {
909 endpoint = interrupt_in_endpoint[i];
910 port = serial->port[i];
911 port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
912 if (!port->interrupt_in_urb) {
913 dev_err(&interface->dev, "No free urbs available\n");
914 goto probe_error;
915 }
916 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
917 port->interrupt_in_endpointAddress = endpoint->bEndpointAddress;
918 port->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
919 if (!port->interrupt_in_buffer) {
920 dev_err(&interface->dev, "Couldn't allocate interrupt_in_buffer\n");
921 goto probe_error;
922 }
923 usb_fill_int_urb (port->interrupt_in_urb, dev,
924 usb_rcvintpipe (dev,
925 endpoint->bEndpointAddress),
926 port->interrupt_in_buffer, buffer_size,
927 serial->type->read_int_callback, port,
928 endpoint->bInterval);
929 }
930 } else if (num_interrupt_in) {
931 dbg("the device claims to support interrupt in transfers, but read_int_callback is not defined");
932 }
933
934 if (serial->type->write_int_callback) {
935 for (i = 0; i < num_interrupt_out; ++i) {
936 endpoint = interrupt_out_endpoint[i];
937 port = serial->port[i];
938 port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
939 if (!port->interrupt_out_urb) {
940 dev_err(&interface->dev, "No free urbs available\n");
941 goto probe_error;
942 }
943 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
944 port->interrupt_out_size = buffer_size;
945 port->interrupt_out_endpointAddress = endpoint->bEndpointAddress;
946 port->interrupt_out_buffer = kmalloc (buffer_size, GFP_KERNEL);
947 if (!port->interrupt_out_buffer) {
948 dev_err(&interface->dev, "Couldn't allocate interrupt_out_buffer\n");
949 goto probe_error;
950 }
951 usb_fill_int_urb (port->interrupt_out_urb, dev,
952 usb_sndintpipe (dev,
953 endpoint->bEndpointAddress),
954 port->interrupt_out_buffer, buffer_size,
955 serial->type->write_int_callback, port,
956 endpoint->bInterval);
957 }
958 } else if (num_interrupt_out) {
959 dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined");
960 }
961
962 /* if this device type has an attach function, call it */
963 if (type->attach) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700964 if (!try_module_get(type->driver.owner)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 dev_err(&interface->dev, "module get failed, exiting\n");
966 goto probe_error;
967 }
968 retval = type->attach (serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700969 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 if (retval < 0)
971 goto probe_error;
972 if (retval > 0) {
973 /* quietly accept this device, but don't bind to a serial port
974 * as it's about to disappear */
975 goto exit;
976 }
977 }
978
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100979 if (get_free_serial (serial, num_ports, &minor) == NULL) {
980 dev_err(&interface->dev, "No more free serial devices\n");
981 goto probe_error;
982 }
Oliver Neukumc744f992007-02-26 15:43:00 +0100983 serial->minor = minor;
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100984
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 /* register all of the individual ports with the driver core */
986 for (i = 0; i < num_ports; ++i) {
987 port = serial->port[i];
988 port->dev.parent = &interface->dev;
989 port->dev.driver = NULL;
990 port->dev.bus = &usb_serial_bus_type;
991 port->dev.release = &port_release;
992
993 snprintf (&port->dev.bus_id[0], sizeof(port->dev.bus_id), "ttyUSB%d", port->number);
994 dbg ("%s - registering %s", __FUNCTION__, port->dev.bus_id);
Greg Kroah-Hartman13f4db92006-08-28 11:43:25 -0700995 retval = device_register(&port->dev);
996 if (retval)
997 dev_err(&port->dev, "Error registering port device, "
998 "continuing\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999 }
1000
1001 usb_serial_console_init (debug, minor);
1002
1003exit:
1004 /* success */
1005 usb_set_intfdata (interface, serial);
1006 return 0;
1007
1008probe_error:
1009 for (i = 0; i < num_bulk_in; ++i) {
1010 port = serial->port[i];
1011 if (!port)
1012 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001013 usb_free_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 kfree(port->bulk_in_buffer);
1015 }
1016 for (i = 0; i < num_bulk_out; ++i) {
1017 port = serial->port[i];
1018 if (!port)
1019 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001020 usb_free_urb(port->write_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 kfree(port->bulk_out_buffer);
1022 }
1023 for (i = 0; i < num_interrupt_in; ++i) {
1024 port = serial->port[i];
1025 if (!port)
1026 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001027 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 kfree(port->interrupt_in_buffer);
1029 }
1030 for (i = 0; i < num_interrupt_out; ++i) {
1031 port = serial->port[i];
1032 if (!port)
1033 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001034 usb_free_urb(port->interrupt_out_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 kfree(port->interrupt_out_buffer);
1036 }
1037
1038 /* return the minor range that this device had */
1039 return_serial (serial);
1040
1041 /* free up any memory that we allocated */
1042 for (i = 0; i < serial->num_port_pointers; ++i)
1043 kfree(serial->port[i]);
1044 kfree (serial);
1045 return -EIO;
1046}
1047
1048void usb_serial_disconnect(struct usb_interface *interface)
1049{
1050 int i;
1051 struct usb_serial *serial = usb_get_intfdata (interface);
1052 struct device *dev = &interface->dev;
1053 struct usb_serial_port *port;
1054
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +02001055 usb_serial_console_disconnect(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 dbg ("%s", __FUNCTION__);
1057
1058 usb_set_intfdata (interface, NULL);
1059 if (serial) {
1060 for (i = 0; i < serial->num_ports; ++i) {
1061 port = serial->port[i];
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001062 if (port) {
1063 if (port->tty)
1064 tty_hangup(port->tty);
1065 kill_traffic(port);
1066 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 }
1068 /* let the last holder of this object
1069 * cause it to be cleaned up */
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +02001070 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 }
1072 dev_info(dev, "device disconnected\n");
1073}
1074
Jeff Dikeb68e31d2006-10-02 02:17:18 -07001075static const struct tty_operations serial_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 .open = serial_open,
1077 .close = serial_close,
1078 .write = serial_write,
1079 .write_room = serial_write_room,
1080 .ioctl = serial_ioctl,
1081 .set_termios = serial_set_termios,
1082 .throttle = serial_throttle,
1083 .unthrottle = serial_unthrottle,
1084 .break_ctl = serial_break,
1085 .chars_in_buffer = serial_chars_in_buffer,
1086 .read_proc = serial_read_proc,
1087 .tiocmget = serial_tiocmget,
1088 .tiocmset = serial_tiocmset,
1089};
1090
1091struct tty_driver *usb_serial_tty_driver;
1092
1093static int __init usb_serial_init(void)
1094{
1095 int i;
1096 int result;
1097
1098 usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS);
1099 if (!usb_serial_tty_driver)
1100 return -ENOMEM;
1101
1102 /* Initialize our global data */
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001103 spin_lock_init(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
1105 serial_table[i] = NULL;
1106 }
1107
1108 result = bus_register(&usb_serial_bus_type);
1109 if (result) {
1110 err("%s - registering bus driver failed", __FUNCTION__);
1111 goto exit_bus;
1112 }
1113
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114 usb_serial_tty_driver->owner = THIS_MODULE;
1115 usb_serial_tty_driver->driver_name = "usbserial";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 usb_serial_tty_driver->name = "ttyUSB";
1117 usb_serial_tty_driver->major = SERIAL_TTY_MAJOR;
1118 usb_serial_tty_driver->minor_start = 0;
1119 usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
1120 usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
Greg Kroah-Hartman331b8312005-06-20 21:15:16 -07001121 usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 usb_serial_tty_driver->init_termios = tty_std_termios;
1123 usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
1124 tty_set_operations(usb_serial_tty_driver, &serial_ops);
1125 result = tty_register_driver(usb_serial_tty_driver);
1126 if (result) {
1127 err("%s - tty_register_driver failed", __FUNCTION__);
1128 goto exit_reg_driver;
1129 }
1130
1131 /* register the USB driver */
1132 result = usb_register(&usb_serial_driver);
1133 if (result < 0) {
1134 err("%s - usb_register failed", __FUNCTION__);
1135 goto exit_tty;
1136 }
1137
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001138 /* register the generic driver, if we should */
1139 result = usb_serial_generic_register(debug);
1140 if (result < 0) {
1141 err("%s - registering generic driver failed", __FUNCTION__);
1142 goto exit_generic;
1143 }
1144
Greg Kroah-Hartman17a882f2005-06-20 21:15:16 -07001145 info(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146
1147 return result;
1148
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001149exit_generic:
1150 usb_deregister(&usb_serial_driver);
1151
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152exit_tty:
1153 tty_unregister_driver(usb_serial_tty_driver);
1154
1155exit_reg_driver:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 bus_unregister(&usb_serial_bus_type);
1157
1158exit_bus:
1159 err ("%s - returning with error %d", __FUNCTION__, result);
1160 put_tty_driver(usb_serial_tty_driver);
1161 return result;
1162}
1163
1164
1165static void __exit usb_serial_exit(void)
1166{
1167 usb_serial_console_exit();
1168
1169 usb_serial_generic_deregister();
1170
1171 usb_deregister(&usb_serial_driver);
1172 tty_unregister_driver(usb_serial_tty_driver);
1173 put_tty_driver(usb_serial_tty_driver);
1174 bus_unregister(&usb_serial_bus_type);
1175}
1176
1177
1178module_init(usb_serial_init);
1179module_exit(usb_serial_exit);
1180
1181#define set_to_generic_if_null(type, function) \
1182 do { \
1183 if (!type->function) { \
1184 type->function = usb_serial_generic_##function; \
1185 dbg("Had to override the " #function \
1186 " usb serial operation with the generic one.");\
1187 } \
1188 } while (0)
1189
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001190static void fixup_generic(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191{
1192 set_to_generic_if_null(device, open);
1193 set_to_generic_if_null(device, write);
1194 set_to_generic_if_null(device, close);
1195 set_to_generic_if_null(device, write_room);
1196 set_to_generic_if_null(device, chars_in_buffer);
1197 set_to_generic_if_null(device, read_bulk_callback);
1198 set_to_generic_if_null(device, write_bulk_callback);
1199 set_to_generic_if_null(device, shutdown);
1200}
1201
Oliver Neukum4b10f0f2007-01-13 07:31:27 +01001202int usb_serial_register(struct usb_serial_driver *driver) /* must be called with BKL held */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203{
1204 int retval;
1205
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001206 fixup_generic(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001208 if (!driver->description)
1209 driver->description = driver->driver.name;
1210
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 /* Add this device to our list of devices */
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001212 list_add(&driver->driver_list, &usb_serial_driver_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001214 retval = usb_serial_bus_register(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 if (retval) {
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001216 err("problem %d when registering driver %s", retval, driver->description);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001217 list_del(&driver->driver_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 }
1219 else
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001220 info("USB Serial support registered for %s", driver->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221
1222 return retval;
1223}
1224
1225
Oliver Neukum4b10f0f2007-01-13 07:31:27 +01001226void usb_serial_deregister(struct usb_serial_driver *device) /* must be called with BKL held */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227{
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001228 info("USB Serial deregistering driver %s", device->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229 list_del(&device->driver_list);
1230 usb_serial_bus_deregister(device);
1231}
1232
1233
1234
1235/* If the usb-serial core is built into the core, the usb-serial drivers
1236 need these symbols to load properly as modules. */
1237EXPORT_SYMBOL_GPL(usb_serial_register);
1238EXPORT_SYMBOL_GPL(usb_serial_deregister);
1239EXPORT_SYMBOL_GPL(usb_serial_probe);
1240EXPORT_SYMBOL_GPL(usb_serial_disconnect);
1241EXPORT_SYMBOL_GPL(usb_serial_port_softint);
1242
1243
1244/* Module information */
1245MODULE_AUTHOR( DRIVER_AUTHOR );
1246MODULE_DESCRIPTION( DRIVER_DESC );
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247MODULE_LICENSE("GPL");
1248
1249module_param(debug, bool, S_IRUGO | S_IWUSR);
1250MODULE_PARM_DESC(debug, "Debug enabled or not");