blob: 80c1f4d8e910804b33fe10226b94ed85b5c6b52e [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>
Alan Coxc56d3002009-07-28 00:34:58 +010035#include <linux/serial.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#include <linux/usb.h>
Greg Kroah-Hartmana9698882006-07-11 21:22:58 -070037#include <linux/usb/serial.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070038#include "pl2303.h"
39
40/*
41 * Version Information
42 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/"
44#define DRIVER_DESC "USB Serial Driver core"
45
Pete Zaitcev34f8e762006-06-21 15:00:45 -070046static void port_free(struct usb_serial_port *port);
47
Linus Torvalds1da177e2005-04-16 15:20:36 -070048/* Driver structure we register with the USB core */
49static struct usb_driver usb_serial_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070050 .name = "usbserial",
51 .probe = usb_serial_probe,
52 .disconnect = usb_serial_disconnect,
Oliver Neukumec225592007-04-27 20:54:57 +020053 .suspend = usb_serial_suspend,
54 .resume = usb_serial_resume,
Greg Kroah-Hartmanba9dc652005-11-16 13:41:28 -080055 .no_dynamic_id = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -070056};
57
58/* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead
59 the MODULE_DEVICE_TABLE declarations in each serial driver
60 cause the "hotplug" program to pull in whatever module is necessary
61 via modprobe, and modprobe will load usbserial because the serial
62 drivers depend on it.
63*/
64
65static int debug;
Alan Coxa8d6f0a2008-07-22 11:12:24 +010066/* initially all NULL */
67static struct usb_serial *serial_table[SERIAL_TTY_MINORS];
Oliver Neukum3ddad822007-07-24 15:13:42 +020068static DEFINE_MUTEX(table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070069static LIST_HEAD(usb_serial_driver_list);
70
71struct usb_serial *usb_serial_get_by_index(unsigned index)
72{
Oliver Neukum34ef50e2007-01-13 07:29:26 +010073 struct usb_serial *serial;
74
Oliver Neukum3ddad822007-07-24 15:13:42 +020075 mutex_lock(&table_lock);
Oliver Neukum34ef50e2007-01-13 07:29:26 +010076 serial = serial_table[index];
Linus Torvalds1da177e2005-04-16 15:20:36 -070077
78 if (serial)
79 kref_get(&serial->kref);
Oliver Neukum3ddad822007-07-24 15:13:42 +020080 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070081 return serial;
82}
83
Alan Coxa8d6f0a2008-07-22 11:12:24 +010084static struct usb_serial *get_free_serial(struct usb_serial *serial,
85 int num_ports, unsigned int *minor)
Linus Torvalds1da177e2005-04-16 15:20:36 -070086{
87 unsigned int i, j;
88 int good_spot;
89
Harvey Harrison441b62c2008-03-03 16:08:34 -080090 dbg("%s %d", __func__, num_ports);
Linus Torvalds1da177e2005-04-16 15:20:36 -070091
92 *minor = 0;
Oliver Neukum3ddad822007-07-24 15:13:42 +020093 mutex_lock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070094 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
95 if (serial_table[i])
96 continue;
97
98 good_spot = 1;
99 for (j = 1; j <= num_ports-1; ++j)
100 if ((i+j >= SERIAL_TTY_MINORS) || (serial_table[i+j])) {
101 good_spot = 0;
102 i += j;
103 break;
104 }
105 if (good_spot == 0)
106 continue;
107
108 *minor = i;
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100109 j = 0;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800110 dbg("%s - minor base = %d", __func__, *minor);
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100111 for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 serial_table[i] = serial;
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100113 serial->port[j++]->number = i;
114 }
Oliver Neukum3ddad822007-07-24 15:13:42 +0200115 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116 return serial;
117 }
Oliver Neukum3ddad822007-07-24 15:13:42 +0200118 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119 return NULL;
120}
121
122static void return_serial(struct usb_serial *serial)
123{
124 int i;
125
Harvey Harrison441b62c2008-03-03 16:08:34 -0800126 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100128 for (i = 0; i < serial->num_ports; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129 serial_table[serial->minor + i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130}
131
132static void destroy_serial(struct kref *kref)
133{
134 struct usb_serial *serial;
135 struct usb_serial_port *port;
136 int i;
137
138 serial = to_usb_serial(kref);
139
Harvey Harrison441b62c2008-03-03 16:08:34 -0800140 dbg("%s - %s", __func__, serial->type->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141
Jim Radford521b85a2007-03-13 08:30:50 -0700142 /* return the minor range that this device had */
Alan Stern0282b7f2008-07-29 12:01:04 -0400143 if (serial->minor != SERIAL_TTY_NO_MINOR)
144 return_serial(serial);
Jim Radford521b85a2007-03-13 08:30:50 -0700145
Alan Sternf9c99bb2009-06-02 11:53:55 -0400146 serial->type->release(serial);
147
148 for (i = 0; i < serial->num_ports; ++i) {
149 port = serial->port[i];
150 if (port)
151 put_device(&port->dev);
152 }
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) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100158 for (i = serial->num_ports;
159 i < serial->num_port_pointers; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160 port = serial->port[i];
Alan Sternf9c99bb2009-06-02 11:53:55 -0400161 if (port)
162 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 */
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100169 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170}
171
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200172void usb_serial_put(struct usb_serial *serial)
173{
Oliver Neukum3ddad822007-07-24 15:13:42 +0200174 mutex_lock(&table_lock);
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200175 kref_put(&serial->kref, destroy_serial);
Oliver Neukum3ddad822007-07-24 15:13:42 +0200176 mutex_unlock(&table_lock);
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200177}
178
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179/*****************************************************************************
180 * Driver tty interface functions
181 *****************************************************************************/
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100182static int serial_open (struct tty_struct *tty, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183{
184 struct usb_serial *serial;
185 struct usb_serial_port *port;
186 unsigned int portNumber;
Alan Stern2d931482009-04-14 11:31:02 -0400187 int retval = 0;
Alan Coxc56d3002009-07-28 00:34:58 +0100188 int first = 0;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100189
Harvey Harrison441b62c2008-03-03 16:08:34 -0800190 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191
192 /* get the serial object associated with this tty pointer */
193 serial = usb_serial_get_by_index(tty->index);
194 if (!serial) {
195 tty->driver_data = NULL;
196 return -ENODEV;
197 }
198
Alan Stern2d931482009-04-14 11:31:02 -0400199 mutex_lock(&serial->disc_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 portNumber = tty->index - serial->minor;
201 port = serial->port[portNumber];
Alan Stern2d931482009-04-14 11:31:02 -0400202 if (!port || serial->disconnected)
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300203 retval = -ENODEV;
Alan Stern2d931482009-04-14 11:31:02 -0400204 else
205 get_device(&port->dev);
206 /*
207 * Note: Our locking order requirement does not allow port->mutex
208 * to be acquired while serial->disc_mutex is held.
209 */
210 mutex_unlock(&serial->disc_mutex);
211 if (retval)
212 goto bailout_serial_put;
James Woodcock331879f2009-02-11 15:06:53 +0000213
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300214 if (mutex_lock_interruptible(&port->mutex)) {
215 retval = -ERESTARTSYS;
Alan Stern2d931482009-04-14 11:31:02 -0400216 goto bailout_port_put;
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300217 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100218
Alan Cox95da3102008-07-22 11:09:07 +0100219 ++port->port.count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220
Paul Fulghumca854852006-04-13 22:28:17 +0200221 /* set up our port structure making the tty driver
222 * remember our port object, and us it */
223 tty->driver_data = port;
Alan Cox4a90f092008-10-13 10:39:46 +0100224 tty_port_tty_set(&port->port, tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225
Jason Wessel6e406122009-06-22 11:32:20 -0500226 /* If the console is attached, the device is already open */
227 if (port->port.count == 1 && !port->console) {
Alan Coxc56d3002009-07-28 00:34:58 +0100228 first = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229 /* lock this module before we call it
230 * this may fail, which means we must bail out,
231 * safe because we are called with BKL held */
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700232 if (!try_module_get(serial->type->driver.owner)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 retval = -ENODEV;
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300234 goto bailout_mutex_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 }
236
Alan Stern2d931482009-04-14 11:31:02 -0400237 mutex_lock(&serial->disc_mutex);
238 if (serial->disconnected)
239 retval = -ENODEV;
240 else
241 retval = usb_autopm_get_interface(serial->interface);
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800242 if (retval)
243 goto bailout_module_put;
Alan Stern2d931482009-04-14 11:31:02 -0400244
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100245 /* only call the device specific open if this
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246 * is the first time the port is opened */
Alan Coxa509a7e2009-09-19 13:13:26 -0700247 retval = serial->type->open(tty, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248 if (retval)
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800249 goto bailout_interface_put;
Alan Stern2d931482009-04-14 11:31:02 -0400250 mutex_unlock(&serial->disc_mutex);
Alan Coxc56d3002009-07-28 00:34:58 +0100251 set_bit(ASYNCB_INITIALIZED, &port->port.flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 }
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300253 mutex_unlock(&port->mutex);
Alan Cox335f8512009-06-11 12:26:29 +0100254 /* Now do the correct tty layer semantics */
255 retval = tty_port_block_til_ready(&port->port, tty, filp);
Alan Coxc56d3002009-07-28 00:34:58 +0100256 if (retval == 0) {
257 if (!first)
258 usb_serial_put(serial);
Alan Cox335f8512009-06-11 12:26:29 +0100259 return 0;
Alan Coxc56d3002009-07-28 00:34:58 +0100260 }
261 mutex_lock(&port->mutex);
262 if (first == 0)
263 goto bailout_mutex_unlock;
264 /* Undo the initial port actions */
265 mutex_lock(&serial->disc_mutex);
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800266bailout_interface_put:
267 usb_autopm_put_interface(serial->interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268bailout_module_put:
Alan Stern2d931482009-04-14 11:31:02 -0400269 mutex_unlock(&serial->disc_mutex);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700270 module_put(serial->type->driver.owner);
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300271bailout_mutex_unlock:
Alan Cox95da3102008-07-22 11:09:07 +0100272 port->port.count = 0;
Frank Gevaertsb059c812006-06-14 15:52:05 +0200273 tty->driver_data = NULL;
Alan Cox4a90f092008-10-13 10:39:46 +0100274 tty_port_tty_set(&port->port, NULL);
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300275 mutex_unlock(&port->mutex);
Alan Stern2d931482009-04-14 11:31:02 -0400276bailout_port_put:
277 put_device(&port->dev);
278bailout_serial_put:
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200279 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 return retval;
281}
282
Alan Cox335f8512009-06-11 12:26:29 +0100283/**
284 * serial_do_down - shut down hardware
285 * @port: port to shut down
286 *
287 * Shut down a USB port unless it is the console. We never shut down the
288 * console hardware as it will always be in use.
289 *
290 * Don't free any resources at this point
291 */
292static void serial_do_down(struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293{
Alan Cox335f8512009-06-11 12:26:29 +0100294 struct usb_serial_driver *drv = port->serial->type;
Alan Stern2d931482009-04-14 11:31:02 -0400295 struct usb_serial *serial;
296 struct module *owner;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297
Alan Cox335f8512009-06-11 12:26:29 +0100298 /* The console is magical, do not hang up the console hardware
299 or there will be tears */
300 if (port->console)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301 return;
302
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300303 mutex_lock(&port->mutex);
Alan Stern2d931482009-04-14 11:31:02 -0400304 serial = port->serial;
305 owner = serial->type->driver.owner;
Luiz Fernando Capitulino8a4613f2005-11-28 19:16:07 -0200306
Alan Cox335f8512009-06-11 12:26:29 +0100307 if (drv->close)
308 drv->close(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300310 mutex_unlock(&port->mutex);
Alan Cox335f8512009-06-11 12:26:29 +0100311}
312
313/**
314 * serial_do_free - free resources post close/hangup
315 * @port: port to free up
316 *
317 * Do the resource freeing and refcount dropping for the port. We must
318 * be careful about ordering and we must avoid freeing up the console.
Alan Cox4455e342009-09-19 13:13:24 -0700319 *
320 * Called when the last tty kref is dropped.
Alan Cox335f8512009-06-11 12:26:29 +0100321 */
322
Alan Cox4455e342009-09-19 13:13:24 -0700323static void serial_do_free(struct tty_struct *tty)
Alan Cox335f8512009-06-11 12:26:29 +0100324{
Alan Cox4455e342009-09-19 13:13:24 -0700325 struct usb_serial_port *port = tty->driver_data;
Alan Cox335f8512009-06-11 12:26:29 +0100326 struct usb_serial *serial;
327 struct module *owner;
328
329 /* The console is magical, do not hang up the console hardware
330 or there will be tears */
Alan Cox4455e342009-09-19 13:13:24 -0700331 if (port == NULL || port->console)
Alan Cox335f8512009-06-11 12:26:29 +0100332 return;
333
334 serial = port->serial;
335 owner = serial->type->driver.owner;
Alan Stern2d931482009-04-14 11:31:02 -0400336 put_device(&port->dev);
Alan Stern2d931482009-04-14 11:31:02 -0400337 /* Mustn't dereference port any more */
Alan Cox335f8512009-06-11 12:26:29 +0100338 mutex_lock(&serial->disc_mutex);
339 if (!serial->disconnected)
340 usb_autopm_put_interface(serial->interface);
341 mutex_unlock(&serial->disc_mutex);
Alan Stern2d931482009-04-14 11:31:02 -0400342 usb_serial_put(serial);
Alan Stern2d931482009-04-14 11:31:02 -0400343 /* Mustn't dereference serial any more */
Alan Cox335f8512009-06-11 12:26:29 +0100344 module_put(owner);
345}
346
347static void serial_close(struct tty_struct *tty, struct file *filp)
348{
349 struct usb_serial_port *port = tty->driver_data;
350
Thadeu Lima de Souza Cascardof4fa4462009-06-25 14:41:37 +0100351 if (!port)
352 return;
353
Alan Cox335f8512009-06-11 12:26:29 +0100354 dbg("%s - port %d", __func__, port->number);
355
Alan Cox335f8512009-06-11 12:26:29 +0100356 if (tty_port_close_start(&port->port, tty, filp) == 0)
357 return;
Alan Cox335f8512009-06-11 12:26:29 +0100358 serial_do_down(port);
359 tty_port_close_end(&port->port, tty);
360 tty_port_tty_set(&port->port, NULL);
Alan Cox4455e342009-09-19 13:13:24 -0700361
Alan Cox335f8512009-06-11 12:26:29 +0100362}
363
364static void serial_hangup(struct tty_struct *tty)
365{
366 struct usb_serial_port *port = tty->driver_data;
367 serial_do_down(port);
368 tty_port_hangup(&port->port);
Alan Coxb68f2fb2009-07-27 10:58:08 +0100369 /* We must not free port yet - the USB serial layer depends on it's
370 continued existence */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371}
372
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100373static int serial_write(struct tty_struct *tty, const unsigned char *buf,
374 int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200376 struct usb_serial_port *port = tty->driver_data;
Oliver Neukum3ff4fd92007-01-13 07:32:27 +0100377 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378
Alan Coxf34d7a52008-04-30 00:54:13 -0700379 if (port->serial->dev->state == USB_STATE_NOTATTACHED)
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200380 goto exit;
381
Harvey Harrison441b62c2008-03-03 16:08:34 -0800382 dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383
Alan Cox95da3102008-07-22 11:09:07 +0100384 /* count is managed under the mutex lock for the tty so cannot
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100385 drop to zero until after the last close completes */
Alan Cox95da3102008-07-22 11:09:07 +0100386 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387
388 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100389 retval = port->serial->type->write(tty, port, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390
391exit:
392 return retval;
393}
394
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100395static int serial_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200397 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800398 dbg("%s - port %d", __func__, port->number);
Alan Cox95da3102008-07-22 11:09:07 +0100399 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100401 return port->serial->type->write_room(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402}
403
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100404static int serial_chars_in_buffer(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200406 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800407 dbg("%s = port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408
Alan Coxeff69372009-01-02 13:47:06 +0000409 /* if the device was unplugged then any remaining characters
410 fell out of the connector ;) */
411 if (port->serial->disconnected)
412 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100414 return port->serial->type->chars_in_buffer(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415}
416
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100417static void serial_throttle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200419 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800420 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421
Alan Cox95da3102008-07-22 11:09:07 +0100422 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 /* pass on to the driver specific version of this function */
424 if (port->serial->type->throttle)
Alan Cox95da3102008-07-22 11:09:07 +0100425 port->serial->type->throttle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426}
427
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100428static void serial_unthrottle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200430 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800431 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432
Alan Cox95da3102008-07-22 11:09:07 +0100433 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 /* pass on to the driver specific version of this function */
435 if (port->serial->type->unthrottle)
Alan Cox95da3102008-07-22 11:09:07 +0100436 port->serial->type->unthrottle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437}
438
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100439static int serial_ioctl(struct tty_struct *tty, struct file *file,
440 unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200442 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 int retval = -ENODEV;
444
Harvey Harrison441b62c2008-03-03 16:08:34 -0800445 dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446
Alan Cox95da3102008-07-22 11:09:07 +0100447 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100449 /* pass on to the driver specific version of this function
450 if it is available */
Alan Coxf34d7a52008-04-30 00:54:13 -0700451 if (port->serial->type->ioctl) {
Alan Cox95da3102008-07-22 11:09:07 +0100452 retval = port->serial->type->ioctl(tty, file, cmd, arg);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100453 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 retval = -ENOIOCTLCMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 return retval;
456}
457
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100458static void serial_set_termios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200460 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800461 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462
Alan Cox95da3102008-07-22 11:09:07 +0100463 WARN_ON(!port->port.count);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100464 /* pass on to the driver specific version of this function
465 if it is available */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 if (port->serial->type->set_termios)
Alan Cox95da3102008-07-22 11:09:07 +0100467 port->serial->type->set_termios(tty, port, old);
Alan Cox33785092007-10-18 01:24:22 -0700468 else
469 tty_termios_copy_hw(tty->termios, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470}
471
Alan Cox9e989662008-07-22 11:18:03 +0100472static int serial_break(struct tty_struct *tty, int break_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200474 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475
Harvey Harrison441b62c2008-03-03 16:08:34 -0800476 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477
Alan Cox95da3102008-07-22 11:09:07 +0100478 WARN_ON(!port->port.count);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100479 /* pass on to the driver specific version of this function
480 if it is available */
Alan Cox6b447f042009-01-02 13:48:56 +0000481 if (port->serial->type->break_ctl)
Alan Cox95da3102008-07-22 11:09:07 +0100482 port->serial->type->break_ctl(tty, break_state);
Alan Cox9e989662008-07-22 11:18:03 +0100483 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484}
485
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700486static int serial_proc_show(struct seq_file *m, void *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487{
488 struct usb_serial *serial;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 char tmp[40];
491
Harvey Harrison441b62c2008-03-03 16:08:34 -0800492 dbg("%s", __func__);
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700493 seq_puts(m, "usbserinfo:1.0 driver:2.0\n");
494 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 serial = usb_serial_get_by_index(i);
496 if (serial == NULL)
497 continue;
498
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700499 seq_printf(m, "%d:", i);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700500 if (serial->type->driver.owner)
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700501 seq_printf(m, " module:%s",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100502 module_name(serial->type->driver.owner));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700503 seq_printf(m, " name:\"%s\"",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100504 serial->type->description);
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700505 seq_printf(m, " vendor:%04x product:%04x",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100506 le16_to_cpu(serial->dev->descriptor.idVendor),
507 le16_to_cpu(serial->dev->descriptor.idProduct));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700508 seq_printf(m, " num_ports:%d", serial->num_ports);
509 seq_printf(m, " port:%d", i - serial->minor + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 usb_make_path(serial->dev, tmp, sizeof(tmp));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700511 seq_printf(m, " path:%s", tmp);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100512
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700513 seq_putc(m, '\n');
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200514 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 }
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700516 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517}
518
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700519static int serial_proc_open(struct inode *inode, struct file *file)
520{
521 return single_open(file, serial_proc_show, NULL);
522}
523
524static const struct file_operations serial_proc_fops = {
525 .owner = THIS_MODULE,
526 .open = serial_proc_open,
527 .read = seq_read,
528 .llseek = seq_lseek,
529 .release = single_release,
530};
531
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100532static int serial_tiocmget(struct tty_struct *tty, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200534 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535
Harvey Harrison441b62c2008-03-03 16:08:34 -0800536 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537
Alan Cox95da3102008-07-22 11:09:07 +0100538 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 if (port->serial->type->tiocmget)
Alan Cox95da3102008-07-22 11:09:07 +0100540 return port->serial->type->tiocmget(tty, file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 return -EINVAL;
542}
543
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100544static int serial_tiocmset(struct tty_struct *tty, struct file *file,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 unsigned int set, unsigned int clear)
546{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200547 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548
Harvey Harrison441b62c2008-03-03 16:08:34 -0800549 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550
Alan Cox95da3102008-07-22 11:09:07 +0100551 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 if (port->serial->type->tiocmset)
Alan Cox95da3102008-07-22 11:09:07 +0100553 return port->serial->type->tiocmset(tty, file, set, clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 return -EINVAL;
555}
556
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700557/*
558 * We would be calling tty_wakeup here, but unfortunately some line
559 * disciplines have an annoying habit of calling tty->write from
560 * the write wakeup callback (e.g. n_hdlc.c).
561 */
562void usb_serial_port_softint(struct usb_serial_port *port)
563{
564 schedule_work(&port->work);
565}
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100566EXPORT_SYMBOL_GPL(usb_serial_port_softint);
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700567
David Howellsc4028952006-11-22 14:57:56 +0000568static void usb_serial_port_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569{
David Howellsc4028952006-11-22 14:57:56 +0000570 struct usb_serial_port *port =
571 container_of(work, struct usb_serial_port, work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572 struct tty_struct *tty;
573
Harvey Harrison441b62c2008-03-03 16:08:34 -0800574 dbg("%s - port %d", __func__, port->number);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100575
Alan Cox4a90f092008-10-13 10:39:46 +0100576 tty = tty_port_tty_get(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 if (!tty)
578 return;
579
580 tty_wakeup(tty);
Alan Cox4a90f092008-10-13 10:39:46 +0100581 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582}
583
584static void port_release(struct device *dev)
585{
586 struct usb_serial_port *port = to_usb_serial_port(dev);
587
Kay Sievers7071a3c2008-05-02 06:02:41 +0200588 dbg ("%s - %s", __func__, dev_name(dev));
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700589 port_free(port);
590}
591
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100592static void kill_traffic(struct usb_serial_port *port)
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700593{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 usb_kill_urb(port->write_urb);
Oliver Neukum5adceac2007-08-17 14:01:38 +0200596 /*
597 * This is tricky.
598 * Some drivers submit the read_urb in the
599 * handler for the write_urb or vice versa
600 * this order determines the order in which
601 * usb_kill_urb() must be used to reliably
602 * kill the URBs. As it is unknown here,
603 * both orders must be used in turn.
604 * The call below is not redundant.
605 */
606 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 usb_kill_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 usb_kill_urb(port->interrupt_out_urb);
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100609}
610
611static void port_free(struct usb_serial_port *port)
612{
Alan Stern2d931482009-04-14 11:31:02 -0400613 /*
614 * Stop all the traffic before cancelling the work, so that
615 * nobody will restart it by calling usb_serial_port_softint.
616 */
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100617 kill_traffic(port);
Alan Stern2d931482009-04-14 11:31:02 -0400618 cancel_work_sync(&port->work);
619
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100620 usb_free_urb(port->read_urb);
621 usb_free_urb(port->write_urb);
622 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 usb_free_urb(port->interrupt_out_urb);
624 kfree(port->bulk_in_buffer);
625 kfree(port->bulk_out_buffer);
626 kfree(port->interrupt_in_buffer);
627 kfree(port->interrupt_out_buffer);
628 kfree(port);
629}
630
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100631static struct usb_serial *create_serial(struct usb_device *dev,
632 struct usb_interface *interface,
633 struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634{
635 struct usb_serial *serial;
636
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100637 serial = kzalloc(sizeof(*serial), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 if (!serial) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800639 dev_err(&dev->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 return NULL;
641 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642 serial->dev = usb_get_dev(dev);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700643 serial->type = driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644 serial->interface = interface;
645 kref_init(&serial->kref);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +0100646 mutex_init(&serial->disc_mutex);
Alan Stern0282b7f2008-07-29 12:01:04 -0400647 serial->minor = SERIAL_TTY_NO_MINOR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648
649 return serial;
650}
651
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100652static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf,
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100653 struct usb_serial_driver *drv)
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100654{
655 struct usb_dynid *dynid;
656
657 spin_lock(&drv->dynids.lock);
658 list_for_each_entry(dynid, &drv->dynids.list, node) {
659 if (usb_match_one_id(intf, &dynid->id)) {
660 spin_unlock(&drv->dynids.lock);
661 return &dynid->id;
662 }
663 }
664 spin_unlock(&drv->dynids.lock);
665 return NULL;
666}
667
668static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv,
669 struct usb_interface *intf)
670{
671 const struct usb_device_id *id;
672
673 id = usb_match_id(intf, drv->id_table);
674 if (id) {
675 dbg("static descriptor matches");
676 goto exit;
677 }
678 id = match_dynamic_id(intf, drv);
679 if (id)
680 dbg("dynamic descriptor matches");
681exit:
682 return id;
683}
684
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100685static struct usb_serial_driver *search_serial_device(
686 struct usb_interface *iface)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688 const struct usb_device_id *id;
Alan Stern063a2da2007-10-10 16:24:06 -0400689 struct usb_serial_driver *drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690
Adrian Bunk93b1fae2006-01-10 00:13:33 +0100691 /* Check if the usb id matches a known device */
Alan Stern063a2da2007-10-10 16:24:06 -0400692 list_for_each_entry(drv, &usb_serial_driver_list, driver_list) {
693 id = get_iface_id(drv, iface);
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100694 if (id)
Alan Stern063a2da2007-10-10 16:24:06 -0400695 return drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 }
697
698 return NULL;
699}
700
Alan Cox335f8512009-06-11 12:26:29 +0100701static int serial_carrier_raised(struct tty_port *port)
702{
703 struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
704 struct usb_serial_driver *drv = p->serial->type;
705 if (drv->carrier_raised)
706 return drv->carrier_raised(p);
707 /* No carrier control - don't block */
708 return 1;
709}
710
711static void serial_dtr_rts(struct tty_port *port, int on)
712{
713 struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
714 struct usb_serial_driver *drv = p->serial->type;
715 if (drv->dtr_rts)
716 drv->dtr_rts(p, on);
717}
718
719static const struct tty_port_operations serial_port_ops = {
720 .carrier_raised = serial_carrier_raised,
721 .dtr_rts = serial_dtr_rts,
722};
723
Alan Coxfe1ae7f2009-09-19 13:13:33 -0700724/**
725 * serial_install - install tty
726 * @driver: the driver (USB in our case)
727 * @tty: the tty being created
728 *
729 * Create the termios objects for this tty. We use the default USB
730 * serial ones but permit them to be overriddenby serial->type->termios.
731 * This lets us remove all the ugly hackery
732 */
733
734static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
735{
736 int idx = tty->index;
737 struct usb_serial *serial;
738 int retval;
739
740 /* If the termios setup has yet to be done */
741 if (tty->driver->termios[idx] == NULL) {
742 /* perform the standard setup */
743 retval = tty_init_termios(tty);
744 if (retval)
745 return retval;
746 /* allow the driver to update it */
747 serial = usb_serial_get_by_index(tty->index);
748 if (serial->type->init_termios)
749 serial->type->init_termios(tty);
750 usb_serial_put(serial);
751 }
752 /* Final install (we use the default method) */
753 tty_driver_kref_get(driver);
754 tty->count++;
755 driver->ttys[idx] = tty;
756 return 0;
757}
758
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759int usb_serial_probe(struct usb_interface *interface,
760 const struct usb_device_id *id)
761{
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100762 struct usb_device *dev = interface_to_usbdev(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 struct usb_serial *serial = NULL;
764 struct usb_serial_port *port;
765 struct usb_host_interface *iface_desc;
766 struct usb_endpoint_descriptor *endpoint;
767 struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS];
768 struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS];
769 struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];
770 struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700771 struct usb_serial_driver *type = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 int retval;
Andre Hauptdd9ca5d2008-06-18 15:56:00 +0200773 unsigned int minor;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 int buffer_size;
775 int i;
776 int num_interrupt_in = 0;
777 int num_interrupt_out = 0;
778 int num_bulk_in = 0;
779 int num_bulk_out = 0;
780 int num_ports = 0;
781 int max_endpoints;
782
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100783 lock_kernel(); /* guard against unloading a serial driver module */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 type = search_serial_device(interface);
785 if (!type) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100786 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 dbg("none matched");
788 return -ENODEV;
789 }
790
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100791 serial = create_serial(dev, interface, type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 if (!serial) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100793 unlock_kernel();
Harvey Harrison441b62c2008-03-03 16:08:34 -0800794 dev_err(&interface->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 return -ENOMEM;
796 }
797
798 /* if this device type has a probe function, call it */
799 if (type->probe) {
800 const struct usb_device_id *id;
801
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700802 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100803 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100804 dev_err(&interface->dev,
805 "module get failed, exiting\n");
806 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 return -EIO;
808 }
809
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100810 id = get_iface_id(type, interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 retval = type->probe(serial, id);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700812 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813
814 if (retval) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100815 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100816 dbg("sub driver rejected device");
817 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818 return retval;
819 }
820 }
821
822 /* descriptor matches, let's find the endpoints needed */
823 /* check out the endpoints */
824 iface_desc = interface->cur_altsetting;
825 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
826 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700827
828 if (usb_endpoint_is_bulk_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 /* we found a bulk in endpoint */
830 dbg("found bulk in on endpoint %d", i);
831 bulk_in_endpoint[num_bulk_in] = endpoint;
832 ++num_bulk_in;
833 }
834
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700835 if (usb_endpoint_is_bulk_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 /* we found a bulk out endpoint */
837 dbg("found bulk out on endpoint %d", i);
838 bulk_out_endpoint[num_bulk_out] = endpoint;
839 ++num_bulk_out;
840 }
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700841
842 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 /* we found a interrupt in endpoint */
844 dbg("found interrupt in on endpoint %d", i);
845 interrupt_in_endpoint[num_interrupt_in] = endpoint;
846 ++num_interrupt_in;
847 }
848
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700849 if (usb_endpoint_is_int_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 /* we found an interrupt out endpoint */
851 dbg("found interrupt out on endpoint %d", i);
852 interrupt_out_endpoint[num_interrupt_out] = endpoint;
853 ++num_interrupt_out;
854 }
855 }
856
857#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100858 /* BEGIN HORRIBLE HACK FOR PL2303 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859 /* this is needed due to the looney way its endpoints are set up */
860 if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&
861 (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||
862 ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) &&
Johannes Steingraeber8fd80132006-09-16 16:17:34 +0200863 (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) ||
864 ((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) &&
Andreas Bombece816cf2008-09-14 01:58:55 +0200865 (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID)) ||
866 ((le16_to_cpu(dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) &&
867 (le16_to_cpu(dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_EF81))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 if (interface != dev->actconfig->interface[0]) {
869 /* check out the endpoints of the other interface*/
870 iface_desc = dev->actconfig->interface[0]->cur_altsetting;
871 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
872 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700873 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874 /* we found a interrupt in endpoint */
875 dbg("found interrupt in for Prolific device on separate interface");
876 interrupt_in_endpoint[num_interrupt_in] = endpoint;
877 ++num_interrupt_in;
878 }
879 }
880 }
881
882 /* Now make sure the PL-2303 is configured correctly.
883 * If not, give up now and hope this hack will work
884 * properly during a later invocation of usb_serial_probe
885 */
886 if (num_bulk_in == 0 || num_bulk_out == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100887 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100889 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 return -ENODEV;
891 }
892 }
893 /* END HORRIBLE HACK FOR PL2303 */
894#endif
895
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896#ifdef CONFIG_USB_SERIAL_GENERIC
897 if (type == &usb_serial_generic_device) {
898 num_ports = num_bulk_out;
899 if (num_ports == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100900 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100901 dev_err(&interface->dev,
902 "Generic device with no bulk out, not allowed.\n");
903 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 return -EIO;
905 }
906 }
907#endif
908 if (!num_ports) {
909 /* if this device type has a calc_num_ports function, call it */
910 if (type->calc_num_ports) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700911 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100912 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100913 dev_err(&interface->dev,
914 "module get failed, exiting\n");
915 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 return -EIO;
917 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100918 num_ports = type->calc_num_ports(serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700919 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 }
921 if (!num_ports)
922 num_ports = type->num_ports;
923 }
924
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 serial->num_ports = num_ports;
926 serial->num_bulk_in = num_bulk_in;
927 serial->num_bulk_out = num_bulk_out;
928 serial->num_interrupt_in = num_interrupt_in;
929 serial->num_interrupt_out = num_interrupt_out;
930
Alan Stern063a2da2007-10-10 16:24:06 -0400931 /* found all that we need */
932 dev_info(&interface->dev, "%s converter detected\n",
933 type->description);
934
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 /* create our ports, we need as many as the max endpoints */
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100936 /* we don't use num_ports here because some devices have more
937 endpoint pairs than ports */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 max_endpoints = max(num_bulk_in, num_bulk_out);
939 max_endpoints = max(max_endpoints, num_interrupt_in);
940 max_endpoints = max(max_endpoints, num_interrupt_out);
941 max_endpoints = max(max_endpoints, (int)serial->num_ports);
942 serial->num_port_pointers = max_endpoints;
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100943 unlock_kernel();
944
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100945 dbg("%s - setting up %d port structures for this device",
946 __func__, max_endpoints);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947 for (i = 0; i < max_endpoints; ++i) {
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100948 port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 if (!port)
950 goto probe_error;
Alan Cox4a90f092008-10-13 10:39:46 +0100951 tty_port_init(&port->port);
Alan Cox335f8512009-06-11 12:26:29 +0100952 port->port.ops = &serial_port_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 port->serial = serial;
Greg Kroah-Hartman507ca9b2005-04-23 12:49:16 -0700954 spin_lock_init(&port->lock);
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300955 mutex_init(&port->mutex);
David Howellsc4028952006-11-22 14:57:56 +0000956 INIT_WORK(&port->work, usb_serial_port_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 serial->port[i] = port;
958 }
959
960 /* set up the endpoint information */
961 for (i = 0; i < num_bulk_in; ++i) {
962 endpoint = bulk_in_endpoint[i];
963 port = serial->port[i];
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100964 port->read_urb = usb_alloc_urb(0, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 if (!port->read_urb) {
966 dev_err(&interface->dev, "No free urbs available\n");
967 goto probe_error;
968 }
969 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
970 port->bulk_in_size = buffer_size;
971 port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100972 port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973 if (!port->bulk_in_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100974 dev_err(&interface->dev,
975 "Couldn't allocate bulk_in_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976 goto probe_error;
977 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100978 usb_fill_bulk_urb(port->read_urb, dev,
979 usb_rcvbulkpipe(dev,
980 endpoint->bEndpointAddress),
981 port->bulk_in_buffer, buffer_size,
982 serial->type->read_bulk_callback, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 }
984
985 for (i = 0; i < num_bulk_out; ++i) {
986 endpoint = bulk_out_endpoint[i];
987 port = serial->port[i];
988 port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
989 if (!port->write_urb) {
990 dev_err(&interface->dev, "No free urbs available\n");
991 goto probe_error;
992 }
993 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
994 port->bulk_out_size = buffer_size;
995 port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100996 port->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 if (!port->bulk_out_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100998 dev_err(&interface->dev,
999 "Couldn't allocate bulk_out_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 goto probe_error;
1001 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001002 usb_fill_bulk_urb(port->write_urb, dev,
1003 usb_sndbulkpipe(dev,
1004 endpoint->bEndpointAddress),
1005 port->bulk_out_buffer, buffer_size,
1006 serial->type->write_bulk_callback, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 }
1008
1009 if (serial->type->read_int_callback) {
1010 for (i = 0; i < num_interrupt_in; ++i) {
1011 endpoint = interrupt_in_endpoint[i];
1012 port = serial->port[i];
1013 port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
1014 if (!port->interrupt_in_urb) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001015 dev_err(&interface->dev,
1016 "No free urbs available\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 goto probe_error;
1018 }
1019 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001020 port->interrupt_in_endpointAddress =
1021 endpoint->bEndpointAddress;
1022 port->interrupt_in_buffer = kmalloc(buffer_size,
1023 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 if (!port->interrupt_in_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001025 dev_err(&interface->dev,
1026 "Couldn't allocate interrupt_in_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 goto probe_error;
1028 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001029 usb_fill_int_urb(port->interrupt_in_urb, dev,
1030 usb_rcvintpipe(dev,
1031 endpoint->bEndpointAddress),
1032 port->interrupt_in_buffer, buffer_size,
1033 serial->type->read_int_callback, port,
1034 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 }
1036 } else if (num_interrupt_in) {
1037 dbg("the device claims to support interrupt in transfers, but read_int_callback is not defined");
1038 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001039
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 if (serial->type->write_int_callback) {
1041 for (i = 0; i < num_interrupt_out; ++i) {
1042 endpoint = interrupt_out_endpoint[i];
1043 port = serial->port[i];
1044 port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
1045 if (!port->interrupt_out_urb) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001046 dev_err(&interface->dev,
1047 "No free urbs available\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 goto probe_error;
1049 }
1050 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
1051 port->interrupt_out_size = buffer_size;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001052 port->interrupt_out_endpointAddress =
1053 endpoint->bEndpointAddress;
1054 port->interrupt_out_buffer = kmalloc(buffer_size,
1055 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 if (!port->interrupt_out_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001057 dev_err(&interface->dev,
1058 "Couldn't allocate interrupt_out_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 goto probe_error;
1060 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001061 usb_fill_int_urb(port->interrupt_out_urb, dev,
1062 usb_sndintpipe(dev,
1063 endpoint->bEndpointAddress),
1064 port->interrupt_out_buffer, buffer_size,
1065 serial->type->write_int_callback, port,
1066 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 }
1068 } else if (num_interrupt_out) {
1069 dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined");
1070 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001071
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 /* if this device type has an attach function, call it */
1073 if (type->attach) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -07001074 if (!try_module_get(type->driver.owner)) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001075 dev_err(&interface->dev,
1076 "module get failed, exiting\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077 goto probe_error;
1078 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001079 retval = type->attach(serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -07001080 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081 if (retval < 0)
1082 goto probe_error;
1083 if (retval > 0) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001084 /* quietly accept this device, but don't bind to a
1085 serial port as it's about to disappear */
Alan Stern0a3c8542009-05-27 11:25:52 -04001086 serial->num_ports = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 goto exit;
1088 }
1089 }
1090
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001091 if (get_free_serial(serial, num_ports, &minor) == NULL) {
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001092 dev_err(&interface->dev, "No more free serial devices\n");
1093 goto probe_error;
1094 }
Oliver Neukumc744f992007-02-26 15:43:00 +01001095 serial->minor = minor;
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001096
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 /* register all of the individual ports with the driver core */
1098 for (i = 0; i < num_ports; ++i) {
1099 port = serial->port[i];
1100 port->dev.parent = &interface->dev;
1101 port->dev.driver = NULL;
1102 port->dev.bus = &usb_serial_bus_type;
1103 port->dev.release = &port_release;
1104
Kay Sievers0031a062008-05-02 06:02:41 +02001105 dev_set_name(&port->dev, "ttyUSB%d", port->number);
Kay Sievers7071a3c2008-05-02 06:02:41 +02001106 dbg ("%s - registering %s", __func__, dev_name(&port->dev));
Alan Sternc706ebd2009-06-02 11:54:11 -04001107 port->dev_state = PORT_REGISTERING;
Greg Kroah-Hartman13f4db92006-08-28 11:43:25 -07001108 retval = device_register(&port->dev);
Alan Sternc706ebd2009-06-02 11:54:11 -04001109 if (retval) {
Greg Kroah-Hartman13f4db92006-08-28 11:43:25 -07001110 dev_err(&port->dev, "Error registering port device, "
1111 "continuing\n");
Alan Sternc706ebd2009-06-02 11:54:11 -04001112 port->dev_state = PORT_UNREGISTERED;
1113 } else {
1114 port->dev_state = PORT_REGISTERED;
1115 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 }
1117
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001118 usb_serial_console_init(debug, minor);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119
1120exit:
1121 /* success */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001122 usb_set_intfdata(interface, serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 return 0;
1124
1125probe_error:
1126 for (i = 0; i < num_bulk_in; ++i) {
1127 port = serial->port[i];
1128 if (!port)
1129 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001130 usb_free_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 kfree(port->bulk_in_buffer);
1132 }
1133 for (i = 0; i < num_bulk_out; ++i) {
1134 port = serial->port[i];
1135 if (!port)
1136 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001137 usb_free_urb(port->write_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 kfree(port->bulk_out_buffer);
1139 }
1140 for (i = 0; i < num_interrupt_in; ++i) {
1141 port = serial->port[i];
1142 if (!port)
1143 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001144 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145 kfree(port->interrupt_in_buffer);
1146 }
1147 for (i = 0; i < num_interrupt_out; ++i) {
1148 port = serial->port[i];
1149 if (!port)
1150 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001151 usb_free_urb(port->interrupt_out_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152 kfree(port->interrupt_out_buffer);
1153 }
1154
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 /* free up any memory that we allocated */
1156 for (i = 0; i < serial->num_port_pointers; ++i)
1157 kfree(serial->port[i]);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001158 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 return -EIO;
1160}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001161EXPORT_SYMBOL_GPL(usb_serial_probe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162
1163void usb_serial_disconnect(struct usb_interface *interface)
1164{
1165 int i;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001166 struct usb_serial *serial = usb_get_intfdata(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167 struct device *dev = &interface->dev;
1168 struct usb_serial_port *port;
1169
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +02001170 usb_serial_console_disconnect(serial);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001171 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001173 mutex_lock(&serial->disc_mutex);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001174 usb_set_intfdata(interface, NULL);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001175 /* must set a flag, to signal subdrivers */
1176 serial->disconnected = 1;
Alan Stern2d931482009-04-14 11:31:02 -04001177 mutex_unlock(&serial->disc_mutex);
1178
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001179 for (i = 0; i < serial->num_ports; ++i) {
1180 port = serial->port[i];
1181 if (port) {
Alan Cox4a90f092008-10-13 10:39:46 +01001182 struct tty_struct *tty = tty_port_tty_get(&port->port);
1183 if (tty) {
Alan Coxd2b39182009-09-19 13:13:23 -07001184 tty_vhangup(tty);
Alan Cox4a90f092008-10-13 10:39:46 +01001185 tty_kref_put(tty);
1186 }
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001187 kill_traffic(port);
Alan Stern2d931482009-04-14 11:31:02 -04001188 cancel_work_sync(&port->work);
Alan Sternc706ebd2009-06-02 11:54:11 -04001189 if (port->dev_state == PORT_REGISTERED) {
1190
1191 /* Make sure the port is bound so that the
1192 * driver's port_remove method is called.
1193 */
1194 if (!port->dev.driver) {
1195 int rc;
1196
1197 port->dev.driver =
1198 &serial->type->driver;
1199 rc = device_bind_driver(&port->dev);
1200 }
1201 port->dev_state = PORT_UNREGISTERING;
1202 device_del(&port->dev);
1203 port->dev_state = PORT_UNREGISTERED;
1204 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 }
Alan Sternf9c99bb2009-06-02 11:53:55 -04001207 serial->type->disconnect(serial);
Alan Stern2d931482009-04-14 11:31:02 -04001208
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001209 /* let the last holder of this object
1210 * cause it to be cleaned up */
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001211 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 dev_info(dev, "device disconnected\n");
1213}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001214EXPORT_SYMBOL_GPL(usb_serial_disconnect);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215
Oliver Neukumec225592007-04-27 20:54:57 +02001216int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
1217{
1218 struct usb_serial *serial = usb_get_intfdata(intf);
1219 struct usb_serial_port *port;
1220 int i, r = 0;
1221
Oliver Neukumf8bece82009-02-05 16:54:25 +01001222 serial->suspending = 1;
1223
Oliver Neukume31c1882007-07-23 08:58:39 +02001224 for (i = 0; i < serial->num_ports; ++i) {
1225 port = serial->port[i];
1226 if (port)
1227 kill_traffic(port);
Oliver Neukumec225592007-04-27 20:54:57 +02001228 }
1229
1230 if (serial->type->suspend)
Oliver Neukume31c1882007-07-23 08:58:39 +02001231 r = serial->type->suspend(serial, message);
Oliver Neukumec225592007-04-27 20:54:57 +02001232
1233 return r;
1234}
1235EXPORT_SYMBOL(usb_serial_suspend);
1236
1237int usb_serial_resume(struct usb_interface *intf)
1238{
1239 struct usb_serial *serial = usb_get_intfdata(intf);
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001240 int rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001241
Oliver Neukumf8bece82009-02-05 16:54:25 +01001242 serial->suspending = 0;
Sarah Sharp8abaee22007-10-25 10:58:43 -07001243 if (serial->type->resume)
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001244 rv = serial->type->resume(serial);
1245 else
1246 rv = usb_serial_generic_resume(serial);
Oliver Neukumf8bece82009-02-05 16:54:25 +01001247
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001248 return rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001249}
1250EXPORT_SYMBOL(usb_serial_resume);
1251
Jeff Dikeb68e31d2006-10-02 02:17:18 -07001252static const struct tty_operations serial_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253 .open = serial_open,
1254 .close = serial_close,
1255 .write = serial_write,
Alan Cox335f8512009-06-11 12:26:29 +01001256 .hangup = serial_hangup,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257 .write_room = serial_write_room,
1258 .ioctl = serial_ioctl,
1259 .set_termios = serial_set_termios,
1260 .throttle = serial_throttle,
1261 .unthrottle = serial_unthrottle,
1262 .break_ctl = serial_break,
1263 .chars_in_buffer = serial_chars_in_buffer,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264 .tiocmget = serial_tiocmget,
1265 .tiocmset = serial_tiocmset,
Alan Coxfe1ae7f2009-09-19 13:13:33 -07001266 .shutdown = serial_do_free,
1267 .install = serial_install,
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -07001268 .proc_fops = &serial_proc_fops,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269};
1270
Alan Cox335f8512009-06-11 12:26:29 +01001271
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272struct tty_driver *usb_serial_tty_driver;
1273
1274static int __init usb_serial_init(void)
1275{
1276 int i;
1277 int result;
1278
1279 usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS);
1280 if (!usb_serial_tty_driver)
1281 return -ENOMEM;
1282
1283 /* Initialize our global data */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001284 for (i = 0; i < SERIAL_TTY_MINORS; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285 serial_table[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286
1287 result = bus_register(&usb_serial_bus_type);
1288 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001289 printk(KERN_ERR "usb-serial: %s - registering bus driver "
1290 "failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 goto exit_bus;
1292 }
1293
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294 usb_serial_tty_driver->owner = THIS_MODULE;
1295 usb_serial_tty_driver->driver_name = "usbserial";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 usb_serial_tty_driver->name = "ttyUSB";
1297 usb_serial_tty_driver->major = SERIAL_TTY_MAJOR;
1298 usb_serial_tty_driver->minor_start = 0;
1299 usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
1300 usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001301 usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW |
1302 TTY_DRIVER_DYNAMIC_DEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303 usb_serial_tty_driver->init_termios = tty_std_termios;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001304 usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD
1305 | HUPCL | CLOCAL;
Alan Coxa5b6f602008-04-08 17:16:06 +01001306 usb_serial_tty_driver->init_termios.c_ispeed = 9600;
1307 usb_serial_tty_driver->init_termios.c_ospeed = 9600;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308 tty_set_operations(usb_serial_tty_driver, &serial_ops);
1309 result = tty_register_driver(usb_serial_tty_driver);
1310 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001311 printk(KERN_ERR "usb-serial: %s - tty_register_driver failed\n",
1312 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313 goto exit_reg_driver;
1314 }
1315
1316 /* register the USB driver */
1317 result = usb_register(&usb_serial_driver);
1318 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001319 printk(KERN_ERR "usb-serial: %s - usb_register failed\n",
1320 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 goto exit_tty;
1322 }
1323
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001324 /* register the generic driver, if we should */
1325 result = usb_serial_generic_register(debug);
1326 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001327 printk(KERN_ERR "usb-serial: %s - registering generic "
1328 "driver failed\n", __func__);
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001329 goto exit_generic;
1330 }
1331
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001332 printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333
1334 return result;
1335
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001336exit_generic:
1337 usb_deregister(&usb_serial_driver);
1338
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339exit_tty:
1340 tty_unregister_driver(usb_serial_tty_driver);
1341
1342exit_reg_driver:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343 bus_unregister(&usb_serial_bus_type);
1344
1345exit_bus:
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001346 printk(KERN_ERR "usb-serial: %s - returning with error %d\n",
1347 __func__, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 put_tty_driver(usb_serial_tty_driver);
1349 return result;
1350}
1351
1352
1353static void __exit usb_serial_exit(void)
1354{
1355 usb_serial_console_exit();
1356
1357 usb_serial_generic_deregister();
1358
1359 usb_deregister(&usb_serial_driver);
1360 tty_unregister_driver(usb_serial_tty_driver);
1361 put_tty_driver(usb_serial_tty_driver);
1362 bus_unregister(&usb_serial_bus_type);
1363}
1364
1365
1366module_init(usb_serial_init);
1367module_exit(usb_serial_exit);
1368
1369#define set_to_generic_if_null(type, function) \
1370 do { \
1371 if (!type->function) { \
1372 type->function = usb_serial_generic_##function; \
1373 dbg("Had to override the " #function \
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001374 " usb serial operation with the generic one.");\
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 } \
1376 } while (0)
1377
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001378static void fixup_generic(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379{
1380 set_to_generic_if_null(device, open);
1381 set_to_generic_if_null(device, write);
1382 set_to_generic_if_null(device, close);
1383 set_to_generic_if_null(device, write_room);
1384 set_to_generic_if_null(device, chars_in_buffer);
1385 set_to_generic_if_null(device, read_bulk_callback);
1386 set_to_generic_if_null(device, write_bulk_callback);
Alan Sternf9c99bb2009-06-02 11:53:55 -04001387 set_to_generic_if_null(device, disconnect);
1388 set_to_generic_if_null(device, release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389}
1390
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001391int usb_serial_register(struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001393 /* must be called with BKL held */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 int retval;
1395
Dave Younge4abe662009-02-14 21:21:13 +08001396 if (usb_disabled())
1397 return -ENODEV;
1398
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001399 fixup_generic(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001401 if (!driver->description)
1402 driver->description = driver->driver.name;
1403
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404 /* Add this device to our list of devices */
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001405 list_add(&driver->driver_list, &usb_serial_driver_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001407 retval = usb_serial_bus_register(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 if (retval) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001409 printk(KERN_ERR "usb-serial: problem %d when registering "
1410 "driver %s\n", retval, driver->description);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001411 list_del(&driver->driver_list);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001412 } else
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001413 printk(KERN_INFO "USB Serial support registered for %s\n",
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001414 driver->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415
1416 return retval;
1417}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001418EXPORT_SYMBOL_GPL(usb_serial_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419
1420
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001421void usb_serial_deregister(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001423 /* must be called with BKL held */
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001424 printk(KERN_INFO "USB Serial deregistering driver %s\n",
1425 device->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426 list_del(&device->driver_list);
1427 usb_serial_bus_deregister(device);
1428}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429EXPORT_SYMBOL_GPL(usb_serial_deregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430
1431/* Module information */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001432MODULE_AUTHOR(DRIVER_AUTHOR);
1433MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434MODULE_LICENSE("GPL");
1435
1436module_param(debug, bool, S_IRUGO | S_IWUSR);
1437MODULE_PARM_DESC(debug, "Debug enabled or not");