blob: 3c8923f62ed15aa425cfe07fee7c1d0b717ae067 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * USB Serial Converter driver
3 *
Greg Kroah-Hartman502b95c2005-06-20 21:15:16 -07004 * Copyright (C) 1999 - 2005 Greg Kroah-Hartman (greg@kroah.com)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 * Copyright (C) 2000 Peter Berger (pberger@brimson.com)
6 * Copyright (C) 2000 Al Borchers (borchers@steinerpoint.com)
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version
10 * 2 as published by the Free Software Foundation.
11 *
Greg Kroah-Hartman502b95c2005-06-20 21:15:16 -070012 * This driver was originally based on the ACM driver by Armin Fuerst (which was
Linus Torvalds1da177e2005-04-16 15:20:36 -070013 * based on a driver by Brad Keryan)
14 *
Alan Coxa8d6f0a2008-07-22 11:12:24 +010015 * See Documentation/usb/usb-serial.txt for more information on using this
16 * driver
Linus Torvalds1da177e2005-04-16 15:20:36 -070017 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 */
19
Linus Torvalds1da177e2005-04-16 15:20:36 -070020#include <linux/kernel.h>
21#include <linux/errno.h>
22#include <linux/init.h>
23#include <linux/slab.h>
Alexey Dobriyan405f5572009-07-11 22:08:37 +040024#include <linux/smp_lock.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <linux/tty.h>
26#include <linux/tty_driver.h>
27#include <linux/tty_flip.h>
28#include <linux/module.h>
29#include <linux/moduleparam.h>
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -070030#include <linux/seq_file.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <linux/spinlock.h>
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -030032#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/list.h>
Alan Coxa8d6f0a2008-07-22 11:12:24 +010034#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/usb.h>
Greg Kroah-Hartmana9698882006-07-11 21:22:58 -070036#include <linux/usb/serial.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include "pl2303.h"
38
39/*
40 * Version Information
41 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/"
43#define DRIVER_DESC "USB Serial Driver core"
44
Pete Zaitcev34f8e762006-06-21 15:00:45 -070045static void port_free(struct usb_serial_port *port);
46
Linus Torvalds1da177e2005-04-16 15:20:36 -070047/* Driver structure we register with the USB core */
48static struct usb_driver usb_serial_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070049 .name = "usbserial",
50 .probe = usb_serial_probe,
51 .disconnect = usb_serial_disconnect,
Oliver Neukumec225592007-04-27 20:54:57 +020052 .suspend = usb_serial_suspend,
53 .resume = usb_serial_resume,
Greg Kroah-Hartmanba9dc652005-11-16 13:41:28 -080054 .no_dynamic_id = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -070055};
56
57/* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead
58 the MODULE_DEVICE_TABLE declarations in each serial driver
59 cause the "hotplug" program to pull in whatever module is necessary
60 via modprobe, and modprobe will load usbserial because the serial
61 drivers depend on it.
62*/
63
64static int debug;
Alan Coxa8d6f0a2008-07-22 11:12:24 +010065/* initially all NULL */
66static struct usb_serial *serial_table[SERIAL_TTY_MINORS];
Oliver Neukum3ddad822007-07-24 15:13:42 +020067static DEFINE_MUTEX(table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070068static LIST_HEAD(usb_serial_driver_list);
69
70struct usb_serial *usb_serial_get_by_index(unsigned index)
71{
Oliver Neukum34ef50e2007-01-13 07:29:26 +010072 struct usb_serial *serial;
73
Oliver Neukum3ddad822007-07-24 15:13:42 +020074 mutex_lock(&table_lock);
Oliver Neukum34ef50e2007-01-13 07:29:26 +010075 serial = serial_table[index];
Linus Torvalds1da177e2005-04-16 15:20:36 -070076
77 if (serial)
78 kref_get(&serial->kref);
Oliver Neukum3ddad822007-07-24 15:13:42 +020079 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070080 return serial;
81}
82
Alan Coxa8d6f0a2008-07-22 11:12:24 +010083static struct usb_serial *get_free_serial(struct usb_serial *serial,
84 int num_ports, unsigned int *minor)
Linus Torvalds1da177e2005-04-16 15:20:36 -070085{
86 unsigned int i, j;
87 int good_spot;
88
Harvey Harrison441b62c2008-03-03 16:08:34 -080089 dbg("%s %d", __func__, num_ports);
Linus Torvalds1da177e2005-04-16 15:20:36 -070090
91 *minor = 0;
Oliver Neukum3ddad822007-07-24 15:13:42 +020092 mutex_lock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070093 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
94 if (serial_table[i])
95 continue;
96
97 good_spot = 1;
98 for (j = 1; j <= num_ports-1; ++j)
99 if ((i+j >= SERIAL_TTY_MINORS) || (serial_table[i+j])) {
100 good_spot = 0;
101 i += j;
102 break;
103 }
104 if (good_spot == 0)
105 continue;
106
107 *minor = i;
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100108 j = 0;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800109 dbg("%s - minor base = %d", __func__, *minor);
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100110 for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111 serial_table[i] = serial;
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100112 serial->port[j++]->number = i;
113 }
Oliver Neukum3ddad822007-07-24 15:13:42 +0200114 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115 return serial;
116 }
Oliver Neukum3ddad822007-07-24 15:13:42 +0200117 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 return NULL;
119}
120
121static void return_serial(struct usb_serial *serial)
122{
123 int i;
124
Harvey Harrison441b62c2008-03-03 16:08:34 -0800125 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100127 for (i = 0; i < serial->num_ports; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128 serial_table[serial->minor + i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129}
130
131static void destroy_serial(struct kref *kref)
132{
133 struct usb_serial *serial;
134 struct usb_serial_port *port;
135 int i;
136
137 serial = to_usb_serial(kref);
138
Harvey Harrison441b62c2008-03-03 16:08:34 -0800139 dbg("%s - %s", __func__, serial->type->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140
Jim Radford521b85a2007-03-13 08:30:50 -0700141 /* return the minor range that this device had */
Alan Stern0282b7f2008-07-29 12:01:04 -0400142 if (serial->minor != SERIAL_TTY_NO_MINOR)
143 return_serial(serial);
Jim Radford521b85a2007-03-13 08:30:50 -0700144
Alan Sternf9c99bb2009-06-02 11:53:55 -0400145 serial->type->release(serial);
146
147 for (i = 0; i < serial->num_ports; ++i) {
148 port = serial->port[i];
149 if (port)
150 put_device(&port->dev);
151 }
152
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153 /* If this is a "fake" port, we have to clean it up here, as it will
154 * not get cleaned up in port_release() as it was never registered with
155 * the driver core */
156 if (serial->num_ports < serial->num_port_pointers) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100157 for (i = serial->num_ports;
158 i < serial->num_port_pointers; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 port = serial->port[i];
Alan Sternf9c99bb2009-06-02 11:53:55 -0400160 if (port)
161 port_free(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 }
163 }
164
165 usb_put_dev(serial->dev);
166
167 /* free up any memory that we allocated */
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100168 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169}
170
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200171void usb_serial_put(struct usb_serial *serial)
172{
Oliver Neukum3ddad822007-07-24 15:13:42 +0200173 mutex_lock(&table_lock);
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200174 kref_put(&serial->kref, destroy_serial);
Oliver Neukum3ddad822007-07-24 15:13:42 +0200175 mutex_unlock(&table_lock);
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200176}
177
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178/*****************************************************************************
179 * Driver tty interface functions
180 *****************************************************************************/
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100181static int serial_open (struct tty_struct *tty, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182{
183 struct usb_serial *serial;
184 struct usb_serial_port *port;
185 unsigned int portNumber;
Alan Stern2d931482009-04-14 11:31:02 -0400186 int retval = 0;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100187
Harvey Harrison441b62c2008-03-03 16:08:34 -0800188 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189
190 /* get the serial object associated with this tty pointer */
191 serial = usb_serial_get_by_index(tty->index);
192 if (!serial) {
193 tty->driver_data = NULL;
194 return -ENODEV;
195 }
196
Alan Stern2d931482009-04-14 11:31:02 -0400197 mutex_lock(&serial->disc_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198 portNumber = tty->index - serial->minor;
199 port = serial->port[portNumber];
Alan Stern2d931482009-04-14 11:31:02 -0400200 if (!port || serial->disconnected)
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300201 retval = -ENODEV;
Alan Stern2d931482009-04-14 11:31:02 -0400202 else
203 get_device(&port->dev);
204 /*
205 * Note: Our locking order requirement does not allow port->mutex
206 * to be acquired while serial->disc_mutex is held.
207 */
208 mutex_unlock(&serial->disc_mutex);
209 if (retval)
210 goto bailout_serial_put;
James Woodcock331879f2009-02-11 15:06:53 +0000211
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300212 if (mutex_lock_interruptible(&port->mutex)) {
213 retval = -ERESTARTSYS;
Alan Stern2d931482009-04-14 11:31:02 -0400214 goto bailout_port_put;
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300215 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100216
Alan Cox95da3102008-07-22 11:09:07 +0100217 ++port->port.count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218
Paul Fulghumca854852006-04-13 22:28:17 +0200219 /* set up our port structure making the tty driver
220 * remember our port object, and us it */
221 tty->driver_data = port;
Alan Cox4a90f092008-10-13 10:39:46 +0100222 tty_port_tty_set(&port->port, tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223
Jason Wessel6e406122009-06-22 11:32:20 -0500224 /* If the console is attached, the device is already open */
225 if (port->port.count == 1 && !port->console) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226
227 /* lock this module before we call it
228 * this may fail, which means we must bail out,
229 * safe because we are called with BKL held */
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700230 if (!try_module_get(serial->type->driver.owner)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231 retval = -ENODEV;
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300232 goto bailout_mutex_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 }
234
Alan Stern2d931482009-04-14 11:31:02 -0400235 mutex_lock(&serial->disc_mutex);
236 if (serial->disconnected)
237 retval = -ENODEV;
238 else
239 retval = usb_autopm_get_interface(serial->interface);
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800240 if (retval)
241 goto bailout_module_put;
Alan Stern2d931482009-04-14 11:31:02 -0400242
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100243 /* only call the device specific open if this
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 * is the first time the port is opened */
Alan Cox95da3102008-07-22 11:09:07 +0100245 retval = serial->type->open(tty, port, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246 if (retval)
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800247 goto bailout_interface_put;
Alan Stern2d931482009-04-14 11:31:02 -0400248 mutex_unlock(&serial->disc_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249 }
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300250 mutex_unlock(&port->mutex);
Alan Cox335f8512009-06-11 12:26:29 +0100251 /* Now do the correct tty layer semantics */
252 retval = tty_port_block_til_ready(&port->port, tty, filp);
253 if (retval == 0)
254 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800256bailout_interface_put:
257 usb_autopm_put_interface(serial->interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258bailout_module_put:
Alan Stern2d931482009-04-14 11:31:02 -0400259 mutex_unlock(&serial->disc_mutex);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700260 module_put(serial->type->driver.owner);
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300261bailout_mutex_unlock:
Alan Cox95da3102008-07-22 11:09:07 +0100262 port->port.count = 0;
Frank Gevaertsb059c812006-06-14 15:52:05 +0200263 tty->driver_data = NULL;
Alan Cox4a90f092008-10-13 10:39:46 +0100264 tty_port_tty_set(&port->port, NULL);
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300265 mutex_unlock(&port->mutex);
Alan Stern2d931482009-04-14 11:31:02 -0400266bailout_port_put:
267 put_device(&port->dev);
268bailout_serial_put:
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200269 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 return retval;
271}
272
Alan Cox335f8512009-06-11 12:26:29 +0100273/**
274 * serial_do_down - shut down hardware
275 * @port: port to shut down
276 *
277 * Shut down a USB port unless it is the console. We never shut down the
278 * console hardware as it will always be in use.
279 *
280 * Don't free any resources at this point
281 */
282static void serial_do_down(struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283{
Alan Cox335f8512009-06-11 12:26:29 +0100284 struct usb_serial_driver *drv = port->serial->type;
Alan Stern2d931482009-04-14 11:31:02 -0400285 struct usb_serial *serial;
286 struct module *owner;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287
Alan Cox335f8512009-06-11 12:26:29 +0100288 /* The console is magical, do not hang up the console hardware
289 or there will be tears */
290 if (port->console)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 return;
292
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300293 mutex_lock(&port->mutex);
Alan Stern2d931482009-04-14 11:31:02 -0400294 serial = port->serial;
295 owner = serial->type->driver.owner;
Luiz Fernando Capitulino8a4613f2005-11-28 19:16:07 -0200296
Alan Cox335f8512009-06-11 12:26:29 +0100297 if (drv->close)
298 drv->close(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300300 mutex_unlock(&port->mutex);
Alan Cox335f8512009-06-11 12:26:29 +0100301}
302
303/**
304 * serial_do_free - free resources post close/hangup
305 * @port: port to free up
306 *
307 * Do the resource freeing and refcount dropping for the port. We must
308 * be careful about ordering and we must avoid freeing up the console.
309 */
310
311static void serial_do_free(struct usb_serial_port *port)
312{
313 struct usb_serial *serial;
314 struct module *owner;
315
316 /* The console is magical, do not hang up the console hardware
317 or there will be tears */
318 if (port->console)
319 return;
320
321 serial = port->serial;
322 owner = serial->type->driver.owner;
Alan Stern2d931482009-04-14 11:31:02 -0400323 put_device(&port->dev);
Alan Stern2d931482009-04-14 11:31:02 -0400324 /* Mustn't dereference port any more */
Alan Cox335f8512009-06-11 12:26:29 +0100325 mutex_lock(&serial->disc_mutex);
326 if (!serial->disconnected)
327 usb_autopm_put_interface(serial->interface);
328 mutex_unlock(&serial->disc_mutex);
Alan Stern2d931482009-04-14 11:31:02 -0400329 usb_serial_put(serial);
Alan Stern2d931482009-04-14 11:31:02 -0400330 /* Mustn't dereference serial any more */
Alan Cox335f8512009-06-11 12:26:29 +0100331 module_put(owner);
332}
333
334static void serial_close(struct tty_struct *tty, struct file *filp)
335{
336 struct usb_serial_port *port = tty->driver_data;
337
Thadeu Lima de Souza Cascardof4fa4462009-06-25 14:41:37 +0100338 if (!port)
339 return;
340
Alan Cox335f8512009-06-11 12:26:29 +0100341 dbg("%s - port %d", __func__, port->number);
342
Alan Coxb68f2fb2009-07-27 10:58:08 +0100343 /* FIXME:
344 This leaves a very narrow race. Really we should do the
345 serial_do_free() on tty->shutdown(), but tty->shutdown can
346 be called from IRQ context and serial_do_free can sleep.
347
348 The right fix is probably to make the tty free (which is rare)
349 and thus tty->shutdown() occur via a work queue and simplify all
350 the drivers that use it.
351 */
352 if (tty_hung_up_p(filp)) {
353 /* serial_hangup already called serial_down at this point.
354 Another user may have already reopened the port but
355 serial_do_free is refcounted */
356 serial_do_free(port);
357 return;
358 }
Alan Cox335f8512009-06-11 12:26:29 +0100359
360 if (tty_port_close_start(&port->port, tty, filp) == 0)
361 return;
362
363 serial_do_down(port);
364 tty_port_close_end(&port->port, tty);
365 tty_port_tty_set(&port->port, NULL);
366 serial_do_free(port);
367}
368
369static void serial_hangup(struct tty_struct *tty)
370{
371 struct usb_serial_port *port = tty->driver_data;
372 serial_do_down(port);
373 tty_port_hangup(&port->port);
Alan Coxb68f2fb2009-07-27 10:58:08 +0100374 /* We must not free port yet - the USB serial layer depends on it's
375 continued existence */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376}
377
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100378static int serial_write(struct tty_struct *tty, const unsigned char *buf,
379 int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200381 struct usb_serial_port *port = tty->driver_data;
Oliver Neukum3ff4fd92007-01-13 07:32:27 +0100382 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383
Alan Coxf34d7a52008-04-30 00:54:13 -0700384 if (port->serial->dev->state == USB_STATE_NOTATTACHED)
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200385 goto exit;
386
Harvey Harrison441b62c2008-03-03 16:08:34 -0800387 dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388
Alan Cox95da3102008-07-22 11:09:07 +0100389 /* count is managed under the mutex lock for the tty so cannot
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100390 drop to zero until after the last close completes */
Alan Cox95da3102008-07-22 11:09:07 +0100391 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392
393 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100394 retval = port->serial->type->write(tty, port, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395
396exit:
397 return retval;
398}
399
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100400static int serial_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200402 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800403 dbg("%s - port %d", __func__, port->number);
Alan Cox95da3102008-07-22 11:09:07 +0100404 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100406 return port->serial->type->write_room(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407}
408
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100409static int serial_chars_in_buffer(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200411 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800412 dbg("%s = port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413
Alan Cox95da3102008-07-22 11:09:07 +0100414 WARN_ON(!port->port.count);
Alan Coxeff69372009-01-02 13:47:06 +0000415 /* if the device was unplugged then any remaining characters
416 fell out of the connector ;) */
417 if (port->serial->disconnected)
418 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100420 return port->serial->type->chars_in_buffer(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421}
422
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100423static void serial_throttle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200425 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800426 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427
Alan Cox95da3102008-07-22 11:09:07 +0100428 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 /* pass on to the driver specific version of this function */
430 if (port->serial->type->throttle)
Alan Cox95da3102008-07-22 11:09:07 +0100431 port->serial->type->throttle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432}
433
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100434static void serial_unthrottle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200436 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800437 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438
Alan Cox95da3102008-07-22 11:09:07 +0100439 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 /* pass on to the driver specific version of this function */
441 if (port->serial->type->unthrottle)
Alan Cox95da3102008-07-22 11:09:07 +0100442 port->serial->type->unthrottle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443}
444
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100445static int serial_ioctl(struct tty_struct *tty, struct file *file,
446 unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200448 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 int retval = -ENODEV;
450
Harvey Harrison441b62c2008-03-03 16:08:34 -0800451 dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452
Alan Cox95da3102008-07-22 11:09:07 +0100453 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100455 /* pass on to the driver specific version of this function
456 if it is available */
Alan Coxf34d7a52008-04-30 00:54:13 -0700457 if (port->serial->type->ioctl) {
Alan Cox95da3102008-07-22 11:09:07 +0100458 retval = port->serial->type->ioctl(tty, file, cmd, arg);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100459 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 retval = -ENOIOCTLCMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461 return retval;
462}
463
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100464static void serial_set_termios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200466 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800467 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468
Alan Cox95da3102008-07-22 11:09:07 +0100469 WARN_ON(!port->port.count);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100470 /* pass on to the driver specific version of this function
471 if it is available */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 if (port->serial->type->set_termios)
Alan Cox95da3102008-07-22 11:09:07 +0100473 port->serial->type->set_termios(tty, port, old);
Alan Cox33785092007-10-18 01:24:22 -0700474 else
475 tty_termios_copy_hw(tty->termios, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476}
477
Alan Cox9e98966c2008-07-22 11:18:03 +0100478static int serial_break(struct tty_struct *tty, int break_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200480 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481
Harvey Harrison441b62c2008-03-03 16:08:34 -0800482 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483
Alan Cox95da3102008-07-22 11:09:07 +0100484 WARN_ON(!port->port.count);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100485 /* pass on to the driver specific version of this function
486 if it is available */
Alan Cox6b447f042009-01-02 13:48:56 +0000487 if (port->serial->type->break_ctl)
Alan Cox95da3102008-07-22 11:09:07 +0100488 port->serial->type->break_ctl(tty, break_state);
Alan Cox9e98966c2008-07-22 11:18:03 +0100489 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490}
491
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700492static int serial_proc_show(struct seq_file *m, void *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493{
494 struct usb_serial *serial;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 char tmp[40];
497
Harvey Harrison441b62c2008-03-03 16:08:34 -0800498 dbg("%s", __func__);
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700499 seq_puts(m, "usbserinfo:1.0 driver:2.0\n");
500 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 serial = usb_serial_get_by_index(i);
502 if (serial == NULL)
503 continue;
504
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700505 seq_printf(m, "%d:", i);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700506 if (serial->type->driver.owner)
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700507 seq_printf(m, " module:%s",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100508 module_name(serial->type->driver.owner));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700509 seq_printf(m, " name:\"%s\"",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100510 serial->type->description);
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700511 seq_printf(m, " vendor:%04x product:%04x",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100512 le16_to_cpu(serial->dev->descriptor.idVendor),
513 le16_to_cpu(serial->dev->descriptor.idProduct));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700514 seq_printf(m, " num_ports:%d", serial->num_ports);
515 seq_printf(m, " port:%d", i - serial->minor + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 usb_make_path(serial->dev, tmp, sizeof(tmp));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700517 seq_printf(m, " path:%s", tmp);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100518
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700519 seq_putc(m, '\n');
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200520 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 }
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700522 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523}
524
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700525static int serial_proc_open(struct inode *inode, struct file *file)
526{
527 return single_open(file, serial_proc_show, NULL);
528}
529
530static const struct file_operations serial_proc_fops = {
531 .owner = THIS_MODULE,
532 .open = serial_proc_open,
533 .read = seq_read,
534 .llseek = seq_lseek,
535 .release = single_release,
536};
537
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100538static int serial_tiocmget(struct tty_struct *tty, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200540 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541
Harvey Harrison441b62c2008-03-03 16:08:34 -0800542 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543
Alan Cox95da3102008-07-22 11:09:07 +0100544 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 if (port->serial->type->tiocmget)
Alan Cox95da3102008-07-22 11:09:07 +0100546 return port->serial->type->tiocmget(tty, file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 return -EINVAL;
548}
549
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100550static int serial_tiocmset(struct tty_struct *tty, struct file *file,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 unsigned int set, unsigned int clear)
552{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200553 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554
Harvey Harrison441b62c2008-03-03 16:08:34 -0800555 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556
Alan Cox95da3102008-07-22 11:09:07 +0100557 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 if (port->serial->type->tiocmset)
Alan Cox95da3102008-07-22 11:09:07 +0100559 return port->serial->type->tiocmset(tty, file, set, clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 return -EINVAL;
561}
562
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700563/*
564 * We would be calling tty_wakeup here, but unfortunately some line
565 * disciplines have an annoying habit of calling tty->write from
566 * the write wakeup callback (e.g. n_hdlc.c).
567 */
568void usb_serial_port_softint(struct usb_serial_port *port)
569{
570 schedule_work(&port->work);
571}
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100572EXPORT_SYMBOL_GPL(usb_serial_port_softint);
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700573
David Howellsc4028952006-11-22 14:57:56 +0000574static void usb_serial_port_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575{
David Howellsc4028952006-11-22 14:57:56 +0000576 struct usb_serial_port *port =
577 container_of(work, struct usb_serial_port, work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578 struct tty_struct *tty;
579
Harvey Harrison441b62c2008-03-03 16:08:34 -0800580 dbg("%s - port %d", __func__, port->number);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100581
Alan Cox4a90f092008-10-13 10:39:46 +0100582 tty = tty_port_tty_get(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 if (!tty)
584 return;
585
586 tty_wakeup(tty);
Alan Cox4a90f092008-10-13 10:39:46 +0100587 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588}
589
590static void port_release(struct device *dev)
591{
592 struct usb_serial_port *port = to_usb_serial_port(dev);
593
Kay Sievers7071a3c2008-05-02 06:02:41 +0200594 dbg ("%s - %s", __func__, dev_name(dev));
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700595 port_free(port);
596}
597
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100598static void kill_traffic(struct usb_serial_port *port)
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700599{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601 usb_kill_urb(port->write_urb);
Oliver Neukum5adceac2007-08-17 14:01:38 +0200602 /*
603 * This is tricky.
604 * Some drivers submit the read_urb in the
605 * handler for the write_urb or vice versa
606 * this order determines the order in which
607 * usb_kill_urb() must be used to reliably
608 * kill the URBs. As it is unknown here,
609 * both orders must be used in turn.
610 * The call below is not redundant.
611 */
612 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 usb_kill_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 usb_kill_urb(port->interrupt_out_urb);
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100615}
616
617static void port_free(struct usb_serial_port *port)
618{
Alan Stern2d931482009-04-14 11:31:02 -0400619 /*
620 * Stop all the traffic before cancelling the work, so that
621 * nobody will restart it by calling usb_serial_port_softint.
622 */
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100623 kill_traffic(port);
Alan Stern2d931482009-04-14 11:31:02 -0400624 cancel_work_sync(&port->work);
625
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100626 usb_free_urb(port->read_urb);
627 usb_free_urb(port->write_urb);
628 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629 usb_free_urb(port->interrupt_out_urb);
630 kfree(port->bulk_in_buffer);
631 kfree(port->bulk_out_buffer);
632 kfree(port->interrupt_in_buffer);
633 kfree(port->interrupt_out_buffer);
634 kfree(port);
635}
636
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100637static struct usb_serial *create_serial(struct usb_device *dev,
638 struct usb_interface *interface,
639 struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640{
641 struct usb_serial *serial;
642
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100643 serial = kzalloc(sizeof(*serial), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644 if (!serial) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800645 dev_err(&dev->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 return NULL;
647 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 serial->dev = usb_get_dev(dev);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700649 serial->type = driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 serial->interface = interface;
651 kref_init(&serial->kref);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +0100652 mutex_init(&serial->disc_mutex);
Alan Stern0282b7f2008-07-29 12:01:04 -0400653 serial->minor = SERIAL_TTY_NO_MINOR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654
655 return serial;
656}
657
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100658static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf,
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100659 struct usb_serial_driver *drv)
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100660{
661 struct usb_dynid *dynid;
662
663 spin_lock(&drv->dynids.lock);
664 list_for_each_entry(dynid, &drv->dynids.list, node) {
665 if (usb_match_one_id(intf, &dynid->id)) {
666 spin_unlock(&drv->dynids.lock);
667 return &dynid->id;
668 }
669 }
670 spin_unlock(&drv->dynids.lock);
671 return NULL;
672}
673
674static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv,
675 struct usb_interface *intf)
676{
677 const struct usb_device_id *id;
678
679 id = usb_match_id(intf, drv->id_table);
680 if (id) {
681 dbg("static descriptor matches");
682 goto exit;
683 }
684 id = match_dynamic_id(intf, drv);
685 if (id)
686 dbg("dynamic descriptor matches");
687exit:
688 return id;
689}
690
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100691static struct usb_serial_driver *search_serial_device(
692 struct usb_interface *iface)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 const struct usb_device_id *id;
Alan Stern063a2da2007-10-10 16:24:06 -0400695 struct usb_serial_driver *drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696
Adrian Bunk93b1fae2006-01-10 00:13:33 +0100697 /* Check if the usb id matches a known device */
Alan Stern063a2da2007-10-10 16:24:06 -0400698 list_for_each_entry(drv, &usb_serial_driver_list, driver_list) {
699 id = get_iface_id(drv, iface);
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100700 if (id)
Alan Stern063a2da2007-10-10 16:24:06 -0400701 return drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 }
703
704 return NULL;
705}
706
Alan Cox335f8512009-06-11 12:26:29 +0100707static int serial_carrier_raised(struct tty_port *port)
708{
709 struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
710 struct usb_serial_driver *drv = p->serial->type;
711 if (drv->carrier_raised)
712 return drv->carrier_raised(p);
713 /* No carrier control - don't block */
714 return 1;
715}
716
717static void serial_dtr_rts(struct tty_port *port, int on)
718{
719 struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
720 struct usb_serial_driver *drv = p->serial->type;
721 if (drv->dtr_rts)
722 drv->dtr_rts(p, on);
723}
724
725static const struct tty_port_operations serial_port_ops = {
726 .carrier_raised = serial_carrier_raised,
727 .dtr_rts = serial_dtr_rts,
728};
729
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730int usb_serial_probe(struct usb_interface *interface,
731 const struct usb_device_id *id)
732{
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100733 struct usb_device *dev = interface_to_usbdev(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 struct usb_serial *serial = NULL;
735 struct usb_serial_port *port;
736 struct usb_host_interface *iface_desc;
737 struct usb_endpoint_descriptor *endpoint;
738 struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS];
739 struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS];
740 struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];
741 struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700742 struct usb_serial_driver *type = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 int retval;
Andre Hauptdd9ca5d2008-06-18 15:56:00 +0200744 unsigned int minor;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 int buffer_size;
746 int i;
747 int num_interrupt_in = 0;
748 int num_interrupt_out = 0;
749 int num_bulk_in = 0;
750 int num_bulk_out = 0;
751 int num_ports = 0;
752 int max_endpoints;
753
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100754 lock_kernel(); /* guard against unloading a serial driver module */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 type = search_serial_device(interface);
756 if (!type) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100757 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 dbg("none matched");
759 return -ENODEV;
760 }
761
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100762 serial = create_serial(dev, interface, type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 if (!serial) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100764 unlock_kernel();
Harvey Harrison441b62c2008-03-03 16:08:34 -0800765 dev_err(&interface->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 return -ENOMEM;
767 }
768
769 /* if this device type has a probe function, call it */
770 if (type->probe) {
771 const struct usb_device_id *id;
772
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700773 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100774 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100775 dev_err(&interface->dev,
776 "module get failed, exiting\n");
777 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 return -EIO;
779 }
780
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100781 id = get_iface_id(type, interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782 retval = type->probe(serial, id);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700783 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784
785 if (retval) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100786 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100787 dbg("sub driver rejected device");
788 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 return retval;
790 }
791 }
792
793 /* descriptor matches, let's find the endpoints needed */
794 /* check out the endpoints */
795 iface_desc = interface->cur_altsetting;
796 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
797 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700798
799 if (usb_endpoint_is_bulk_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 /* we found a bulk in endpoint */
801 dbg("found bulk in on endpoint %d", i);
802 bulk_in_endpoint[num_bulk_in] = endpoint;
803 ++num_bulk_in;
804 }
805
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700806 if (usb_endpoint_is_bulk_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 /* we found a bulk out endpoint */
808 dbg("found bulk out on endpoint %d", i);
809 bulk_out_endpoint[num_bulk_out] = endpoint;
810 ++num_bulk_out;
811 }
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700812
813 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814 /* we found a interrupt in endpoint */
815 dbg("found interrupt in on endpoint %d", i);
816 interrupt_in_endpoint[num_interrupt_in] = endpoint;
817 ++num_interrupt_in;
818 }
819
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700820 if (usb_endpoint_is_int_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 /* we found an interrupt out endpoint */
822 dbg("found interrupt out on endpoint %d", i);
823 interrupt_out_endpoint[num_interrupt_out] = endpoint;
824 ++num_interrupt_out;
825 }
826 }
827
828#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100829 /* BEGIN HORRIBLE HACK FOR PL2303 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 /* this is needed due to the looney way its endpoints are set up */
831 if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&
832 (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||
833 ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) &&
Johannes Steingraeber8fd80132006-09-16 16:17:34 +0200834 (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) ||
835 ((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) &&
Andreas Bombece816cf2008-09-14 01:58:55 +0200836 (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID)) ||
837 ((le16_to_cpu(dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) &&
838 (le16_to_cpu(dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_EF81))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 if (interface != dev->actconfig->interface[0]) {
840 /* check out the endpoints of the other interface*/
841 iface_desc = dev->actconfig->interface[0]->cur_altsetting;
842 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
843 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700844 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 /* we found a interrupt in endpoint */
846 dbg("found interrupt in for Prolific device on separate interface");
847 interrupt_in_endpoint[num_interrupt_in] = endpoint;
848 ++num_interrupt_in;
849 }
850 }
851 }
852
853 /* Now make sure the PL-2303 is configured correctly.
854 * If not, give up now and hope this hack will work
855 * properly during a later invocation of usb_serial_probe
856 */
857 if (num_bulk_in == 0 || num_bulk_out == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100858 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859 dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100860 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 return -ENODEV;
862 }
863 }
864 /* END HORRIBLE HACK FOR PL2303 */
865#endif
866
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867#ifdef CONFIG_USB_SERIAL_GENERIC
868 if (type == &usb_serial_generic_device) {
869 num_ports = num_bulk_out;
870 if (num_ports == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100871 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100872 dev_err(&interface->dev,
873 "Generic device with no bulk out, not allowed.\n");
874 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 return -EIO;
876 }
877 }
878#endif
879 if (!num_ports) {
880 /* if this device type has a calc_num_ports function, call it */
881 if (type->calc_num_ports) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700882 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100883 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100884 dev_err(&interface->dev,
885 "module get failed, exiting\n");
886 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887 return -EIO;
888 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100889 num_ports = type->calc_num_ports(serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700890 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 }
892 if (!num_ports)
893 num_ports = type->num_ports;
894 }
895
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 serial->num_ports = num_ports;
897 serial->num_bulk_in = num_bulk_in;
898 serial->num_bulk_out = num_bulk_out;
899 serial->num_interrupt_in = num_interrupt_in;
900 serial->num_interrupt_out = num_interrupt_out;
901
Alan Stern063a2da2007-10-10 16:24:06 -0400902 /* found all that we need */
903 dev_info(&interface->dev, "%s converter detected\n",
904 type->description);
905
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 /* create our ports, we need as many as the max endpoints */
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100907 /* we don't use num_ports here because some devices have more
908 endpoint pairs than ports */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 max_endpoints = max(num_bulk_in, num_bulk_out);
910 max_endpoints = max(max_endpoints, num_interrupt_in);
911 max_endpoints = max(max_endpoints, num_interrupt_out);
912 max_endpoints = max(max_endpoints, (int)serial->num_ports);
913 serial->num_port_pointers = max_endpoints;
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100914 unlock_kernel();
915
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100916 dbg("%s - setting up %d port structures for this device",
917 __func__, max_endpoints);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 for (i = 0; i < max_endpoints; ++i) {
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100919 port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 if (!port)
921 goto probe_error;
Alan Cox4a90f092008-10-13 10:39:46 +0100922 tty_port_init(&port->port);
Alan Cox335f8512009-06-11 12:26:29 +0100923 port->port.ops = &serial_port_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 port->serial = serial;
Greg Kroah-Hartman507ca9b2005-04-23 12:49:16 -0700925 spin_lock_init(&port->lock);
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300926 mutex_init(&port->mutex);
David Howellsc4028952006-11-22 14:57:56 +0000927 INIT_WORK(&port->work, usb_serial_port_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 serial->port[i] = port;
929 }
930
931 /* set up the endpoint information */
932 for (i = 0; i < num_bulk_in; ++i) {
933 endpoint = bulk_in_endpoint[i];
934 port = serial->port[i];
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100935 port->read_urb = usb_alloc_urb(0, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936 if (!port->read_urb) {
937 dev_err(&interface->dev, "No free urbs available\n");
938 goto probe_error;
939 }
940 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
941 port->bulk_in_size = buffer_size;
942 port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100943 port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944 if (!port->bulk_in_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100945 dev_err(&interface->dev,
946 "Couldn't allocate bulk_in_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947 goto probe_error;
948 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100949 usb_fill_bulk_urb(port->read_urb, dev,
950 usb_rcvbulkpipe(dev,
951 endpoint->bEndpointAddress),
952 port->bulk_in_buffer, buffer_size,
953 serial->type->read_bulk_callback, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 }
955
956 for (i = 0; i < num_bulk_out; ++i) {
957 endpoint = bulk_out_endpoint[i];
958 port = serial->port[i];
959 port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
960 if (!port->write_urb) {
961 dev_err(&interface->dev, "No free urbs available\n");
962 goto probe_error;
963 }
964 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
965 port->bulk_out_size = buffer_size;
966 port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100967 port->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 if (!port->bulk_out_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100969 dev_err(&interface->dev,
970 "Couldn't allocate bulk_out_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971 goto probe_error;
972 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100973 usb_fill_bulk_urb(port->write_urb, dev,
974 usb_sndbulkpipe(dev,
975 endpoint->bEndpointAddress),
976 port->bulk_out_buffer, buffer_size,
977 serial->type->write_bulk_callback, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 }
979
980 if (serial->type->read_int_callback) {
981 for (i = 0; i < num_interrupt_in; ++i) {
982 endpoint = interrupt_in_endpoint[i];
983 port = serial->port[i];
984 port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
985 if (!port->interrupt_in_urb) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100986 dev_err(&interface->dev,
987 "No free urbs available\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 goto probe_error;
989 }
990 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100991 port->interrupt_in_endpointAddress =
992 endpoint->bEndpointAddress;
993 port->interrupt_in_buffer = kmalloc(buffer_size,
994 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995 if (!port->interrupt_in_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100996 dev_err(&interface->dev,
997 "Couldn't allocate interrupt_in_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 goto probe_error;
999 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001000 usb_fill_int_urb(port->interrupt_in_urb, dev,
1001 usb_rcvintpipe(dev,
1002 endpoint->bEndpointAddress),
1003 port->interrupt_in_buffer, buffer_size,
1004 serial->type->read_int_callback, port,
1005 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 }
1007 } else if (num_interrupt_in) {
1008 dbg("the device claims to support interrupt in transfers, but read_int_callback is not defined");
1009 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001010
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 if (serial->type->write_int_callback) {
1012 for (i = 0; i < num_interrupt_out; ++i) {
1013 endpoint = interrupt_out_endpoint[i];
1014 port = serial->port[i];
1015 port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
1016 if (!port->interrupt_out_urb) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001017 dev_err(&interface->dev,
1018 "No free urbs available\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 goto probe_error;
1020 }
1021 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
1022 port->interrupt_out_size = buffer_size;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001023 port->interrupt_out_endpointAddress =
1024 endpoint->bEndpointAddress;
1025 port->interrupt_out_buffer = kmalloc(buffer_size,
1026 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 if (!port->interrupt_out_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001028 dev_err(&interface->dev,
1029 "Couldn't allocate interrupt_out_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 goto probe_error;
1031 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001032 usb_fill_int_urb(port->interrupt_out_urb, dev,
1033 usb_sndintpipe(dev,
1034 endpoint->bEndpointAddress),
1035 port->interrupt_out_buffer, buffer_size,
1036 serial->type->write_int_callback, port,
1037 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 }
1039 } else if (num_interrupt_out) {
1040 dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined");
1041 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001042
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 /* if this device type has an attach function, call it */
1044 if (type->attach) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -07001045 if (!try_module_get(type->driver.owner)) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001046 dev_err(&interface->dev,
1047 "module get failed, exiting\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 goto probe_error;
1049 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001050 retval = type->attach(serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -07001051 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 if (retval < 0)
1053 goto probe_error;
1054 if (retval > 0) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001055 /* quietly accept this device, but don't bind to a
1056 serial port as it's about to disappear */
Alan Stern0a3c8542009-05-27 11:25:52 -04001057 serial->num_ports = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 goto exit;
1059 }
1060 }
1061
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001062 if (get_free_serial(serial, num_ports, &minor) == NULL) {
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001063 dev_err(&interface->dev, "No more free serial devices\n");
1064 goto probe_error;
1065 }
Oliver Neukumc744f992007-02-26 15:43:00 +01001066 serial->minor = minor;
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001067
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 /* register all of the individual ports with the driver core */
1069 for (i = 0; i < num_ports; ++i) {
1070 port = serial->port[i];
1071 port->dev.parent = &interface->dev;
1072 port->dev.driver = NULL;
1073 port->dev.bus = &usb_serial_bus_type;
1074 port->dev.release = &port_release;
1075
Kay Sievers0031a062008-05-02 06:02:41 +02001076 dev_set_name(&port->dev, "ttyUSB%d", port->number);
Kay Sievers7071a3c2008-05-02 06:02:41 +02001077 dbg ("%s - registering %s", __func__, dev_name(&port->dev));
Alan Sternc706ebd2009-06-02 11:54:11 -04001078 port->dev_state = PORT_REGISTERING;
Greg Kroah-Hartman13f4db92006-08-28 11:43:25 -07001079 retval = device_register(&port->dev);
Alan Sternc706ebd2009-06-02 11:54:11 -04001080 if (retval) {
Greg Kroah-Hartman13f4db92006-08-28 11:43:25 -07001081 dev_err(&port->dev, "Error registering port device, "
1082 "continuing\n");
Alan Sternc706ebd2009-06-02 11:54:11 -04001083 port->dev_state = PORT_UNREGISTERED;
1084 } else {
1085 port->dev_state = PORT_REGISTERED;
1086 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 }
1088
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001089 usb_serial_console_init(debug, minor);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090
1091exit:
1092 /* success */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001093 usb_set_intfdata(interface, serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 return 0;
1095
1096probe_error:
1097 for (i = 0; i < num_bulk_in; ++i) {
1098 port = serial->port[i];
1099 if (!port)
1100 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001101 usb_free_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102 kfree(port->bulk_in_buffer);
1103 }
1104 for (i = 0; i < num_bulk_out; ++i) {
1105 port = serial->port[i];
1106 if (!port)
1107 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001108 usb_free_urb(port->write_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 kfree(port->bulk_out_buffer);
1110 }
1111 for (i = 0; i < num_interrupt_in; ++i) {
1112 port = serial->port[i];
1113 if (!port)
1114 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001115 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 kfree(port->interrupt_in_buffer);
1117 }
1118 for (i = 0; i < num_interrupt_out; ++i) {
1119 port = serial->port[i];
1120 if (!port)
1121 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001122 usb_free_urb(port->interrupt_out_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 kfree(port->interrupt_out_buffer);
1124 }
1125
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 /* free up any memory that we allocated */
1127 for (i = 0; i < serial->num_port_pointers; ++i)
1128 kfree(serial->port[i]);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001129 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130 return -EIO;
1131}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001132EXPORT_SYMBOL_GPL(usb_serial_probe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133
1134void usb_serial_disconnect(struct usb_interface *interface)
1135{
1136 int i;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001137 struct usb_serial *serial = usb_get_intfdata(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 struct device *dev = &interface->dev;
1139 struct usb_serial_port *port;
1140
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +02001141 usb_serial_console_disconnect(serial);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001142 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001144 mutex_lock(&serial->disc_mutex);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001145 usb_set_intfdata(interface, NULL);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001146 /* must set a flag, to signal subdrivers */
1147 serial->disconnected = 1;
Alan Stern2d931482009-04-14 11:31:02 -04001148 mutex_unlock(&serial->disc_mutex);
1149
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001150 for (i = 0; i < serial->num_ports; ++i) {
1151 port = serial->port[i];
1152 if (port) {
Alan Cox4a90f092008-10-13 10:39:46 +01001153 struct tty_struct *tty = tty_port_tty_get(&port->port);
1154 if (tty) {
Alan Cox335f8512009-06-11 12:26:29 +01001155 /* The hangup will occur asynchronously but
1156 the object refcounts will sort out all the
1157 cleanup */
Alan Cox4a90f092008-10-13 10:39:46 +01001158 tty_hangup(tty);
1159 tty_kref_put(tty);
1160 }
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001161 kill_traffic(port);
Alan Stern2d931482009-04-14 11:31:02 -04001162 cancel_work_sync(&port->work);
Alan Sternc706ebd2009-06-02 11:54:11 -04001163 if (port->dev_state == PORT_REGISTERED) {
1164
1165 /* Make sure the port is bound so that the
1166 * driver's port_remove method is called.
1167 */
1168 if (!port->dev.driver) {
1169 int rc;
1170
1171 port->dev.driver =
1172 &serial->type->driver;
1173 rc = device_bind_driver(&port->dev);
1174 }
1175 port->dev_state = PORT_UNREGISTERING;
1176 device_del(&port->dev);
1177 port->dev_state = PORT_UNREGISTERED;
1178 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180 }
Alan Sternf9c99bb2009-06-02 11:53:55 -04001181 serial->type->disconnect(serial);
Alan Stern2d931482009-04-14 11:31:02 -04001182
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001183 /* let the last holder of this object
1184 * cause it to be cleaned up */
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001185 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 dev_info(dev, "device disconnected\n");
1187}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001188EXPORT_SYMBOL_GPL(usb_serial_disconnect);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189
Oliver Neukumec225592007-04-27 20:54:57 +02001190int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
1191{
1192 struct usb_serial *serial = usb_get_intfdata(intf);
1193 struct usb_serial_port *port;
1194 int i, r = 0;
1195
Oliver Neukumf8bece82009-02-05 16:54:25 +01001196 serial->suspending = 1;
1197
Oliver Neukume31c1882007-07-23 08:58:39 +02001198 for (i = 0; i < serial->num_ports; ++i) {
1199 port = serial->port[i];
1200 if (port)
1201 kill_traffic(port);
Oliver Neukumec225592007-04-27 20:54:57 +02001202 }
1203
1204 if (serial->type->suspend)
Oliver Neukume31c1882007-07-23 08:58:39 +02001205 r = serial->type->suspend(serial, message);
Oliver Neukumec225592007-04-27 20:54:57 +02001206
1207 return r;
1208}
1209EXPORT_SYMBOL(usb_serial_suspend);
1210
1211int usb_serial_resume(struct usb_interface *intf)
1212{
1213 struct usb_serial *serial = usb_get_intfdata(intf);
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001214 int rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001215
Oliver Neukumf8bece82009-02-05 16:54:25 +01001216 serial->suspending = 0;
Sarah Sharp8abaee22007-10-25 10:58:43 -07001217 if (serial->type->resume)
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001218 rv = serial->type->resume(serial);
1219 else
1220 rv = usb_serial_generic_resume(serial);
Oliver Neukumf8bece82009-02-05 16:54:25 +01001221
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001222 return rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001223}
1224EXPORT_SYMBOL(usb_serial_resume);
1225
Jeff Dikeb68e31d2006-10-02 02:17:18 -07001226static const struct tty_operations serial_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 .open = serial_open,
1228 .close = serial_close,
1229 .write = serial_write,
Alan Cox335f8512009-06-11 12:26:29 +01001230 .hangup = serial_hangup,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 .write_room = serial_write_room,
1232 .ioctl = serial_ioctl,
1233 .set_termios = serial_set_termios,
1234 .throttle = serial_throttle,
1235 .unthrottle = serial_unthrottle,
1236 .break_ctl = serial_break,
1237 .chars_in_buffer = serial_chars_in_buffer,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 .tiocmget = serial_tiocmget,
1239 .tiocmset = serial_tiocmset,
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -07001240 .proc_fops = &serial_proc_fops,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241};
1242
Alan Cox335f8512009-06-11 12:26:29 +01001243
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244struct tty_driver *usb_serial_tty_driver;
1245
1246static int __init usb_serial_init(void)
1247{
1248 int i;
1249 int result;
1250
1251 usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS);
1252 if (!usb_serial_tty_driver)
1253 return -ENOMEM;
1254
1255 /* Initialize our global data */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001256 for (i = 0; i < SERIAL_TTY_MINORS; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257 serial_table[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258
1259 result = bus_register(&usb_serial_bus_type);
1260 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001261 printk(KERN_ERR "usb-serial: %s - registering bus driver "
1262 "failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263 goto exit_bus;
1264 }
1265
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 usb_serial_tty_driver->owner = THIS_MODULE;
1267 usb_serial_tty_driver->driver_name = "usbserial";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 usb_serial_tty_driver->name = "ttyUSB";
1269 usb_serial_tty_driver->major = SERIAL_TTY_MAJOR;
1270 usb_serial_tty_driver->minor_start = 0;
1271 usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
1272 usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001273 usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW |
1274 TTY_DRIVER_DYNAMIC_DEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275 usb_serial_tty_driver->init_termios = tty_std_termios;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001276 usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD
1277 | HUPCL | CLOCAL;
Alan Coxa5b6f602008-04-08 17:16:06 +01001278 usb_serial_tty_driver->init_termios.c_ispeed = 9600;
1279 usb_serial_tty_driver->init_termios.c_ospeed = 9600;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 tty_set_operations(usb_serial_tty_driver, &serial_ops);
1281 result = tty_register_driver(usb_serial_tty_driver);
1282 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001283 printk(KERN_ERR "usb-serial: %s - tty_register_driver failed\n",
1284 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285 goto exit_reg_driver;
1286 }
1287
1288 /* register the USB driver */
1289 result = usb_register(&usb_serial_driver);
1290 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001291 printk(KERN_ERR "usb-serial: %s - usb_register failed\n",
1292 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293 goto exit_tty;
1294 }
1295
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001296 /* register the generic driver, if we should */
1297 result = usb_serial_generic_register(debug);
1298 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001299 printk(KERN_ERR "usb-serial: %s - registering generic "
1300 "driver failed\n", __func__);
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001301 goto exit_generic;
1302 }
1303
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001304 printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305
1306 return result;
1307
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001308exit_generic:
1309 usb_deregister(&usb_serial_driver);
1310
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311exit_tty:
1312 tty_unregister_driver(usb_serial_tty_driver);
1313
1314exit_reg_driver:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315 bus_unregister(&usb_serial_bus_type);
1316
1317exit_bus:
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001318 printk(KERN_ERR "usb-serial: %s - returning with error %d\n",
1319 __func__, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 put_tty_driver(usb_serial_tty_driver);
1321 return result;
1322}
1323
1324
1325static void __exit usb_serial_exit(void)
1326{
1327 usb_serial_console_exit();
1328
1329 usb_serial_generic_deregister();
1330
1331 usb_deregister(&usb_serial_driver);
1332 tty_unregister_driver(usb_serial_tty_driver);
1333 put_tty_driver(usb_serial_tty_driver);
1334 bus_unregister(&usb_serial_bus_type);
1335}
1336
1337
1338module_init(usb_serial_init);
1339module_exit(usb_serial_exit);
1340
1341#define set_to_generic_if_null(type, function) \
1342 do { \
1343 if (!type->function) { \
1344 type->function = usb_serial_generic_##function; \
1345 dbg("Had to override the " #function \
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001346 " usb serial operation with the generic one.");\
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 } \
1348 } while (0)
1349
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001350static void fixup_generic(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351{
1352 set_to_generic_if_null(device, open);
1353 set_to_generic_if_null(device, write);
1354 set_to_generic_if_null(device, close);
1355 set_to_generic_if_null(device, write_room);
1356 set_to_generic_if_null(device, chars_in_buffer);
1357 set_to_generic_if_null(device, read_bulk_callback);
1358 set_to_generic_if_null(device, write_bulk_callback);
Alan Sternf9c99bb2009-06-02 11:53:55 -04001359 set_to_generic_if_null(device, disconnect);
1360 set_to_generic_if_null(device, release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361}
1362
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001363int usb_serial_register(struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001365 /* must be called with BKL held */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366 int retval;
1367
Dave Younge4abe662009-02-14 21:21:13 +08001368 if (usb_disabled())
1369 return -ENODEV;
1370
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001371 fixup_generic(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001373 if (!driver->description)
1374 driver->description = driver->driver.name;
1375
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376 /* Add this device to our list of devices */
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001377 list_add(&driver->driver_list, &usb_serial_driver_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001379 retval = usb_serial_bus_register(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380 if (retval) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001381 printk(KERN_ERR "usb-serial: problem %d when registering "
1382 "driver %s\n", retval, driver->description);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001383 list_del(&driver->driver_list);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001384 } else
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001385 printk(KERN_INFO "USB Serial support registered for %s\n",
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001386 driver->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387
1388 return retval;
1389}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001390EXPORT_SYMBOL_GPL(usb_serial_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391
1392
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001393void usb_serial_deregister(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001395 /* must be called with BKL held */
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001396 printk(KERN_INFO "USB Serial deregistering driver %s\n",
1397 device->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398 list_del(&device->driver_list);
1399 usb_serial_bus_deregister(device);
1400}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401EXPORT_SYMBOL_GPL(usb_serial_deregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402
1403/* Module information */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001404MODULE_AUTHOR(DRIVER_AUTHOR);
1405MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406MODULE_LICENSE("GPL");
1407
1408module_param(debug, bool, S_IRUGO | S_IWUSR);
1409MODULE_PARM_DESC(debug, "Debug enabled or not");