blob: 99188c92068bb4492416ff99b7655086721c9034 [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 Cox95da3102008-07-22 11:09:07 +0100247 retval = serial->type->open(tty, port, filp);
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.
319 */
320
321static void serial_do_free(struct usb_serial_port *port)
322{
323 struct usb_serial *serial;
324 struct module *owner;
325
326 /* The console is magical, do not hang up the console hardware
327 or there will be tears */
328 if (port->console)
329 return;
330
331 serial = port->serial;
332 owner = serial->type->driver.owner;
Alan Stern2d931482009-04-14 11:31:02 -0400333 put_device(&port->dev);
Alan Stern2d931482009-04-14 11:31:02 -0400334 /* Mustn't dereference port any more */
Alan Cox335f8512009-06-11 12:26:29 +0100335 mutex_lock(&serial->disc_mutex);
336 if (!serial->disconnected)
337 usb_autopm_put_interface(serial->interface);
338 mutex_unlock(&serial->disc_mutex);
Alan Stern2d931482009-04-14 11:31:02 -0400339 usb_serial_put(serial);
Alan Stern2d931482009-04-14 11:31:02 -0400340 /* Mustn't dereference serial any more */
Alan Cox335f8512009-06-11 12:26:29 +0100341 module_put(owner);
342}
343
344static void serial_close(struct tty_struct *tty, struct file *filp)
345{
346 struct usb_serial_port *port = tty->driver_data;
347
Thadeu Lima de Souza Cascardof4fa4462009-06-25 14:41:37 +0100348 if (!port)
349 return;
350
Alan Cox335f8512009-06-11 12:26:29 +0100351 dbg("%s - port %d", __func__, port->number);
352
Alan Coxb68f2fb2009-07-27 10:58:08 +0100353 /* FIXME:
354 This leaves a very narrow race. Really we should do the
355 serial_do_free() on tty->shutdown(), but tty->shutdown can
356 be called from IRQ context and serial_do_free can sleep.
357
358 The right fix is probably to make the tty free (which is rare)
359 and thus tty->shutdown() occur via a work queue and simplify all
360 the drivers that use it.
361 */
362 if (tty_hung_up_p(filp)) {
363 /* serial_hangup already called serial_down at this point.
364 Another user may have already reopened the port but
365 serial_do_free is refcounted */
366 serial_do_free(port);
367 return;
368 }
Alan Cox335f8512009-06-11 12:26:29 +0100369
370 if (tty_port_close_start(&port->port, tty, filp) == 0)
371 return;
372
373 serial_do_down(port);
374 tty_port_close_end(&port->port, tty);
375 tty_port_tty_set(&port->port, NULL);
376 serial_do_free(port);
377}
378
379static void serial_hangup(struct tty_struct *tty)
380{
381 struct usb_serial_port *port = tty->driver_data;
382 serial_do_down(port);
383 tty_port_hangup(&port->port);
Alan Coxb68f2fb2009-07-27 10:58:08 +0100384 /* We must not free port yet - the USB serial layer depends on it's
385 continued existence */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386}
387
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100388static int serial_write(struct tty_struct *tty, const unsigned char *buf,
389 int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200391 struct usb_serial_port *port = tty->driver_data;
Oliver Neukum3ff4fd92007-01-13 07:32:27 +0100392 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393
Alan Coxf34d7a52008-04-30 00:54:13 -0700394 if (port->serial->dev->state == USB_STATE_NOTATTACHED)
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200395 goto exit;
396
Harvey Harrison441b62c2008-03-03 16:08:34 -0800397 dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398
Alan Cox95da3102008-07-22 11:09:07 +0100399 /* count is managed under the mutex lock for the tty so cannot
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100400 drop to zero until after the last close completes */
Alan Cox95da3102008-07-22 11:09:07 +0100401 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402
403 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100404 retval = port->serial->type->write(tty, port, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405
406exit:
407 return retval;
408}
409
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100410static int serial_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200412 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800413 dbg("%s - port %d", __func__, port->number);
Alan Cox95da3102008-07-22 11:09:07 +0100414 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100416 return port->serial->type->write_room(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417}
418
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100419static int serial_chars_in_buffer(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200421 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800422 dbg("%s = port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423
Alan Coxeff69372009-01-02 13:47:06 +0000424 /* if the device was unplugged then any remaining characters
425 fell out of the connector ;) */
426 if (port->serial->disconnected)
427 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100429 return port->serial->type->chars_in_buffer(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430}
431
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100432static void serial_throttle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200434 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800435 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436
Alan Cox95da3102008-07-22 11:09:07 +0100437 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438 /* pass on to the driver specific version of this function */
439 if (port->serial->type->throttle)
Alan Cox95da3102008-07-22 11:09:07 +0100440 port->serial->type->throttle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441}
442
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100443static void serial_unthrottle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200445 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800446 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447
Alan Cox95da3102008-07-22 11:09:07 +0100448 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 /* pass on to the driver specific version of this function */
450 if (port->serial->type->unthrottle)
Alan Cox95da3102008-07-22 11:09:07 +0100451 port->serial->type->unthrottle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452}
453
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100454static int serial_ioctl(struct tty_struct *tty, struct file *file,
455 unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200457 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458 int retval = -ENODEV;
459
Harvey Harrison441b62c2008-03-03 16:08:34 -0800460 dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461
Alan Cox95da3102008-07-22 11:09:07 +0100462 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100464 /* pass on to the driver specific version of this function
465 if it is available */
Alan Coxf34d7a52008-04-30 00:54:13 -0700466 if (port->serial->type->ioctl) {
Alan Cox95da3102008-07-22 11:09:07 +0100467 retval = port->serial->type->ioctl(tty, file, cmd, arg);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100468 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 retval = -ENOIOCTLCMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 return retval;
471}
472
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100473static void serial_set_termios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200475 struct usb_serial_port *port = tty->driver_data;
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 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 if (port->serial->type->set_termios)
Alan Cox95da3102008-07-22 11:09:07 +0100482 port->serial->type->set_termios(tty, port, old);
Alan Cox33785092007-10-18 01:24:22 -0700483 else
484 tty_termios_copy_hw(tty->termios, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485}
486
Alan Cox9e989662008-07-22 11:18:03 +0100487static int serial_break(struct tty_struct *tty, int break_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200489 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490
Harvey Harrison441b62c2008-03-03 16:08:34 -0800491 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492
Alan Cox95da3102008-07-22 11:09:07 +0100493 WARN_ON(!port->port.count);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100494 /* pass on to the driver specific version of this function
495 if it is available */
Alan Cox6b447f042009-01-02 13:48:56 +0000496 if (port->serial->type->break_ctl)
Alan Cox95da3102008-07-22 11:09:07 +0100497 port->serial->type->break_ctl(tty, break_state);
Alan Cox9e989662008-07-22 11:18:03 +0100498 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499}
500
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700501static int serial_proc_show(struct seq_file *m, void *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502{
503 struct usb_serial *serial;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 char tmp[40];
506
Harvey Harrison441b62c2008-03-03 16:08:34 -0800507 dbg("%s", __func__);
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700508 seq_puts(m, "usbserinfo:1.0 driver:2.0\n");
509 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 serial = usb_serial_get_by_index(i);
511 if (serial == NULL)
512 continue;
513
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700514 seq_printf(m, "%d:", i);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700515 if (serial->type->driver.owner)
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700516 seq_printf(m, " module:%s",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100517 module_name(serial->type->driver.owner));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700518 seq_printf(m, " name:\"%s\"",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100519 serial->type->description);
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700520 seq_printf(m, " vendor:%04x product:%04x",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100521 le16_to_cpu(serial->dev->descriptor.idVendor),
522 le16_to_cpu(serial->dev->descriptor.idProduct));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700523 seq_printf(m, " num_ports:%d", serial->num_ports);
524 seq_printf(m, " port:%d", i - serial->minor + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 usb_make_path(serial->dev, tmp, sizeof(tmp));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700526 seq_printf(m, " path:%s", tmp);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100527
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700528 seq_putc(m, '\n');
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200529 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 }
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700531 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532}
533
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700534static int serial_proc_open(struct inode *inode, struct file *file)
535{
536 return single_open(file, serial_proc_show, NULL);
537}
538
539static const struct file_operations serial_proc_fops = {
540 .owner = THIS_MODULE,
541 .open = serial_proc_open,
542 .read = seq_read,
543 .llseek = seq_lseek,
544 .release = single_release,
545};
546
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100547static int serial_tiocmget(struct tty_struct *tty, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200549 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550
Harvey Harrison441b62c2008-03-03 16:08:34 -0800551 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552
Alan Cox95da3102008-07-22 11:09:07 +0100553 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 if (port->serial->type->tiocmget)
Alan Cox95da3102008-07-22 11:09:07 +0100555 return port->serial->type->tiocmget(tty, file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556 return -EINVAL;
557}
558
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100559static int serial_tiocmset(struct tty_struct *tty, struct file *file,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 unsigned int set, unsigned int clear)
561{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200562 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563
Harvey Harrison441b62c2008-03-03 16:08:34 -0800564 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565
Alan Cox95da3102008-07-22 11:09:07 +0100566 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567 if (port->serial->type->tiocmset)
Alan Cox95da3102008-07-22 11:09:07 +0100568 return port->serial->type->tiocmset(tty, file, set, clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 return -EINVAL;
570}
571
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700572/*
573 * We would be calling tty_wakeup here, but unfortunately some line
574 * disciplines have an annoying habit of calling tty->write from
575 * the write wakeup callback (e.g. n_hdlc.c).
576 */
577void usb_serial_port_softint(struct usb_serial_port *port)
578{
579 schedule_work(&port->work);
580}
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100581EXPORT_SYMBOL_GPL(usb_serial_port_softint);
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700582
David Howellsc4028952006-11-22 14:57:56 +0000583static void usb_serial_port_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584{
David Howellsc4028952006-11-22 14:57:56 +0000585 struct usb_serial_port *port =
586 container_of(work, struct usb_serial_port, work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587 struct tty_struct *tty;
588
Harvey Harrison441b62c2008-03-03 16:08:34 -0800589 dbg("%s - port %d", __func__, port->number);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100590
Alan Cox4a90f092008-10-13 10:39:46 +0100591 tty = tty_port_tty_get(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592 if (!tty)
593 return;
594
595 tty_wakeup(tty);
Alan Cox4a90f092008-10-13 10:39:46 +0100596 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597}
598
599static void port_release(struct device *dev)
600{
601 struct usb_serial_port *port = to_usb_serial_port(dev);
602
Kay Sievers7071a3c2008-05-02 06:02:41 +0200603 dbg ("%s - %s", __func__, dev_name(dev));
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700604 port_free(port);
605}
606
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100607static void kill_traffic(struct usb_serial_port *port)
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700608{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610 usb_kill_urb(port->write_urb);
Oliver Neukum5adceac2007-08-17 14:01:38 +0200611 /*
612 * This is tricky.
613 * Some drivers submit the read_urb in the
614 * handler for the write_urb or vice versa
615 * this order determines the order in which
616 * usb_kill_urb() must be used to reliably
617 * kill the URBs. As it is unknown here,
618 * both orders must be used in turn.
619 * The call below is not redundant.
620 */
621 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622 usb_kill_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 usb_kill_urb(port->interrupt_out_urb);
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100624}
625
626static void port_free(struct usb_serial_port *port)
627{
Alan Stern2d931482009-04-14 11:31:02 -0400628 /*
629 * Stop all the traffic before cancelling the work, so that
630 * nobody will restart it by calling usb_serial_port_softint.
631 */
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100632 kill_traffic(port);
Alan Stern2d931482009-04-14 11:31:02 -0400633 cancel_work_sync(&port->work);
634
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100635 usb_free_urb(port->read_urb);
636 usb_free_urb(port->write_urb);
637 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 usb_free_urb(port->interrupt_out_urb);
639 kfree(port->bulk_in_buffer);
640 kfree(port->bulk_out_buffer);
641 kfree(port->interrupt_in_buffer);
642 kfree(port->interrupt_out_buffer);
643 kfree(port);
644}
645
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100646static struct usb_serial *create_serial(struct usb_device *dev,
647 struct usb_interface *interface,
648 struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649{
650 struct usb_serial *serial;
651
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100652 serial = kzalloc(sizeof(*serial), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 if (!serial) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800654 dev_err(&dev->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655 return NULL;
656 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 serial->dev = usb_get_dev(dev);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700658 serial->type = driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 serial->interface = interface;
660 kref_init(&serial->kref);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +0100661 mutex_init(&serial->disc_mutex);
Alan Stern0282b7f2008-07-29 12:01:04 -0400662 serial->minor = SERIAL_TTY_NO_MINOR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663
664 return serial;
665}
666
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100667static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf,
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100668 struct usb_serial_driver *drv)
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100669{
670 struct usb_dynid *dynid;
671
672 spin_lock(&drv->dynids.lock);
673 list_for_each_entry(dynid, &drv->dynids.list, node) {
674 if (usb_match_one_id(intf, &dynid->id)) {
675 spin_unlock(&drv->dynids.lock);
676 return &dynid->id;
677 }
678 }
679 spin_unlock(&drv->dynids.lock);
680 return NULL;
681}
682
683static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv,
684 struct usb_interface *intf)
685{
686 const struct usb_device_id *id;
687
688 id = usb_match_id(intf, drv->id_table);
689 if (id) {
690 dbg("static descriptor matches");
691 goto exit;
692 }
693 id = match_dynamic_id(intf, drv);
694 if (id)
695 dbg("dynamic descriptor matches");
696exit:
697 return id;
698}
699
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100700static struct usb_serial_driver *search_serial_device(
701 struct usb_interface *iface)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 const struct usb_device_id *id;
Alan Stern063a2da2007-10-10 16:24:06 -0400704 struct usb_serial_driver *drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705
Adrian Bunk93b1fae2006-01-10 00:13:33 +0100706 /* Check if the usb id matches a known device */
Alan Stern063a2da2007-10-10 16:24:06 -0400707 list_for_each_entry(drv, &usb_serial_driver_list, driver_list) {
708 id = get_iface_id(drv, iface);
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100709 if (id)
Alan Stern063a2da2007-10-10 16:24:06 -0400710 return drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711 }
712
713 return NULL;
714}
715
Alan Cox335f8512009-06-11 12:26:29 +0100716static int serial_carrier_raised(struct tty_port *port)
717{
718 struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
719 struct usb_serial_driver *drv = p->serial->type;
720 if (drv->carrier_raised)
721 return drv->carrier_raised(p);
722 /* No carrier control - don't block */
723 return 1;
724}
725
726static void serial_dtr_rts(struct tty_port *port, int on)
727{
728 struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
729 struct usb_serial_driver *drv = p->serial->type;
730 if (drv->dtr_rts)
731 drv->dtr_rts(p, on);
732}
733
734static const struct tty_port_operations serial_port_ops = {
735 .carrier_raised = serial_carrier_raised,
736 .dtr_rts = serial_dtr_rts,
737};
738
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739int usb_serial_probe(struct usb_interface *interface,
740 const struct usb_device_id *id)
741{
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100742 struct usb_device *dev = interface_to_usbdev(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 struct usb_serial *serial = NULL;
744 struct usb_serial_port *port;
745 struct usb_host_interface *iface_desc;
746 struct usb_endpoint_descriptor *endpoint;
747 struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS];
748 struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS];
749 struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];
750 struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700751 struct usb_serial_driver *type = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 int retval;
Andre Hauptdd9ca5d2008-06-18 15:56:00 +0200753 unsigned int minor;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754 int buffer_size;
755 int i;
756 int num_interrupt_in = 0;
757 int num_interrupt_out = 0;
758 int num_bulk_in = 0;
759 int num_bulk_out = 0;
760 int num_ports = 0;
761 int max_endpoints;
762
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100763 lock_kernel(); /* guard against unloading a serial driver module */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 type = search_serial_device(interface);
765 if (!type) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100766 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767 dbg("none matched");
768 return -ENODEV;
769 }
770
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100771 serial = create_serial(dev, interface, type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 if (!serial) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100773 unlock_kernel();
Harvey Harrison441b62c2008-03-03 16:08:34 -0800774 dev_err(&interface->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775 return -ENOMEM;
776 }
777
778 /* if this device type has a probe function, call it */
779 if (type->probe) {
780 const struct usb_device_id *id;
781
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700782 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100783 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100784 dev_err(&interface->dev,
785 "module get failed, exiting\n");
786 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 return -EIO;
788 }
789
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100790 id = get_iface_id(type, interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791 retval = type->probe(serial, id);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700792 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793
794 if (retval) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100795 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100796 dbg("sub driver rejected device");
797 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 return retval;
799 }
800 }
801
802 /* descriptor matches, let's find the endpoints needed */
803 /* check out the endpoints */
804 iface_desc = interface->cur_altsetting;
805 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
806 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700807
808 if (usb_endpoint_is_bulk_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 /* we found a bulk in endpoint */
810 dbg("found bulk in on endpoint %d", i);
811 bulk_in_endpoint[num_bulk_in] = endpoint;
812 ++num_bulk_in;
813 }
814
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700815 if (usb_endpoint_is_bulk_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 /* we found a bulk out endpoint */
817 dbg("found bulk out on endpoint %d", i);
818 bulk_out_endpoint[num_bulk_out] = endpoint;
819 ++num_bulk_out;
820 }
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700821
822 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 /* we found a interrupt in endpoint */
824 dbg("found interrupt in on endpoint %d", i);
825 interrupt_in_endpoint[num_interrupt_in] = endpoint;
826 ++num_interrupt_in;
827 }
828
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700829 if (usb_endpoint_is_int_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 /* we found an interrupt out endpoint */
831 dbg("found interrupt out on endpoint %d", i);
832 interrupt_out_endpoint[num_interrupt_out] = endpoint;
833 ++num_interrupt_out;
834 }
835 }
836
837#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100838 /* BEGIN HORRIBLE HACK FOR PL2303 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 /* this is needed due to the looney way its endpoints are set up */
840 if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&
841 (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||
842 ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) &&
Johannes Steingraeber8fd80132006-09-16 16:17:34 +0200843 (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) ||
844 ((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) &&
Andreas Bombece816cf2008-09-14 01:58:55 +0200845 (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID)) ||
846 ((le16_to_cpu(dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) &&
847 (le16_to_cpu(dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_EF81))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 if (interface != dev->actconfig->interface[0]) {
849 /* check out the endpoints of the other interface*/
850 iface_desc = dev->actconfig->interface[0]->cur_altsetting;
851 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
852 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700853 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854 /* we found a interrupt in endpoint */
855 dbg("found interrupt in for Prolific device on separate interface");
856 interrupt_in_endpoint[num_interrupt_in] = endpoint;
857 ++num_interrupt_in;
858 }
859 }
860 }
861
862 /* Now make sure the PL-2303 is configured correctly.
863 * If not, give up now and hope this hack will work
864 * properly during a later invocation of usb_serial_probe
865 */
866 if (num_bulk_in == 0 || num_bulk_out == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100867 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100869 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 return -ENODEV;
871 }
872 }
873 /* END HORRIBLE HACK FOR PL2303 */
874#endif
875
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876#ifdef CONFIG_USB_SERIAL_GENERIC
877 if (type == &usb_serial_generic_device) {
878 num_ports = num_bulk_out;
879 if (num_ports == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100880 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100881 dev_err(&interface->dev,
882 "Generic device with no bulk out, not allowed.\n");
883 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 return -EIO;
885 }
886 }
887#endif
888 if (!num_ports) {
889 /* if this device type has a calc_num_ports function, call it */
890 if (type->calc_num_ports) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700891 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100892 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100893 dev_err(&interface->dev,
894 "module get failed, exiting\n");
895 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 return -EIO;
897 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100898 num_ports = type->calc_num_ports(serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700899 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 }
901 if (!num_ports)
902 num_ports = type->num_ports;
903 }
904
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 serial->num_ports = num_ports;
906 serial->num_bulk_in = num_bulk_in;
907 serial->num_bulk_out = num_bulk_out;
908 serial->num_interrupt_in = num_interrupt_in;
909 serial->num_interrupt_out = num_interrupt_out;
910
Alan Stern063a2da2007-10-10 16:24:06 -0400911 /* found all that we need */
912 dev_info(&interface->dev, "%s converter detected\n",
913 type->description);
914
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 /* create our ports, we need as many as the max endpoints */
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100916 /* we don't use num_ports here because some devices have more
917 endpoint pairs than ports */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 max_endpoints = max(num_bulk_in, num_bulk_out);
919 max_endpoints = max(max_endpoints, num_interrupt_in);
920 max_endpoints = max(max_endpoints, num_interrupt_out);
921 max_endpoints = max(max_endpoints, (int)serial->num_ports);
922 serial->num_port_pointers = max_endpoints;
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100923 unlock_kernel();
924
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100925 dbg("%s - setting up %d port structures for this device",
926 __func__, max_endpoints);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 for (i = 0; i < max_endpoints; ++i) {
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100928 port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 if (!port)
930 goto probe_error;
Alan Cox4a90f092008-10-13 10:39:46 +0100931 tty_port_init(&port->port);
Alan Cox335f8512009-06-11 12:26:29 +0100932 port->port.ops = &serial_port_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 port->serial = serial;
Greg Kroah-Hartman507ca9b2005-04-23 12:49:16 -0700934 spin_lock_init(&port->lock);
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300935 mutex_init(&port->mutex);
David Howellsc4028952006-11-22 14:57:56 +0000936 INIT_WORK(&port->work, usb_serial_port_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937 serial->port[i] = port;
938 }
939
940 /* set up the endpoint information */
941 for (i = 0; i < num_bulk_in; ++i) {
942 endpoint = bulk_in_endpoint[i];
943 port = serial->port[i];
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100944 port->read_urb = usb_alloc_urb(0, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 if (!port->read_urb) {
946 dev_err(&interface->dev, "No free urbs available\n");
947 goto probe_error;
948 }
949 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
950 port->bulk_in_size = buffer_size;
951 port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100952 port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 if (!port->bulk_in_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100954 dev_err(&interface->dev,
955 "Couldn't allocate bulk_in_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 goto probe_error;
957 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100958 usb_fill_bulk_urb(port->read_urb, dev,
959 usb_rcvbulkpipe(dev,
960 endpoint->bEndpointAddress),
961 port->bulk_in_buffer, buffer_size,
962 serial->type->read_bulk_callback, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 }
964
965 for (i = 0; i < num_bulk_out; ++i) {
966 endpoint = bulk_out_endpoint[i];
967 port = serial->port[i];
968 port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
969 if (!port->write_urb) {
970 dev_err(&interface->dev, "No free urbs available\n");
971 goto probe_error;
972 }
973 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
974 port->bulk_out_size = buffer_size;
975 port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100976 port->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 if (!port->bulk_out_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100978 dev_err(&interface->dev,
979 "Couldn't allocate bulk_out_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 goto probe_error;
981 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100982 usb_fill_bulk_urb(port->write_urb, dev,
983 usb_sndbulkpipe(dev,
984 endpoint->bEndpointAddress),
985 port->bulk_out_buffer, buffer_size,
986 serial->type->write_bulk_callback, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 }
988
989 if (serial->type->read_int_callback) {
990 for (i = 0; i < num_interrupt_in; ++i) {
991 endpoint = interrupt_in_endpoint[i];
992 port = serial->port[i];
993 port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
994 if (!port->interrupt_in_urb) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100995 dev_err(&interface->dev,
996 "No free urbs available\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 goto probe_error;
998 }
999 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001000 port->interrupt_in_endpointAddress =
1001 endpoint->bEndpointAddress;
1002 port->interrupt_in_buffer = kmalloc(buffer_size,
1003 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 if (!port->interrupt_in_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001005 dev_err(&interface->dev,
1006 "Couldn't allocate interrupt_in_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 goto probe_error;
1008 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001009 usb_fill_int_urb(port->interrupt_in_urb, dev,
1010 usb_rcvintpipe(dev,
1011 endpoint->bEndpointAddress),
1012 port->interrupt_in_buffer, buffer_size,
1013 serial->type->read_int_callback, port,
1014 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 }
1016 } else if (num_interrupt_in) {
1017 dbg("the device claims to support interrupt in transfers, but read_int_callback is not defined");
1018 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001019
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 if (serial->type->write_int_callback) {
1021 for (i = 0; i < num_interrupt_out; ++i) {
1022 endpoint = interrupt_out_endpoint[i];
1023 port = serial->port[i];
1024 port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
1025 if (!port->interrupt_out_urb) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001026 dev_err(&interface->dev,
1027 "No free urbs available\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 goto probe_error;
1029 }
1030 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
1031 port->interrupt_out_size = buffer_size;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001032 port->interrupt_out_endpointAddress =
1033 endpoint->bEndpointAddress;
1034 port->interrupt_out_buffer = kmalloc(buffer_size,
1035 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 if (!port->interrupt_out_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001037 dev_err(&interface->dev,
1038 "Couldn't allocate interrupt_out_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 goto probe_error;
1040 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001041 usb_fill_int_urb(port->interrupt_out_urb, dev,
1042 usb_sndintpipe(dev,
1043 endpoint->bEndpointAddress),
1044 port->interrupt_out_buffer, buffer_size,
1045 serial->type->write_int_callback, port,
1046 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 }
1048 } else if (num_interrupt_out) {
1049 dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined");
1050 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001051
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 /* if this device type has an attach function, call it */
1053 if (type->attach) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -07001054 if (!try_module_get(type->driver.owner)) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001055 dev_err(&interface->dev,
1056 "module get failed, exiting\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 goto probe_error;
1058 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001059 retval = type->attach(serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -07001060 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 if (retval < 0)
1062 goto probe_error;
1063 if (retval > 0) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001064 /* quietly accept this device, but don't bind to a
1065 serial port as it's about to disappear */
Alan Stern0a3c8542009-05-27 11:25:52 -04001066 serial->num_ports = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 goto exit;
1068 }
1069 }
1070
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001071 if (get_free_serial(serial, num_ports, &minor) == NULL) {
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001072 dev_err(&interface->dev, "No more free serial devices\n");
1073 goto probe_error;
1074 }
Oliver Neukumc744f992007-02-26 15:43:00 +01001075 serial->minor = minor;
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001076
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077 /* register all of the individual ports with the driver core */
1078 for (i = 0; i < num_ports; ++i) {
1079 port = serial->port[i];
1080 port->dev.parent = &interface->dev;
1081 port->dev.driver = NULL;
1082 port->dev.bus = &usb_serial_bus_type;
1083 port->dev.release = &port_release;
1084
Kay Sievers0031a062008-05-02 06:02:41 +02001085 dev_set_name(&port->dev, "ttyUSB%d", port->number);
Kay Sievers7071a3c2008-05-02 06:02:41 +02001086 dbg ("%s - registering %s", __func__, dev_name(&port->dev));
Alan Sternc706ebd2009-06-02 11:54:11 -04001087 port->dev_state = PORT_REGISTERING;
Greg Kroah-Hartman13f4db92006-08-28 11:43:25 -07001088 retval = device_register(&port->dev);
Alan Sternc706ebd2009-06-02 11:54:11 -04001089 if (retval) {
Greg Kroah-Hartman13f4db92006-08-28 11:43:25 -07001090 dev_err(&port->dev, "Error registering port device, "
1091 "continuing\n");
Alan Sternc706ebd2009-06-02 11:54:11 -04001092 port->dev_state = PORT_UNREGISTERED;
1093 } else {
1094 port->dev_state = PORT_REGISTERED;
1095 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 }
1097
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001098 usb_serial_console_init(debug, minor);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099
1100exit:
1101 /* success */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001102 usb_set_intfdata(interface, serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 return 0;
1104
1105probe_error:
1106 for (i = 0; i < num_bulk_in; ++i) {
1107 port = serial->port[i];
1108 if (!port)
1109 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001110 usb_free_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 kfree(port->bulk_in_buffer);
1112 }
1113 for (i = 0; i < num_bulk_out; ++i) {
1114 port = serial->port[i];
1115 if (!port)
1116 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001117 usb_free_urb(port->write_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118 kfree(port->bulk_out_buffer);
1119 }
1120 for (i = 0; i < num_interrupt_in; ++i) {
1121 port = serial->port[i];
1122 if (!port)
1123 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001124 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 kfree(port->interrupt_in_buffer);
1126 }
1127 for (i = 0; i < num_interrupt_out; ++i) {
1128 port = serial->port[i];
1129 if (!port)
1130 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001131 usb_free_urb(port->interrupt_out_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 kfree(port->interrupt_out_buffer);
1133 }
1134
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 /* free up any memory that we allocated */
1136 for (i = 0; i < serial->num_port_pointers; ++i)
1137 kfree(serial->port[i]);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001138 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139 return -EIO;
1140}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001141EXPORT_SYMBOL_GPL(usb_serial_probe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142
1143void usb_serial_disconnect(struct usb_interface *interface)
1144{
1145 int i;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001146 struct usb_serial *serial = usb_get_intfdata(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 struct device *dev = &interface->dev;
1148 struct usb_serial_port *port;
1149
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +02001150 usb_serial_console_disconnect(serial);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001151 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001153 mutex_lock(&serial->disc_mutex);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001154 usb_set_intfdata(interface, NULL);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001155 /* must set a flag, to signal subdrivers */
1156 serial->disconnected = 1;
Alan Stern2d931482009-04-14 11:31:02 -04001157 mutex_unlock(&serial->disc_mutex);
1158
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001159 for (i = 0; i < serial->num_ports; ++i) {
1160 port = serial->port[i];
1161 if (port) {
Alan Cox4a90f092008-10-13 10:39:46 +01001162 struct tty_struct *tty = tty_port_tty_get(&port->port);
1163 if (tty) {
Alan Cox335f8512009-06-11 12:26:29 +01001164 /* The hangup will occur asynchronously but
1165 the object refcounts will sort out all the
1166 cleanup */
Alan Cox4a90f092008-10-13 10:39:46 +01001167 tty_hangup(tty);
1168 tty_kref_put(tty);
1169 }
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001170 kill_traffic(port);
Alan Stern2d931482009-04-14 11:31:02 -04001171 cancel_work_sync(&port->work);
Alan Sternc706ebd2009-06-02 11:54:11 -04001172 if (port->dev_state == PORT_REGISTERED) {
1173
1174 /* Make sure the port is bound so that the
1175 * driver's port_remove method is called.
1176 */
1177 if (!port->dev.driver) {
1178 int rc;
1179
1180 port->dev.driver =
1181 &serial->type->driver;
1182 rc = device_bind_driver(&port->dev);
1183 }
1184 port->dev_state = PORT_UNREGISTERING;
1185 device_del(&port->dev);
1186 port->dev_state = PORT_UNREGISTERED;
1187 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 }
Alan Sternf9c99bb2009-06-02 11:53:55 -04001190 serial->type->disconnect(serial);
Alan Stern2d931482009-04-14 11:31:02 -04001191
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001192 /* let the last holder of this object
1193 * cause it to be cleaned up */
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001194 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195 dev_info(dev, "device disconnected\n");
1196}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001197EXPORT_SYMBOL_GPL(usb_serial_disconnect);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198
Oliver Neukumec225592007-04-27 20:54:57 +02001199int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
1200{
1201 struct usb_serial *serial = usb_get_intfdata(intf);
1202 struct usb_serial_port *port;
1203 int i, r = 0;
1204
Oliver Neukumf8bece82009-02-05 16:54:25 +01001205 serial->suspending = 1;
1206
Oliver Neukume31c1882007-07-23 08:58:39 +02001207 for (i = 0; i < serial->num_ports; ++i) {
1208 port = serial->port[i];
1209 if (port)
1210 kill_traffic(port);
Oliver Neukumec225592007-04-27 20:54:57 +02001211 }
1212
1213 if (serial->type->suspend)
Oliver Neukume31c1882007-07-23 08:58:39 +02001214 r = serial->type->suspend(serial, message);
Oliver Neukumec225592007-04-27 20:54:57 +02001215
1216 return r;
1217}
1218EXPORT_SYMBOL(usb_serial_suspend);
1219
1220int usb_serial_resume(struct usb_interface *intf)
1221{
1222 struct usb_serial *serial = usb_get_intfdata(intf);
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001223 int rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001224
Oliver Neukumf8bece82009-02-05 16:54:25 +01001225 serial->suspending = 0;
Sarah Sharp8abaee22007-10-25 10:58:43 -07001226 if (serial->type->resume)
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001227 rv = serial->type->resume(serial);
1228 else
1229 rv = usb_serial_generic_resume(serial);
Oliver Neukumf8bece82009-02-05 16:54:25 +01001230
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001231 return rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001232}
1233EXPORT_SYMBOL(usb_serial_resume);
1234
Jeff Dikeb68e31d2006-10-02 02:17:18 -07001235static const struct tty_operations serial_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236 .open = serial_open,
1237 .close = serial_close,
1238 .write = serial_write,
Alan Cox335f8512009-06-11 12:26:29 +01001239 .hangup = serial_hangup,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240 .write_room = serial_write_room,
1241 .ioctl = serial_ioctl,
1242 .set_termios = serial_set_termios,
1243 .throttle = serial_throttle,
1244 .unthrottle = serial_unthrottle,
1245 .break_ctl = serial_break,
1246 .chars_in_buffer = serial_chars_in_buffer,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247 .tiocmget = serial_tiocmget,
1248 .tiocmset = serial_tiocmset,
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -07001249 .proc_fops = &serial_proc_fops,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250};
1251
Alan Cox335f8512009-06-11 12:26:29 +01001252
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253struct tty_driver *usb_serial_tty_driver;
1254
1255static int __init usb_serial_init(void)
1256{
1257 int i;
1258 int result;
1259
1260 usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS);
1261 if (!usb_serial_tty_driver)
1262 return -ENOMEM;
1263
1264 /* Initialize our global data */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001265 for (i = 0; i < SERIAL_TTY_MINORS; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 serial_table[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267
1268 result = bus_register(&usb_serial_bus_type);
1269 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001270 printk(KERN_ERR "usb-serial: %s - registering bus driver "
1271 "failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272 goto exit_bus;
1273 }
1274
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275 usb_serial_tty_driver->owner = THIS_MODULE;
1276 usb_serial_tty_driver->driver_name = "usbserial";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277 usb_serial_tty_driver->name = "ttyUSB";
1278 usb_serial_tty_driver->major = SERIAL_TTY_MAJOR;
1279 usb_serial_tty_driver->minor_start = 0;
1280 usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
1281 usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001282 usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW |
1283 TTY_DRIVER_DYNAMIC_DEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284 usb_serial_tty_driver->init_termios = tty_std_termios;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001285 usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD
1286 | HUPCL | CLOCAL;
Alan Coxa5b6f602008-04-08 17:16:06 +01001287 usb_serial_tty_driver->init_termios.c_ispeed = 9600;
1288 usb_serial_tty_driver->init_termios.c_ospeed = 9600;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289 tty_set_operations(usb_serial_tty_driver, &serial_ops);
1290 result = tty_register_driver(usb_serial_tty_driver);
1291 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001292 printk(KERN_ERR "usb-serial: %s - tty_register_driver failed\n",
1293 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294 goto exit_reg_driver;
1295 }
1296
1297 /* register the USB driver */
1298 result = usb_register(&usb_serial_driver);
1299 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001300 printk(KERN_ERR "usb-serial: %s - usb_register failed\n",
1301 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302 goto exit_tty;
1303 }
1304
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001305 /* register the generic driver, if we should */
1306 result = usb_serial_generic_register(debug);
1307 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001308 printk(KERN_ERR "usb-serial: %s - registering generic "
1309 "driver failed\n", __func__);
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001310 goto exit_generic;
1311 }
1312
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001313 printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314
1315 return result;
1316
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001317exit_generic:
1318 usb_deregister(&usb_serial_driver);
1319
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320exit_tty:
1321 tty_unregister_driver(usb_serial_tty_driver);
1322
1323exit_reg_driver:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324 bus_unregister(&usb_serial_bus_type);
1325
1326exit_bus:
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001327 printk(KERN_ERR "usb-serial: %s - returning with error %d\n",
1328 __func__, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329 put_tty_driver(usb_serial_tty_driver);
1330 return result;
1331}
1332
1333
1334static void __exit usb_serial_exit(void)
1335{
1336 usb_serial_console_exit();
1337
1338 usb_serial_generic_deregister();
1339
1340 usb_deregister(&usb_serial_driver);
1341 tty_unregister_driver(usb_serial_tty_driver);
1342 put_tty_driver(usb_serial_tty_driver);
1343 bus_unregister(&usb_serial_bus_type);
1344}
1345
1346
1347module_init(usb_serial_init);
1348module_exit(usb_serial_exit);
1349
1350#define set_to_generic_if_null(type, function) \
1351 do { \
1352 if (!type->function) { \
1353 type->function = usb_serial_generic_##function; \
1354 dbg("Had to override the " #function \
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001355 " usb serial operation with the generic one.");\
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356 } \
1357 } while (0)
1358
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001359static void fixup_generic(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360{
1361 set_to_generic_if_null(device, open);
1362 set_to_generic_if_null(device, write);
1363 set_to_generic_if_null(device, close);
1364 set_to_generic_if_null(device, write_room);
1365 set_to_generic_if_null(device, chars_in_buffer);
1366 set_to_generic_if_null(device, read_bulk_callback);
1367 set_to_generic_if_null(device, write_bulk_callback);
Alan Sternf9c99bb2009-06-02 11:53:55 -04001368 set_to_generic_if_null(device, disconnect);
1369 set_to_generic_if_null(device, release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370}
1371
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001372int usb_serial_register(struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001374 /* must be called with BKL held */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 int retval;
1376
Dave Younge4abe662009-02-14 21:21:13 +08001377 if (usb_disabled())
1378 return -ENODEV;
1379
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001380 fixup_generic(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001382 if (!driver->description)
1383 driver->description = driver->driver.name;
1384
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 /* Add this device to our list of devices */
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001386 list_add(&driver->driver_list, &usb_serial_driver_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001388 retval = usb_serial_bus_register(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389 if (retval) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001390 printk(KERN_ERR "usb-serial: problem %d when registering "
1391 "driver %s\n", retval, driver->description);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001392 list_del(&driver->driver_list);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001393 } else
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001394 printk(KERN_INFO "USB Serial support registered for %s\n",
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001395 driver->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396
1397 return retval;
1398}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001399EXPORT_SYMBOL_GPL(usb_serial_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400
1401
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001402void usb_serial_deregister(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001404 /* must be called with BKL held */
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001405 printk(KERN_INFO "USB Serial deregistering driver %s\n",
1406 device->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407 list_del(&device->driver_list);
1408 usb_serial_bus_deregister(device);
1409}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410EXPORT_SYMBOL_GPL(usb_serial_deregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411
1412/* Module information */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001413MODULE_AUTHOR(DRIVER_AUTHOR);
1414MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415MODULE_LICENSE("GPL");
1416
1417module_param(debug, bool, S_IRUGO | S_IWUSR);
1418MODULE_PARM_DESC(debug, "Debug enabled or not");