blob: 0c39b55aeef4f4ff75a1cf3827d833ab6e3314c8 [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 *
Alan Coxa8d6f0a2008-07-22 11:12:24 +010015 * See Documentation/usb/usb-serial.txt for more information on using this
16 * driver
Linus Torvalds1da177e2005-04-16 15:20:36 -070017 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 */
19
Linus Torvalds1da177e2005-04-16 15:20:36 -070020#include <linux/kernel.h>
21#include <linux/errno.h>
22#include <linux/init.h>
23#include <linux/slab.h>
Alexey Dobriyan405f5572009-07-11 22:08:37 +040024#include <linux/smp_lock.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <linux/tty.h>
26#include <linux/tty_driver.h>
27#include <linux/tty_flip.h>
28#include <linux/module.h>
29#include <linux/moduleparam.h>
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -070030#include <linux/seq_file.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <linux/spinlock.h>
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -030032#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/list.h>
Alan Coxa8d6f0a2008-07-22 11:12:24 +010034#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/usb.h>
Greg Kroah-Hartmana9698882006-07-11 21:22:58 -070036#include <linux/usb/serial.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include "pl2303.h"
38
39/*
40 * Version Information
41 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/"
43#define DRIVER_DESC "USB Serial Driver core"
44
Pete Zaitcev34f8e762006-06-21 15:00:45 -070045static void port_free(struct usb_serial_port *port);
46
Linus Torvalds1da177e2005-04-16 15:20:36 -070047/* Driver structure we register with the USB core */
48static struct usb_driver usb_serial_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070049 .name = "usbserial",
50 .probe = usb_serial_probe,
51 .disconnect = usb_serial_disconnect,
Oliver Neukumec225592007-04-27 20:54:57 +020052 .suspend = usb_serial_suspend,
53 .resume = usb_serial_resume,
Greg Kroah-Hartmanba9dc652005-11-16 13:41:28 -080054 .no_dynamic_id = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -070055};
56
57/* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead
58 the MODULE_DEVICE_TABLE declarations in each serial driver
59 cause the "hotplug" program to pull in whatever module is necessary
60 via modprobe, and modprobe will load usbserial because the serial
61 drivers depend on it.
62*/
63
64static int debug;
Alan Coxa8d6f0a2008-07-22 11:12:24 +010065/* initially all NULL */
66static struct usb_serial *serial_table[SERIAL_TTY_MINORS];
Oliver Neukum3ddad822007-07-24 15:13:42 +020067static DEFINE_MUTEX(table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070068static LIST_HEAD(usb_serial_driver_list);
69
70struct usb_serial *usb_serial_get_by_index(unsigned index)
71{
Oliver Neukum34ef50e2007-01-13 07:29:26 +010072 struct usb_serial *serial;
73
Oliver Neukum3ddad822007-07-24 15:13:42 +020074 mutex_lock(&table_lock);
Oliver Neukum34ef50e2007-01-13 07:29:26 +010075 serial = serial_table[index];
Linus Torvalds1da177e2005-04-16 15:20:36 -070076
77 if (serial)
78 kref_get(&serial->kref);
Oliver Neukum3ddad822007-07-24 15:13:42 +020079 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070080 return serial;
81}
82
Alan Coxa8d6f0a2008-07-22 11:12:24 +010083static struct usb_serial *get_free_serial(struct usb_serial *serial,
84 int num_ports, unsigned int *minor)
Linus Torvalds1da177e2005-04-16 15:20:36 -070085{
86 unsigned int i, j;
87 int good_spot;
88
Harvey Harrison441b62c2008-03-03 16:08:34 -080089 dbg("%s %d", __func__, num_ports);
Linus Torvalds1da177e2005-04-16 15:20:36 -070090
91 *minor = 0;
Oliver Neukum3ddad822007-07-24 15:13:42 +020092 mutex_lock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070093 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
94 if (serial_table[i])
95 continue;
96
97 good_spot = 1;
98 for (j = 1; j <= num_ports-1; ++j)
99 if ((i+j >= SERIAL_TTY_MINORS) || (serial_table[i+j])) {
100 good_spot = 0;
101 i += j;
102 break;
103 }
104 if (good_spot == 0)
105 continue;
106
107 *minor = i;
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100108 j = 0;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800109 dbg("%s - minor base = %d", __func__, *minor);
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100110 for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111 serial_table[i] = serial;
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100112 serial->port[j++]->number = i;
113 }
Oliver Neukum3ddad822007-07-24 15:13:42 +0200114 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115 return serial;
116 }
Oliver Neukum3ddad822007-07-24 15:13:42 +0200117 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 return NULL;
119}
120
121static void return_serial(struct usb_serial *serial)
122{
123 int i;
124
Harvey Harrison441b62c2008-03-03 16:08:34 -0800125 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100127 for (i = 0; i < serial->num_ports; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128 serial_table[serial->minor + i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129}
130
131static void destroy_serial(struct kref *kref)
132{
133 struct usb_serial *serial;
134 struct usb_serial_port *port;
135 int i;
136
137 serial = to_usb_serial(kref);
138
Harvey Harrison441b62c2008-03-03 16:08:34 -0800139 dbg("%s - %s", __func__, serial->type->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140
Jim Radford521b85a2007-03-13 08:30:50 -0700141 /* return the minor range that this device had */
Alan Stern0282b7f2008-07-29 12:01:04 -0400142 if (serial->minor != SERIAL_TTY_NO_MINOR)
143 return_serial(serial);
Jim Radford521b85a2007-03-13 08:30:50 -0700144
Alan Sternf9c99bb2009-06-02 11:53:55 -0400145 serial->type->release(serial);
146
147 for (i = 0; i < serial->num_ports; ++i) {
148 port = serial->port[i];
149 if (port)
150 put_device(&port->dev);
151 }
152
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153 /* 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) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100157 for (i = serial->num_ports;
158 i < serial->num_port_pointers; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 port = serial->port[i];
Alan Sternf9c99bb2009-06-02 11:53:55 -0400160 if (port)
161 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 */
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100168 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169}
170
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200171void usb_serial_put(struct usb_serial *serial)
172{
Oliver Neukum3ddad822007-07-24 15:13:42 +0200173 mutex_lock(&table_lock);
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200174 kref_put(&serial->kref, destroy_serial);
Oliver Neukum3ddad822007-07-24 15:13:42 +0200175 mutex_unlock(&table_lock);
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200176}
177
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178/*****************************************************************************
179 * Driver tty interface functions
180 *****************************************************************************/
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100181static int serial_open (struct tty_struct *tty, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182{
183 struct usb_serial *serial;
184 struct usb_serial_port *port;
185 unsigned int portNumber;
Alan Stern2d931482009-04-14 11:31:02 -0400186 int retval = 0;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100187
Harvey Harrison441b62c2008-03-03 16:08:34 -0800188 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189
190 /* get the serial object associated with this tty pointer */
191 serial = usb_serial_get_by_index(tty->index);
192 if (!serial) {
193 tty->driver_data = NULL;
194 return -ENODEV;
195 }
196
Alan Stern2d931482009-04-14 11:31:02 -0400197 mutex_lock(&serial->disc_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198 portNumber = tty->index - serial->minor;
199 port = serial->port[portNumber];
Alan Stern2d931482009-04-14 11:31:02 -0400200 if (!port || serial->disconnected)
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300201 retval = -ENODEV;
Alan Stern2d931482009-04-14 11:31:02 -0400202 else
203 get_device(&port->dev);
204 /*
205 * Note: Our locking order requirement does not allow port->mutex
206 * to be acquired while serial->disc_mutex is held.
207 */
208 mutex_unlock(&serial->disc_mutex);
209 if (retval)
210 goto bailout_serial_put;
James Woodcock331879f2009-02-11 15:06:53 +0000211
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300212 if (mutex_lock_interruptible(&port->mutex)) {
213 retval = -ERESTARTSYS;
Alan Stern2d931482009-04-14 11:31:02 -0400214 goto bailout_port_put;
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300215 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100216
Alan Cox95da3102008-07-22 11:09:07 +0100217 ++port->port.count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218
Paul Fulghumca854852006-04-13 22:28:17 +0200219 /* set up our port structure making the tty driver
220 * remember our port object, and us it */
221 tty->driver_data = port;
Alan Cox4a90f092008-10-13 10:39:46 +0100222 tty_port_tty_set(&port->port, tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223
Alan Cox95da3102008-07-22 11:09:07 +0100224 if (port->port.count == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225
226 /* lock this module before we call it
227 * this may fail, which means we must bail out,
228 * safe because we are called with BKL held */
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700229 if (!try_module_get(serial->type->driver.owner)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230 retval = -ENODEV;
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300231 goto bailout_mutex_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232 }
233
Alan Stern2d931482009-04-14 11:31:02 -0400234 mutex_lock(&serial->disc_mutex);
235 if (serial->disconnected)
236 retval = -ENODEV;
237 else
238 retval = usb_autopm_get_interface(serial->interface);
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800239 if (retval)
240 goto bailout_module_put;
Alan Stern2d931482009-04-14 11:31:02 -0400241
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100242 /* only call the device specific open if this
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 * is the first time the port is opened */
Alan Cox95da3102008-07-22 11:09:07 +0100244 retval = serial->type->open(tty, port, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245 if (retval)
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800246 goto bailout_interface_put;
Alan Stern2d931482009-04-14 11:31:02 -0400247 mutex_unlock(&serial->disc_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248 }
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300249 mutex_unlock(&port->mutex);
Alan Cox335f8512009-06-11 12:26:29 +0100250 /* Now do the correct tty layer semantics */
251 retval = tty_port_block_til_ready(&port->port, tty, filp);
252 if (retval == 0)
253 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800255bailout_interface_put:
256 usb_autopm_put_interface(serial->interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257bailout_module_put:
Alan Stern2d931482009-04-14 11:31:02 -0400258 mutex_unlock(&serial->disc_mutex);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700259 module_put(serial->type->driver.owner);
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300260bailout_mutex_unlock:
Alan Cox95da3102008-07-22 11:09:07 +0100261 port->port.count = 0;
Frank Gevaertsb059c812006-06-14 15:52:05 +0200262 tty->driver_data = NULL;
Alan Cox4a90f092008-10-13 10:39:46 +0100263 tty_port_tty_set(&port->port, NULL);
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300264 mutex_unlock(&port->mutex);
Alan Stern2d931482009-04-14 11:31:02 -0400265bailout_port_put:
266 put_device(&port->dev);
267bailout_serial_put:
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200268 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269 return retval;
270}
271
Alan Cox335f8512009-06-11 12:26:29 +0100272/**
273 * serial_do_down - shut down hardware
274 * @port: port to shut down
275 *
276 * Shut down a USB port unless it is the console. We never shut down the
277 * console hardware as it will always be in use.
278 *
279 * Don't free any resources at this point
280 */
281static void serial_do_down(struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282{
Alan Cox335f8512009-06-11 12:26:29 +0100283 struct usb_serial_driver *drv = port->serial->type;
Alan Stern2d931482009-04-14 11:31:02 -0400284 struct usb_serial *serial;
285 struct module *owner;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286
Alan Cox335f8512009-06-11 12:26:29 +0100287 /* The console is magical, do not hang up the console hardware
288 or there will be tears */
289 if (port->console)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 return;
291
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300292 mutex_lock(&port->mutex);
Alan Stern2d931482009-04-14 11:31:02 -0400293 serial = port->serial;
294 owner = serial->type->driver.owner;
Luiz Fernando Capitulino8a4613f2005-11-28 19:16:07 -0200295
Alan Cox335f8512009-06-11 12:26:29 +0100296 if (drv->close)
297 drv->close(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300299 mutex_unlock(&port->mutex);
Alan Cox335f8512009-06-11 12:26:29 +0100300}
301
302/**
303 * serial_do_free - free resources post close/hangup
304 * @port: port to free up
305 *
306 * Do the resource freeing and refcount dropping for the port. We must
307 * be careful about ordering and we must avoid freeing up the console.
308 */
309
310static void serial_do_free(struct usb_serial_port *port)
311{
312 struct usb_serial *serial;
313 struct module *owner;
314
315 /* The console is magical, do not hang up the console hardware
316 or there will be tears */
317 if (port->console)
318 return;
319
320 serial = port->serial;
321 owner = serial->type->driver.owner;
Alan Stern2d931482009-04-14 11:31:02 -0400322 put_device(&port->dev);
Alan Stern2d931482009-04-14 11:31:02 -0400323 /* Mustn't dereference port any more */
Alan Cox335f8512009-06-11 12:26:29 +0100324 mutex_lock(&serial->disc_mutex);
325 if (!serial->disconnected)
326 usb_autopm_put_interface(serial->interface);
327 mutex_unlock(&serial->disc_mutex);
Alan Stern2d931482009-04-14 11:31:02 -0400328 usb_serial_put(serial);
Alan Stern2d931482009-04-14 11:31:02 -0400329 /* Mustn't dereference serial any more */
Alan Cox335f8512009-06-11 12:26:29 +0100330 module_put(owner);
331}
332
333static void serial_close(struct tty_struct *tty, struct file *filp)
334{
335 struct usb_serial_port *port = tty->driver_data;
336
Thadeu Lima de Souza Cascardof4fa4462009-06-25 14:41:37 +0100337 if (!port)
338 return;
339
Alan Cox335f8512009-06-11 12:26:29 +0100340 dbg("%s - port %d", __func__, port->number);
341
342
343 if (tty_port_close_start(&port->port, tty, filp) == 0)
344 return;
345
346 serial_do_down(port);
347 tty_port_close_end(&port->port, tty);
348 tty_port_tty_set(&port->port, NULL);
349 serial_do_free(port);
350}
351
352static void serial_hangup(struct tty_struct *tty)
353{
354 struct usb_serial_port *port = tty->driver_data;
355 serial_do_down(port);
356 tty_port_hangup(&port->port);
357 serial_do_free(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358}
359
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100360static int serial_write(struct tty_struct *tty, const unsigned char *buf,
361 int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200363 struct usb_serial_port *port = tty->driver_data;
Oliver Neukum3ff4fd92007-01-13 07:32:27 +0100364 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365
Alan Coxf34d7a52008-04-30 00:54:13 -0700366 if (port->serial->dev->state == USB_STATE_NOTATTACHED)
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200367 goto exit;
368
Harvey Harrison441b62c2008-03-03 16:08:34 -0800369 dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370
Alan Cox95da3102008-07-22 11:09:07 +0100371 /* count is managed under the mutex lock for the tty so cannot
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100372 drop to zero until after the last close completes */
Alan Cox95da3102008-07-22 11:09:07 +0100373 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374
375 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100376 retval = port->serial->type->write(tty, port, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377
378exit:
379 return retval;
380}
381
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100382static int serial_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200384 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800385 dbg("%s - port %d", __func__, port->number);
Alan Cox95da3102008-07-22 11:09:07 +0100386 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100388 return port->serial->type->write_room(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389}
390
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100391static int serial_chars_in_buffer(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200393 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800394 dbg("%s = port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395
Alan Cox95da3102008-07-22 11:09:07 +0100396 WARN_ON(!port->port.count);
Alan Coxeff69372009-01-02 13:47:06 +0000397 /* if the device was unplugged then any remaining characters
398 fell out of the connector ;) */
399 if (port->serial->disconnected)
400 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100402 return port->serial->type->chars_in_buffer(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403}
404
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100405static void serial_throttle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200407 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800408 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409
Alan Cox95da3102008-07-22 11:09:07 +0100410 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 /* pass on to the driver specific version of this function */
412 if (port->serial->type->throttle)
Alan Cox95da3102008-07-22 11:09:07 +0100413 port->serial->type->throttle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414}
415
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100416static void serial_unthrottle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200418 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800419 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420
Alan Cox95da3102008-07-22 11:09:07 +0100421 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 /* pass on to the driver specific version of this function */
423 if (port->serial->type->unthrottle)
Alan Cox95da3102008-07-22 11:09:07 +0100424 port->serial->type->unthrottle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425}
426
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100427static int serial_ioctl(struct tty_struct *tty, struct file *file,
428 unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200430 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 int retval = -ENODEV;
432
Harvey Harrison441b62c2008-03-03 16:08:34 -0800433 dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434
Alan Cox95da3102008-07-22 11:09:07 +0100435 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100437 /* pass on to the driver specific version of this function
438 if it is available */
Alan Coxf34d7a52008-04-30 00:54:13 -0700439 if (port->serial->type->ioctl) {
Alan Cox95da3102008-07-22 11:09:07 +0100440 retval = port->serial->type->ioctl(tty, file, cmd, arg);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100441 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 retval = -ENOIOCTLCMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 return retval;
444}
445
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100446static void serial_set_termios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200448 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800449 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450
Alan Cox95da3102008-07-22 11:09:07 +0100451 WARN_ON(!port->port.count);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100452 /* pass on to the driver specific version of this function
453 if it is available */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 if (port->serial->type->set_termios)
Alan Cox95da3102008-07-22 11:09:07 +0100455 port->serial->type->set_termios(tty, port, old);
Alan Cox33785092007-10-18 01:24:22 -0700456 else
457 tty_termios_copy_hw(tty->termios, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458}
459
Alan Cox9e989662008-07-22 11:18:03 +0100460static int serial_break(struct tty_struct *tty, int break_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200462 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463
Harvey Harrison441b62c2008-03-03 16:08:34 -0800464 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465
Alan Cox95da3102008-07-22 11:09:07 +0100466 WARN_ON(!port->port.count);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100467 /* pass on to the driver specific version of this function
468 if it is available */
Alan Cox6b447f042009-01-02 13:48:56 +0000469 if (port->serial->type->break_ctl)
Alan Cox95da3102008-07-22 11:09:07 +0100470 port->serial->type->break_ctl(tty, break_state);
Alan Cox9e989662008-07-22 11:18:03 +0100471 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472}
473
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700474static int serial_proc_show(struct seq_file *m, void *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475{
476 struct usb_serial *serial;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 char tmp[40];
479
Harvey Harrison441b62c2008-03-03 16:08:34 -0800480 dbg("%s", __func__);
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700481 seq_puts(m, "usbserinfo:1.0 driver:2.0\n");
482 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 serial = usb_serial_get_by_index(i);
484 if (serial == NULL)
485 continue;
486
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700487 seq_printf(m, "%d:", i);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700488 if (serial->type->driver.owner)
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700489 seq_printf(m, " module:%s",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100490 module_name(serial->type->driver.owner));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700491 seq_printf(m, " name:\"%s\"",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100492 serial->type->description);
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700493 seq_printf(m, " vendor:%04x product:%04x",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100494 le16_to_cpu(serial->dev->descriptor.idVendor),
495 le16_to_cpu(serial->dev->descriptor.idProduct));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700496 seq_printf(m, " num_ports:%d", serial->num_ports);
497 seq_printf(m, " port:%d", i - serial->minor + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 usb_make_path(serial->dev, tmp, sizeof(tmp));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700499 seq_printf(m, " path:%s", tmp);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100500
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700501 seq_putc(m, '\n');
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200502 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 }
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700504 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505}
506
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700507static int serial_proc_open(struct inode *inode, struct file *file)
508{
509 return single_open(file, serial_proc_show, NULL);
510}
511
512static const struct file_operations serial_proc_fops = {
513 .owner = THIS_MODULE,
514 .open = serial_proc_open,
515 .read = seq_read,
516 .llseek = seq_lseek,
517 .release = single_release,
518};
519
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100520static int serial_tiocmget(struct tty_struct *tty, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200522 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523
Harvey Harrison441b62c2008-03-03 16:08:34 -0800524 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525
Alan Cox95da3102008-07-22 11:09:07 +0100526 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 if (port->serial->type->tiocmget)
Alan Cox95da3102008-07-22 11:09:07 +0100528 return port->serial->type->tiocmget(tty, file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 return -EINVAL;
530}
531
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100532static int serial_tiocmset(struct tty_struct *tty, struct file *file,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533 unsigned int set, unsigned int clear)
534{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200535 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536
Harvey Harrison441b62c2008-03-03 16:08:34 -0800537 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538
Alan Cox95da3102008-07-22 11:09:07 +0100539 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 if (port->serial->type->tiocmset)
Alan Cox95da3102008-07-22 11:09:07 +0100541 return port->serial->type->tiocmset(tty, file, set, clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 return -EINVAL;
543}
544
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700545/*
546 * We would be calling tty_wakeup here, but unfortunately some line
547 * disciplines have an annoying habit of calling tty->write from
548 * the write wakeup callback (e.g. n_hdlc.c).
549 */
550void usb_serial_port_softint(struct usb_serial_port *port)
551{
552 schedule_work(&port->work);
553}
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100554EXPORT_SYMBOL_GPL(usb_serial_port_softint);
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700555
David Howellsc4028952006-11-22 14:57:56 +0000556static void usb_serial_port_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557{
David Howellsc4028952006-11-22 14:57:56 +0000558 struct usb_serial_port *port =
559 container_of(work, struct usb_serial_port, work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 struct tty_struct *tty;
561
Harvey Harrison441b62c2008-03-03 16:08:34 -0800562 dbg("%s - port %d", __func__, port->number);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100563
Alan Cox4a90f092008-10-13 10:39:46 +0100564 tty = tty_port_tty_get(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 if (!tty)
566 return;
567
568 tty_wakeup(tty);
Alan Cox4a90f092008-10-13 10:39:46 +0100569 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570}
571
572static void port_release(struct device *dev)
573{
574 struct usb_serial_port *port = to_usb_serial_port(dev);
575
Kay Sievers7071a3c2008-05-02 06:02:41 +0200576 dbg ("%s - %s", __func__, dev_name(dev));
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700577 port_free(port);
578}
579
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100580static void kill_traffic(struct usb_serial_port *port)
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700581{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 usb_kill_urb(port->write_urb);
Oliver Neukum5adceac2007-08-17 14:01:38 +0200584 /*
585 * This is tricky.
586 * Some drivers submit the read_urb in the
587 * handler for the write_urb or vice versa
588 * this order determines the order in which
589 * usb_kill_urb() must be used to reliably
590 * kill the URBs. As it is unknown here,
591 * both orders must be used in turn.
592 * The call below is not redundant.
593 */
594 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 usb_kill_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596 usb_kill_urb(port->interrupt_out_urb);
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100597}
598
599static void port_free(struct usb_serial_port *port)
600{
Alan Stern2d931482009-04-14 11:31:02 -0400601 /*
602 * Stop all the traffic before cancelling the work, so that
603 * nobody will restart it by calling usb_serial_port_softint.
604 */
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100605 kill_traffic(port);
Alan Stern2d931482009-04-14 11:31:02 -0400606 cancel_work_sync(&port->work);
607
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100608 usb_free_urb(port->read_urb);
609 usb_free_urb(port->write_urb);
610 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 usb_free_urb(port->interrupt_out_urb);
612 kfree(port->bulk_in_buffer);
613 kfree(port->bulk_out_buffer);
614 kfree(port->interrupt_in_buffer);
615 kfree(port->interrupt_out_buffer);
616 kfree(port);
617}
618
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100619static struct usb_serial *create_serial(struct usb_device *dev,
620 struct usb_interface *interface,
621 struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622{
623 struct usb_serial *serial;
624
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100625 serial = kzalloc(sizeof(*serial), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 if (!serial) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800627 dev_err(&dev->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 return NULL;
629 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 serial->dev = usb_get_dev(dev);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700631 serial->type = driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 serial->interface = interface;
633 kref_init(&serial->kref);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +0100634 mutex_init(&serial->disc_mutex);
Alan Stern0282b7f2008-07-29 12:01:04 -0400635 serial->minor = SERIAL_TTY_NO_MINOR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636
637 return serial;
638}
639
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100640static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf,
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100641 struct usb_serial_driver *drv)
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100642{
643 struct usb_dynid *dynid;
644
645 spin_lock(&drv->dynids.lock);
646 list_for_each_entry(dynid, &drv->dynids.list, node) {
647 if (usb_match_one_id(intf, &dynid->id)) {
648 spin_unlock(&drv->dynids.lock);
649 return &dynid->id;
650 }
651 }
652 spin_unlock(&drv->dynids.lock);
653 return NULL;
654}
655
656static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv,
657 struct usb_interface *intf)
658{
659 const struct usb_device_id *id;
660
661 id = usb_match_id(intf, drv->id_table);
662 if (id) {
663 dbg("static descriptor matches");
664 goto exit;
665 }
666 id = match_dynamic_id(intf, drv);
667 if (id)
668 dbg("dynamic descriptor matches");
669exit:
670 return id;
671}
672
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100673static struct usb_serial_driver *search_serial_device(
674 struct usb_interface *iface)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676 const struct usb_device_id *id;
Alan Stern063a2da2007-10-10 16:24:06 -0400677 struct usb_serial_driver *drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678
Adrian Bunk93b1fae2006-01-10 00:13:33 +0100679 /* Check if the usb id matches a known device */
Alan Stern063a2da2007-10-10 16:24:06 -0400680 list_for_each_entry(drv, &usb_serial_driver_list, driver_list) {
681 id = get_iface_id(drv, iface);
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100682 if (id)
Alan Stern063a2da2007-10-10 16:24:06 -0400683 return drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 }
685
686 return NULL;
687}
688
Alan Cox335f8512009-06-11 12:26:29 +0100689static int serial_carrier_raised(struct tty_port *port)
690{
691 struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
692 struct usb_serial_driver *drv = p->serial->type;
693 if (drv->carrier_raised)
694 return drv->carrier_raised(p);
695 /* No carrier control - don't block */
696 return 1;
697}
698
699static void serial_dtr_rts(struct tty_port *port, int on)
700{
701 struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
702 struct usb_serial_driver *drv = p->serial->type;
703 if (drv->dtr_rts)
704 drv->dtr_rts(p, on);
705}
706
707static const struct tty_port_operations serial_port_ops = {
708 .carrier_raised = serial_carrier_raised,
709 .dtr_rts = serial_dtr_rts,
710};
711
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712int usb_serial_probe(struct usb_interface *interface,
713 const struct usb_device_id *id)
714{
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100715 struct usb_device *dev = interface_to_usbdev(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716 struct usb_serial *serial = NULL;
717 struct usb_serial_port *port;
718 struct usb_host_interface *iface_desc;
719 struct usb_endpoint_descriptor *endpoint;
720 struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS];
721 struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS];
722 struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];
723 struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700724 struct usb_serial_driver *type = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 int retval;
Andre Hauptdd9ca5d2008-06-18 15:56:00 +0200726 unsigned int minor;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 int buffer_size;
728 int i;
729 int num_interrupt_in = 0;
730 int num_interrupt_out = 0;
731 int num_bulk_in = 0;
732 int num_bulk_out = 0;
733 int num_ports = 0;
734 int max_endpoints;
735
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100736 lock_kernel(); /* guard against unloading a serial driver module */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 type = search_serial_device(interface);
738 if (!type) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100739 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 dbg("none matched");
741 return -ENODEV;
742 }
743
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100744 serial = create_serial(dev, interface, type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 if (!serial) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100746 unlock_kernel();
Harvey Harrison441b62c2008-03-03 16:08:34 -0800747 dev_err(&interface->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 return -ENOMEM;
749 }
750
751 /* if this device type has a probe function, call it */
752 if (type->probe) {
753 const struct usb_device_id *id;
754
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700755 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100756 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100757 dev_err(&interface->dev,
758 "module get failed, exiting\n");
759 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 return -EIO;
761 }
762
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100763 id = get_iface_id(type, interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 retval = type->probe(serial, id);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700765 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766
767 if (retval) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100768 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100769 dbg("sub driver rejected device");
770 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 return retval;
772 }
773 }
774
775 /* descriptor matches, let's find the endpoints needed */
776 /* check out the endpoints */
777 iface_desc = interface->cur_altsetting;
778 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
779 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700780
781 if (usb_endpoint_is_bulk_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782 /* we found a bulk in endpoint */
783 dbg("found bulk in on endpoint %d", i);
784 bulk_in_endpoint[num_bulk_in] = endpoint;
785 ++num_bulk_in;
786 }
787
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700788 if (usb_endpoint_is_bulk_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 /* we found a bulk out endpoint */
790 dbg("found bulk out on endpoint %d", i);
791 bulk_out_endpoint[num_bulk_out] = endpoint;
792 ++num_bulk_out;
793 }
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700794
795 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796 /* we found a interrupt in endpoint */
797 dbg("found interrupt in on endpoint %d", i);
798 interrupt_in_endpoint[num_interrupt_in] = endpoint;
799 ++num_interrupt_in;
800 }
801
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700802 if (usb_endpoint_is_int_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 /* we found an interrupt out endpoint */
804 dbg("found interrupt out on endpoint %d", i);
805 interrupt_out_endpoint[num_interrupt_out] = endpoint;
806 ++num_interrupt_out;
807 }
808 }
809
810#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100811 /* BEGIN HORRIBLE HACK FOR PL2303 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 /* this is needed due to the looney way its endpoints are set up */
813 if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&
814 (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||
815 ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) &&
Johannes Steingraeber8fd80132006-09-16 16:17:34 +0200816 (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) ||
817 ((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) &&
Andreas Bombece816cf2008-09-14 01:58:55 +0200818 (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID)) ||
819 ((le16_to_cpu(dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) &&
820 (le16_to_cpu(dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_EF81))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 if (interface != dev->actconfig->interface[0]) {
822 /* check out the endpoints of the other interface*/
823 iface_desc = dev->actconfig->interface[0]->cur_altsetting;
824 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
825 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700826 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 /* we found a interrupt in endpoint */
828 dbg("found interrupt in for Prolific device on separate interface");
829 interrupt_in_endpoint[num_interrupt_in] = endpoint;
830 ++num_interrupt_in;
831 }
832 }
833 }
834
835 /* Now make sure the PL-2303 is configured correctly.
836 * If not, give up now and hope this hack will work
837 * properly during a later invocation of usb_serial_probe
838 */
839 if (num_bulk_in == 0 || num_bulk_out == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100840 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841 dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100842 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 return -ENODEV;
844 }
845 }
846 /* END HORRIBLE HACK FOR PL2303 */
847#endif
848
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849#ifdef CONFIG_USB_SERIAL_GENERIC
850 if (type == &usb_serial_generic_device) {
851 num_ports = num_bulk_out;
852 if (num_ports == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100853 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100854 dev_err(&interface->dev,
855 "Generic device with no bulk out, not allowed.\n");
856 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857 return -EIO;
858 }
859 }
860#endif
861 if (!num_ports) {
862 /* if this device type has a calc_num_ports function, call it */
863 if (type->calc_num_ports) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700864 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100865 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100866 dev_err(&interface->dev,
867 "module get failed, exiting\n");
868 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 return -EIO;
870 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100871 num_ports = type->calc_num_ports(serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700872 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 }
874 if (!num_ports)
875 num_ports = type->num_ports;
876 }
877
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878 serial->num_ports = num_ports;
879 serial->num_bulk_in = num_bulk_in;
880 serial->num_bulk_out = num_bulk_out;
881 serial->num_interrupt_in = num_interrupt_in;
882 serial->num_interrupt_out = num_interrupt_out;
883
Alan Stern063a2da2007-10-10 16:24:06 -0400884 /* found all that we need */
885 dev_info(&interface->dev, "%s converter detected\n",
886 type->description);
887
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 /* create our ports, we need as many as the max endpoints */
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100889 /* we don't use num_ports here because some devices have more
890 endpoint pairs than ports */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 max_endpoints = max(num_bulk_in, num_bulk_out);
892 max_endpoints = max(max_endpoints, num_interrupt_in);
893 max_endpoints = max(max_endpoints, num_interrupt_out);
894 max_endpoints = max(max_endpoints, (int)serial->num_ports);
895 serial->num_port_pointers = max_endpoints;
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100896 unlock_kernel();
897
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100898 dbg("%s - setting up %d port structures for this device",
899 __func__, max_endpoints);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 for (i = 0; i < max_endpoints; ++i) {
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100901 port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 if (!port)
903 goto probe_error;
Alan Cox4a90f092008-10-13 10:39:46 +0100904 tty_port_init(&port->port);
Alan Cox335f8512009-06-11 12:26:29 +0100905 port->port.ops = &serial_port_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 port->serial = serial;
Greg Kroah-Hartman507ca9b2005-04-23 12:49:16 -0700907 spin_lock_init(&port->lock);
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300908 mutex_init(&port->mutex);
David Howellsc4028952006-11-22 14:57:56 +0000909 INIT_WORK(&port->work, usb_serial_port_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 serial->port[i] = port;
911 }
912
913 /* set up the endpoint information */
914 for (i = 0; i < num_bulk_in; ++i) {
915 endpoint = bulk_in_endpoint[i];
916 port = serial->port[i];
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100917 port->read_urb = usb_alloc_urb(0, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 if (!port->read_urb) {
919 dev_err(&interface->dev, "No free urbs available\n");
920 goto probe_error;
921 }
922 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
923 port->bulk_in_size = buffer_size;
924 port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100925 port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 if (!port->bulk_in_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100927 dev_err(&interface->dev,
928 "Couldn't allocate bulk_in_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 goto probe_error;
930 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100931 usb_fill_bulk_urb(port->read_urb, dev,
932 usb_rcvbulkpipe(dev,
933 endpoint->bEndpointAddress),
934 port->bulk_in_buffer, buffer_size,
935 serial->type->read_bulk_callback, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936 }
937
938 for (i = 0; i < num_bulk_out; ++i) {
939 endpoint = bulk_out_endpoint[i];
940 port = serial->port[i];
941 port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
942 if (!port->write_urb) {
943 dev_err(&interface->dev, "No free urbs available\n");
944 goto probe_error;
945 }
946 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
947 port->bulk_out_size = buffer_size;
948 port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100949 port->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 if (!port->bulk_out_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100951 dev_err(&interface->dev,
952 "Couldn't allocate bulk_out_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 goto probe_error;
954 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100955 usb_fill_bulk_urb(port->write_urb, dev,
956 usb_sndbulkpipe(dev,
957 endpoint->bEndpointAddress),
958 port->bulk_out_buffer, buffer_size,
959 serial->type->write_bulk_callback, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 }
961
962 if (serial->type->read_int_callback) {
963 for (i = 0; i < num_interrupt_in; ++i) {
964 endpoint = interrupt_in_endpoint[i];
965 port = serial->port[i];
966 port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
967 if (!port->interrupt_in_urb) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100968 dev_err(&interface->dev,
969 "No free urbs available\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 goto probe_error;
971 }
972 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100973 port->interrupt_in_endpointAddress =
974 endpoint->bEndpointAddress;
975 port->interrupt_in_buffer = kmalloc(buffer_size,
976 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 if (!port->interrupt_in_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100978 dev_err(&interface->dev,
979 "Couldn't allocate interrupt_in_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 goto probe_error;
981 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100982 usb_fill_int_urb(port->interrupt_in_urb, dev,
983 usb_rcvintpipe(dev,
984 endpoint->bEndpointAddress),
985 port->interrupt_in_buffer, buffer_size,
986 serial->type->read_int_callback, port,
987 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 }
989 } else if (num_interrupt_in) {
990 dbg("the device claims to support interrupt in transfers, but read_int_callback is not defined");
991 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100992
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 if (serial->type->write_int_callback) {
994 for (i = 0; i < num_interrupt_out; ++i) {
995 endpoint = interrupt_out_endpoint[i];
996 port = serial->port[i];
997 port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
998 if (!port->interrupt_out_urb) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100999 dev_err(&interface->dev,
1000 "No free urbs available\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 goto probe_error;
1002 }
1003 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
1004 port->interrupt_out_size = buffer_size;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001005 port->interrupt_out_endpointAddress =
1006 endpoint->bEndpointAddress;
1007 port->interrupt_out_buffer = kmalloc(buffer_size,
1008 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 if (!port->interrupt_out_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001010 dev_err(&interface->dev,
1011 "Couldn't allocate interrupt_out_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 goto probe_error;
1013 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001014 usb_fill_int_urb(port->interrupt_out_urb, dev,
1015 usb_sndintpipe(dev,
1016 endpoint->bEndpointAddress),
1017 port->interrupt_out_buffer, buffer_size,
1018 serial->type->write_int_callback, port,
1019 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 }
1021 } else if (num_interrupt_out) {
1022 dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined");
1023 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001024
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 /* if this device type has an attach function, call it */
1026 if (type->attach) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -07001027 if (!try_module_get(type->driver.owner)) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001028 dev_err(&interface->dev,
1029 "module get failed, exiting\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 goto probe_error;
1031 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001032 retval = type->attach(serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -07001033 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 if (retval < 0)
1035 goto probe_error;
1036 if (retval > 0) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001037 /* quietly accept this device, but don't bind to a
1038 serial port as it's about to disappear */
Alan Stern0a3c8542009-05-27 11:25:52 -04001039 serial->num_ports = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 goto exit;
1041 }
1042 }
1043
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001044 if (get_free_serial(serial, num_ports, &minor) == NULL) {
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001045 dev_err(&interface->dev, "No more free serial devices\n");
1046 goto probe_error;
1047 }
Oliver Neukumc744f992007-02-26 15:43:00 +01001048 serial->minor = minor;
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001049
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 /* register all of the individual ports with the driver core */
1051 for (i = 0; i < num_ports; ++i) {
1052 port = serial->port[i];
1053 port->dev.parent = &interface->dev;
1054 port->dev.driver = NULL;
1055 port->dev.bus = &usb_serial_bus_type;
1056 port->dev.release = &port_release;
1057
Kay Sievers0031a062008-05-02 06:02:41 +02001058 dev_set_name(&port->dev, "ttyUSB%d", port->number);
Kay Sievers7071a3c2008-05-02 06:02:41 +02001059 dbg ("%s - registering %s", __func__, dev_name(&port->dev));
Alan Sternc706ebd2009-06-02 11:54:11 -04001060 port->dev_state = PORT_REGISTERING;
Greg Kroah-Hartman13f4db92006-08-28 11:43:25 -07001061 retval = device_register(&port->dev);
Alan Sternc706ebd2009-06-02 11:54:11 -04001062 if (retval) {
Greg Kroah-Hartman13f4db92006-08-28 11:43:25 -07001063 dev_err(&port->dev, "Error registering port device, "
1064 "continuing\n");
Alan Sternc706ebd2009-06-02 11:54:11 -04001065 port->dev_state = PORT_UNREGISTERED;
1066 } else {
1067 port->dev_state = PORT_REGISTERED;
1068 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 }
1070
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001071 usb_serial_console_init(debug, minor);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072
1073exit:
1074 /* success */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001075 usb_set_intfdata(interface, serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 return 0;
1077
1078probe_error:
1079 for (i = 0; i < num_bulk_in; ++i) {
1080 port = serial->port[i];
1081 if (!port)
1082 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001083 usb_free_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 kfree(port->bulk_in_buffer);
1085 }
1086 for (i = 0; i < num_bulk_out; ++i) {
1087 port = serial->port[i];
1088 if (!port)
1089 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001090 usb_free_urb(port->write_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 kfree(port->bulk_out_buffer);
1092 }
1093 for (i = 0; i < num_interrupt_in; ++i) {
1094 port = serial->port[i];
1095 if (!port)
1096 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001097 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098 kfree(port->interrupt_in_buffer);
1099 }
1100 for (i = 0; i < num_interrupt_out; ++i) {
1101 port = serial->port[i];
1102 if (!port)
1103 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001104 usb_free_urb(port->interrupt_out_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105 kfree(port->interrupt_out_buffer);
1106 }
1107
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 /* free up any memory that we allocated */
1109 for (i = 0; i < serial->num_port_pointers; ++i)
1110 kfree(serial->port[i]);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001111 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 return -EIO;
1113}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001114EXPORT_SYMBOL_GPL(usb_serial_probe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115
1116void usb_serial_disconnect(struct usb_interface *interface)
1117{
1118 int i;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001119 struct usb_serial *serial = usb_get_intfdata(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 struct device *dev = &interface->dev;
1121 struct usb_serial_port *port;
1122
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +02001123 usb_serial_console_disconnect(serial);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001124 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001126 mutex_lock(&serial->disc_mutex);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001127 usb_set_intfdata(interface, NULL);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001128 /* must set a flag, to signal subdrivers */
1129 serial->disconnected = 1;
Alan Stern2d931482009-04-14 11:31:02 -04001130 mutex_unlock(&serial->disc_mutex);
1131
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001132 for (i = 0; i < serial->num_ports; ++i) {
1133 port = serial->port[i];
1134 if (port) {
Alan Cox4a90f092008-10-13 10:39:46 +01001135 struct tty_struct *tty = tty_port_tty_get(&port->port);
1136 if (tty) {
Alan Cox335f8512009-06-11 12:26:29 +01001137 /* The hangup will occur asynchronously but
1138 the object refcounts will sort out all the
1139 cleanup */
Alan Cox4a90f092008-10-13 10:39:46 +01001140 tty_hangup(tty);
1141 tty_kref_put(tty);
1142 }
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001143 kill_traffic(port);
Alan Stern2d931482009-04-14 11:31:02 -04001144 cancel_work_sync(&port->work);
Alan Sternc706ebd2009-06-02 11:54:11 -04001145 if (port->dev_state == PORT_REGISTERED) {
1146
1147 /* Make sure the port is bound so that the
1148 * driver's port_remove method is called.
1149 */
1150 if (!port->dev.driver) {
1151 int rc;
1152
1153 port->dev.driver =
1154 &serial->type->driver;
1155 rc = device_bind_driver(&port->dev);
1156 }
1157 port->dev_state = PORT_UNREGISTERING;
1158 device_del(&port->dev);
1159 port->dev_state = PORT_UNREGISTERED;
1160 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 }
Alan Sternf9c99bb2009-06-02 11:53:55 -04001163 serial->type->disconnect(serial);
Alan Stern2d931482009-04-14 11:31:02 -04001164
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001165 /* let the last holder of this object
1166 * cause it to be cleaned up */
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001167 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 dev_info(dev, "device disconnected\n");
1169}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001170EXPORT_SYMBOL_GPL(usb_serial_disconnect);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171
Oliver Neukumec225592007-04-27 20:54:57 +02001172int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
1173{
1174 struct usb_serial *serial = usb_get_intfdata(intf);
1175 struct usb_serial_port *port;
1176 int i, r = 0;
1177
Oliver Neukumf8bece82009-02-05 16:54:25 +01001178 serial->suspending = 1;
1179
Oliver Neukume31c1882007-07-23 08:58:39 +02001180 for (i = 0; i < serial->num_ports; ++i) {
1181 port = serial->port[i];
1182 if (port)
1183 kill_traffic(port);
Oliver Neukumec225592007-04-27 20:54:57 +02001184 }
1185
1186 if (serial->type->suspend)
Oliver Neukume31c1882007-07-23 08:58:39 +02001187 r = serial->type->suspend(serial, message);
Oliver Neukumec225592007-04-27 20:54:57 +02001188
1189 return r;
1190}
1191EXPORT_SYMBOL(usb_serial_suspend);
1192
1193int usb_serial_resume(struct usb_interface *intf)
1194{
1195 struct usb_serial *serial = usb_get_intfdata(intf);
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001196 int rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001197
Oliver Neukumf8bece82009-02-05 16:54:25 +01001198 serial->suspending = 0;
Sarah Sharp8abaee22007-10-25 10:58:43 -07001199 if (serial->type->resume)
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001200 rv = serial->type->resume(serial);
1201 else
1202 rv = usb_serial_generic_resume(serial);
Oliver Neukumf8bece82009-02-05 16:54:25 +01001203
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001204 return rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001205}
1206EXPORT_SYMBOL(usb_serial_resume);
1207
Jeff Dikeb68e31d2006-10-02 02:17:18 -07001208static const struct tty_operations serial_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 .open = serial_open,
1210 .close = serial_close,
1211 .write = serial_write,
Alan Cox335f8512009-06-11 12:26:29 +01001212 .hangup = serial_hangup,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 .write_room = serial_write_room,
1214 .ioctl = serial_ioctl,
1215 .set_termios = serial_set_termios,
1216 .throttle = serial_throttle,
1217 .unthrottle = serial_unthrottle,
1218 .break_ctl = serial_break,
1219 .chars_in_buffer = serial_chars_in_buffer,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 .tiocmget = serial_tiocmget,
1221 .tiocmset = serial_tiocmset,
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -07001222 .proc_fops = &serial_proc_fops,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223};
1224
Alan Cox335f8512009-06-11 12:26:29 +01001225
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226struct tty_driver *usb_serial_tty_driver;
1227
1228static int __init usb_serial_init(void)
1229{
1230 int i;
1231 int result;
1232
1233 usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS);
1234 if (!usb_serial_tty_driver)
1235 return -ENOMEM;
1236
1237 /* Initialize our global data */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001238 for (i = 0; i < SERIAL_TTY_MINORS; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239 serial_table[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240
1241 result = bus_register(&usb_serial_bus_type);
1242 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001243 printk(KERN_ERR "usb-serial: %s - registering bus driver "
1244 "failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245 goto exit_bus;
1246 }
1247
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248 usb_serial_tty_driver->owner = THIS_MODULE;
1249 usb_serial_tty_driver->driver_name = "usbserial";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250 usb_serial_tty_driver->name = "ttyUSB";
1251 usb_serial_tty_driver->major = SERIAL_TTY_MAJOR;
1252 usb_serial_tty_driver->minor_start = 0;
1253 usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
1254 usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001255 usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW |
1256 TTY_DRIVER_DYNAMIC_DEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257 usb_serial_tty_driver->init_termios = tty_std_termios;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001258 usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD
1259 | HUPCL | CLOCAL;
Alan Coxa5b6f602008-04-08 17:16:06 +01001260 usb_serial_tty_driver->init_termios.c_ispeed = 9600;
1261 usb_serial_tty_driver->init_termios.c_ospeed = 9600;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262 tty_set_operations(usb_serial_tty_driver, &serial_ops);
1263 result = tty_register_driver(usb_serial_tty_driver);
1264 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001265 printk(KERN_ERR "usb-serial: %s - tty_register_driver failed\n",
1266 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267 goto exit_reg_driver;
1268 }
1269
1270 /* register the USB driver */
1271 result = usb_register(&usb_serial_driver);
1272 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001273 printk(KERN_ERR "usb-serial: %s - usb_register failed\n",
1274 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275 goto exit_tty;
1276 }
1277
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001278 /* register the generic driver, if we should */
1279 result = usb_serial_generic_register(debug);
1280 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001281 printk(KERN_ERR "usb-serial: %s - registering generic "
1282 "driver failed\n", __func__);
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001283 goto exit_generic;
1284 }
1285
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001286 printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287
1288 return result;
1289
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001290exit_generic:
1291 usb_deregister(&usb_serial_driver);
1292
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293exit_tty:
1294 tty_unregister_driver(usb_serial_tty_driver);
1295
1296exit_reg_driver:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297 bus_unregister(&usb_serial_bus_type);
1298
1299exit_bus:
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001300 printk(KERN_ERR "usb-serial: %s - returning with error %d\n",
1301 __func__, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302 put_tty_driver(usb_serial_tty_driver);
1303 return result;
1304}
1305
1306
1307static void __exit usb_serial_exit(void)
1308{
1309 usb_serial_console_exit();
1310
1311 usb_serial_generic_deregister();
1312
1313 usb_deregister(&usb_serial_driver);
1314 tty_unregister_driver(usb_serial_tty_driver);
1315 put_tty_driver(usb_serial_tty_driver);
1316 bus_unregister(&usb_serial_bus_type);
1317}
1318
1319
1320module_init(usb_serial_init);
1321module_exit(usb_serial_exit);
1322
1323#define set_to_generic_if_null(type, function) \
1324 do { \
1325 if (!type->function) { \
1326 type->function = usb_serial_generic_##function; \
1327 dbg("Had to override the " #function \
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001328 " usb serial operation with the generic one.");\
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329 } \
1330 } while (0)
1331
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001332static void fixup_generic(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333{
1334 set_to_generic_if_null(device, open);
1335 set_to_generic_if_null(device, write);
1336 set_to_generic_if_null(device, close);
1337 set_to_generic_if_null(device, write_room);
1338 set_to_generic_if_null(device, chars_in_buffer);
1339 set_to_generic_if_null(device, read_bulk_callback);
1340 set_to_generic_if_null(device, write_bulk_callback);
Alan Sternf9c99bb2009-06-02 11:53:55 -04001341 set_to_generic_if_null(device, disconnect);
1342 set_to_generic_if_null(device, release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343}
1344
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001345int usb_serial_register(struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001347 /* must be called with BKL held */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 int retval;
1349
Dave Younge4abe662009-02-14 21:21:13 +08001350 if (usb_disabled())
1351 return -ENODEV;
1352
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001353 fixup_generic(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001355 if (!driver->description)
1356 driver->description = driver->driver.name;
1357
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358 /* Add this device to our list of devices */
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001359 list_add(&driver->driver_list, &usb_serial_driver_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001361 retval = usb_serial_bus_register(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362 if (retval) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001363 printk(KERN_ERR "usb-serial: problem %d when registering "
1364 "driver %s\n", retval, driver->description);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001365 list_del(&driver->driver_list);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001366 } else
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001367 printk(KERN_INFO "USB Serial support registered for %s\n",
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001368 driver->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369
1370 return retval;
1371}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001372EXPORT_SYMBOL_GPL(usb_serial_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373
1374
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001375void usb_serial_deregister(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001377 /* must be called with BKL held */
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001378 printk(KERN_INFO "USB Serial deregistering driver %s\n",
1379 device->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380 list_del(&device->driver_list);
1381 usb_serial_bus_deregister(device);
1382}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383EXPORT_SYMBOL_GPL(usb_serial_deregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384
1385/* Module information */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001386MODULE_AUTHOR(DRIVER_AUTHOR);
1387MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388MODULE_LICENSE("GPL");
1389
1390module_param(debug, bool, S_IRUGO | S_IWUSR);
1391MODULE_PARM_DESC(debug, "Debug enabled or not");