blob: ff75a3589e7e9f809a6839053c20fb2442784d50 [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>
David VomLehn8e8dce02009-08-28 12:54:27 -070038#include <linux/kfifo.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070039#include "pl2303.h"
40
41/*
42 * Version Information
43 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/"
45#define DRIVER_DESC "USB Serial Driver core"
46
47/* 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
Alan Stern8bc2c1b2009-09-01 11:38:59 -040070/*
71 * Look up the serial structure. If it is found and it hasn't been
72 * disconnected, return with its disc_mutex held and its refcount
73 * incremented. Otherwise return NULL.
74 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070075struct usb_serial *usb_serial_get_by_index(unsigned index)
76{
Oliver Neukum34ef50e2007-01-13 07:29:26 +010077 struct usb_serial *serial;
78
Oliver Neukum3ddad822007-07-24 15:13:42 +020079 mutex_lock(&table_lock);
Oliver Neukum34ef50e2007-01-13 07:29:26 +010080 serial = serial_table[index];
Linus Torvalds1da177e2005-04-16 15:20:36 -070081
Alan Stern8bc2c1b2009-09-01 11:38:59 -040082 if (serial) {
83 mutex_lock(&serial->disc_mutex);
84 if (serial->disconnected) {
85 mutex_unlock(&serial->disc_mutex);
86 serial = NULL;
87 } else {
88 kref_get(&serial->kref);
89 }
90 }
Oliver Neukum3ddad822007-07-24 15:13:42 +020091 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070092 return serial;
93}
94
Alan Coxa8d6f0a2008-07-22 11:12:24 +010095static struct usb_serial *get_free_serial(struct usb_serial *serial,
96 int num_ports, unsigned int *minor)
Linus Torvalds1da177e2005-04-16 15:20:36 -070097{
98 unsigned int i, j;
99 int good_spot;
100
Harvey Harrison441b62c2008-03-03 16:08:34 -0800101 dbg("%s %d", __func__, num_ports);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102
103 *minor = 0;
Oliver Neukum3ddad822007-07-24 15:13:42 +0200104 mutex_lock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
106 if (serial_table[i])
107 continue;
108
109 good_spot = 1;
110 for (j = 1; j <= num_ports-1; ++j)
111 if ((i+j >= SERIAL_TTY_MINORS) || (serial_table[i+j])) {
112 good_spot = 0;
113 i += j;
114 break;
115 }
116 if (good_spot == 0)
117 continue;
118
119 *minor = i;
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100120 j = 0;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800121 dbg("%s - minor base = %d", __func__, *minor);
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100122 for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123 serial_table[i] = serial;
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100124 serial->port[j++]->number = i;
125 }
Oliver Neukum3ddad822007-07-24 15:13:42 +0200126 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127 return serial;
128 }
Oliver Neukum3ddad822007-07-24 15:13:42 +0200129 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130 return NULL;
131}
132
133static void return_serial(struct usb_serial *serial)
134{
135 int i;
136
Harvey Harrison441b62c2008-03-03 16:08:34 -0800137 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138
Alan Stern8bc2c1b2009-09-01 11:38:59 -0400139 mutex_lock(&table_lock);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100140 for (i = 0; i < serial->num_ports; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141 serial_table[serial->minor + i] = NULL;
Alan Stern8bc2c1b2009-09-01 11:38:59 -0400142 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143}
144
145static void destroy_serial(struct kref *kref)
146{
147 struct usb_serial *serial;
148 struct usb_serial_port *port;
149 int i;
150
151 serial = to_usb_serial(kref);
152
Harvey Harrison441b62c2008-03-03 16:08:34 -0800153 dbg("%s - %s", __func__, serial->type->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154
Jim Radford521b85a2007-03-13 08:30:50 -0700155 /* return the minor range that this device had */
Alan Stern0282b7f2008-07-29 12:01:04 -0400156 if (serial->minor != SERIAL_TTY_NO_MINOR)
157 return_serial(serial);
Jim Radford521b85a2007-03-13 08:30:50 -0700158
Alan Sternf9c99bb2009-06-02 11:53:55 -0400159 serial->type->release(serial);
160
Alan Stern41bd34d2009-09-01 11:38:34 -0400161 /* Now that nothing is using the ports, they can be freed */
162 for (i = 0; i < serial->num_port_pointers; ++i) {
Alan Sternf9c99bb2009-06-02 11:53:55 -0400163 port = serial->port[i];
Alan Stern41bd34d2009-09-01 11:38:34 -0400164 if (port) {
165 port->serial = NULL;
Alan Sternf9c99bb2009-06-02 11:53:55 -0400166 put_device(&port->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 }
168 }
169
170 usb_put_dev(serial->dev);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100171 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172}
173
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200174void usb_serial_put(struct usb_serial *serial)
175{
176 kref_put(&serial->kref, destroy_serial);
177}
178
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179/*****************************************************************************
180 * Driver tty interface functions
181 *****************************************************************************/
Alan Sternf5b09532009-09-01 11:38:44 -0400182
183/**
184 * serial_install - install tty
185 * @driver: the driver (USB in our case)
186 * @tty: the tty being created
187 *
188 * Create the termios objects for this tty. We use the default
189 * USB serial settings but permit them to be overridden by
190 * serial->type->init_termios.
Alan Sterncc56cd02009-09-01 11:39:13 -0400191 *
192 * This is the first place a new tty gets used. Hence this is where we
193 * acquire references to the usb_serial structure and the driver module,
194 * where we store a pointer to the port, and where we do an autoresume.
Alan Stern74556122009-09-01 11:39:40 -0400195 * All these actions are reversed in serial_release().
Alan Sternf5b09532009-09-01 11:38:44 -0400196 */
197static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
198{
199 int idx = tty->index;
200 struct usb_serial *serial;
Alan Sterncc56cd02009-09-01 11:39:13 -0400201 struct usb_serial_port *port;
202 int retval = -ENODEV;
203
Alan Sternff8324d2009-09-01 11:39:51 -0400204 dbg("%s", __func__);
205
Alan Sterncc56cd02009-09-01 11:39:13 -0400206 serial = usb_serial_get_by_index(idx);
207 if (!serial)
208 return retval;
209
210 port = serial->port[idx - serial->minor];
211 if (!port)
212 goto error_no_port;
213 if (!try_module_get(serial->type->driver.owner))
214 goto error_module_get;
215
Alan Stern7e29bb42009-09-01 11:39:22 -0400216 /* perform the standard setup */
217 retval = tty_init_termios(tty);
218 if (retval)
219 goto error_init_termios;
220
Alan Sterncc56cd02009-09-01 11:39:13 -0400221 retval = usb_autopm_get_interface(serial->interface);
222 if (retval)
223 goto error_get_interface;
Alan Sternf5b09532009-09-01 11:38:44 -0400224
Alan Sterncc56cd02009-09-01 11:39:13 -0400225 mutex_unlock(&serial->disc_mutex);
226
Alan Stern7e29bb42009-09-01 11:39:22 -0400227 /* allow the driver to update the settings */
228 if (serial->type->init_termios)
229 serial->type->init_termios(tty);
230
Alan Sterncc56cd02009-09-01 11:39:13 -0400231 tty->driver_data = port;
232
Alan Sternf5b09532009-09-01 11:38:44 -0400233 /* Final install (we use the default method) */
234 tty_driver_kref_get(driver);
235 tty->count++;
236 driver->ttys[idx] = tty;
Alan Sterncc56cd02009-09-01 11:39:13 -0400237 return retval;
238
Alan Sterncc56cd02009-09-01 11:39:13 -0400239 error_get_interface:
Alan Stern7e29bb42009-09-01 11:39:22 -0400240 error_init_termios:
Alan Sterncc56cd02009-09-01 11:39:13 -0400241 module_put(serial->type->driver.owner);
242 error_module_get:
243 error_no_port:
244 usb_serial_put(serial);
245 mutex_unlock(&serial->disc_mutex);
246 return retval;
Alan Sternf5b09532009-09-01 11:38:44 -0400247}
248
Alan Stern320348c2009-09-01 11:39:59 -0400249static int serial_open(struct tty_struct *tty, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250{
Alan Stern320348c2009-09-01 11:39:59 -0400251 struct usb_serial_port *port = tty->driver_data;
252 struct usb_serial *serial = port->serial;
253 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254
Alan Sternff8324d2009-09-01 11:39:51 -0400255 dbg("%s - port %d", __func__, port->number);
256
Alan Stern320348c2009-09-01 11:39:59 -0400257 spin_lock_irq(&port->port.lock);
258 if (!tty_hung_up_p(filp))
259 ++port->port.count;
260 spin_unlock_irq(&port->port.lock);
Alan Cox4a90f092008-10-13 10:39:46 +0100261 tty_port_tty_set(&port->port, tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262
Alan Stern320348c2009-09-01 11:39:59 -0400263 /* Do the device-specific open only if the hardware isn't
264 * already initialized.
265 */
266 if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) {
267 if (mutex_lock_interruptible(&port->mutex))
268 return -ERESTARTSYS;
Alan Stern2d931482009-04-14 11:31:02 -0400269 mutex_lock(&serial->disc_mutex);
Alan Stern320348c2009-09-01 11:39:59 -0400270 if (serial->disconnected)
271 retval = -ENODEV;
272 else
273 retval = port->serial->type->open(tty, port);
Alan Stern2d931482009-04-14 11:31:02 -0400274 mutex_unlock(&serial->disc_mutex);
Alan Stern320348c2009-09-01 11:39:59 -0400275 mutex_unlock(&port->mutex);
276 if (retval)
277 return retval;
Alan Coxc56d3002009-07-28 00:34:58 +0100278 set_bit(ASYNCB_INITIALIZED, &port->port.flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 }
Alan Stern320348c2009-09-01 11:39:59 -0400280
Alan Cox335f8512009-06-11 12:26:29 +0100281 /* Now do the correct tty layer semantics */
282 retval = tty_port_block_til_ready(&port->port, tty, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 return retval;
284}
285
Alan Cox335f8512009-06-11 12:26:29 +0100286/**
Alan Stern74556122009-09-01 11:39:40 -0400287 * serial_down - shut down hardware
Alan Sternf5b09532009-09-01 11:38:44 -0400288 * @port: port to shut down
Alan Cox335f8512009-06-11 12:26:29 +0100289 *
Alan Sternf5b09532009-09-01 11:38:44 -0400290 * Shut down a USB serial port unless it is the console. We never
291 * shut down the console hardware as it will always be in use.
Alan Cox335f8512009-06-11 12:26:29 +0100292 */
Alan Stern74556122009-09-01 11:39:40 -0400293static void serial_down(struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294{
Alan Cox335f8512009-06-11 12:26:29 +0100295 struct usb_serial_driver *drv = port->serial->type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296
Alan Sternf5b09532009-09-01 11:38:44 -0400297 /*
298 * The console is magical. Do not hang up the console hardware
299 * or there will be tears.
300 */
Alan Cox335f8512009-06-11 12:26:29 +0100301 if (port->console)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302 return;
303
Alan Sternff8324d2009-09-01 11:39:51 -0400304 /* Don't call the close method if the hardware hasn't been
305 * initialized.
306 */
307 if (!test_and_clear_bit(ASYNCB_INITIALIZED, &port->port.flags))
308 return;
309
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300310 mutex_lock(&port->mutex);
Alan Cox335f8512009-06-11 12:26:29 +0100311 if (drv->close)
312 drv->close(port);
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300313 mutex_unlock(&port->mutex);
Alan Cox335f8512009-06-11 12:26:29 +0100314}
315
Alan Sternf5b09532009-09-01 11:38:44 -0400316static void serial_hangup(struct tty_struct *tty)
Alan Cox335f8512009-06-11 12:26:29 +0100317{
Alan Cox4455e342009-09-19 13:13:24 -0700318 struct usb_serial_port *port = tty->driver_data;
Alan Sternff8324d2009-09-01 11:39:51 -0400319
320 dbg("%s - port %d", __func__, port->number);
321
Alan Stern74556122009-09-01 11:39:40 -0400322 serial_down(port);
Alan Sternf5b09532009-09-01 11:38:44 -0400323 tty_port_hangup(&port->port);
Alan Cox335f8512009-06-11 12:26:29 +0100324}
325
326static void serial_close(struct tty_struct *tty, struct file *filp)
327{
328 struct usb_serial_port *port = tty->driver_data;
329
330 dbg("%s - port %d", __func__, port->number);
331
Alan Sternff8324d2009-09-01 11:39:51 -0400332 if (tty_hung_up_p(filp))
333 return;
Alan Cox335f8512009-06-11 12:26:29 +0100334 if (tty_port_close_start(&port->port, tty, filp) == 0)
335 return;
Alan Stern74556122009-09-01 11:39:40 -0400336 serial_down(port);
Alan Cox335f8512009-06-11 12:26:29 +0100337 tty_port_close_end(&port->port, tty);
338 tty_port_tty_set(&port->port, NULL);
Alan Cox335f8512009-06-11 12:26:29 +0100339}
340
Alan Sternf5b09532009-09-01 11:38:44 -0400341/**
Alan Stern74556122009-09-01 11:39:40 -0400342 * serial_release - free resources post close/hangup
Alan Sternf5b09532009-09-01 11:38:44 -0400343 * @port: port to free up
344 *
345 * Do the resource freeing and refcount dropping for the port.
346 * Avoid freeing the console.
347 *
348 * Called when the last tty kref is dropped.
349 */
Alan Stern74556122009-09-01 11:39:40 -0400350static void serial_release(struct tty_struct *tty)
Alan Cox335f8512009-06-11 12:26:29 +0100351{
352 struct usb_serial_port *port = tty->driver_data;
Alan Sternf5b09532009-09-01 11:38:44 -0400353 struct usb_serial *serial;
354 struct module *owner;
355
356 /* The console is magical. Do not hang up the console hardware
357 * or there will be tears.
358 */
Alan Sterncc56cd02009-09-01 11:39:13 -0400359 if (port->console)
Alan Sternf5b09532009-09-01 11:38:44 -0400360 return;
361
Alan Sternff8324d2009-09-01 11:39:51 -0400362 dbg("%s - port %d", __func__, port->number);
363
Alan Stern74556122009-09-01 11:39:40 -0400364 /* Standard shutdown processing */
365 tty_shutdown(tty);
366
Alan Sterncc56cd02009-09-01 11:39:13 -0400367 tty->driver_data = NULL;
368
Alan Sternf5b09532009-09-01 11:38:44 -0400369 serial = port->serial;
370 owner = serial->type->driver.owner;
371
372 mutex_lock(&serial->disc_mutex);
373 if (!serial->disconnected)
374 usb_autopm_put_interface(serial->interface);
375 mutex_unlock(&serial->disc_mutex);
376
377 usb_serial_put(serial);
378 module_put(owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379}
380
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100381static int serial_write(struct tty_struct *tty, const unsigned char *buf,
382 int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200384 struct usb_serial_port *port = tty->driver_data;
Oliver Neukum3ff4fd92007-01-13 07:32:27 +0100385 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386
Alan Coxf34d7a52008-04-30 00:54:13 -0700387 if (port->serial->dev->state == USB_STATE_NOTATTACHED)
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200388 goto exit;
389
Harvey Harrison441b62c2008-03-03 16:08:34 -0800390 dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391
Alan Cox95da3102008-07-22 11:09:07 +0100392 /* count is managed under the mutex lock for the tty so cannot
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100393 drop to zero until after the last close completes */
Alan Cox95da3102008-07-22 11:09:07 +0100394 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395
396 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100397 retval = port->serial->type->write(tty, port, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398
399exit:
400 return retval;
401}
402
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100403static int serial_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200405 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800406 dbg("%s - port %d", __func__, port->number);
Alan Cox95da3102008-07-22 11:09:07 +0100407 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100409 return port->serial->type->write_room(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410}
411
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100412static int serial_chars_in_buffer(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200414 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800415 dbg("%s = port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416
Alan Coxeff69372009-01-02 13:47:06 +0000417 /* if the device was unplugged then any remaining characters
418 fell out of the connector ;) */
419 if (port->serial->disconnected)
420 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100422 return port->serial->type->chars_in_buffer(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423}
424
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100425static void serial_throttle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200427 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800428 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429
Alan Cox95da3102008-07-22 11:09:07 +0100430 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 /* pass on to the driver specific version of this function */
432 if (port->serial->type->throttle)
Alan Cox95da3102008-07-22 11:09:07 +0100433 port->serial->type->throttle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434}
435
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100436static void serial_unthrottle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200438 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800439 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440
Alan Cox95da3102008-07-22 11:09:07 +0100441 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 /* pass on to the driver specific version of this function */
443 if (port->serial->type->unthrottle)
Alan Cox95da3102008-07-22 11:09:07 +0100444 port->serial->type->unthrottle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445}
446
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100447static int serial_ioctl(struct tty_struct *tty, struct file *file,
448 unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200450 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 int retval = -ENODEV;
452
Harvey Harrison441b62c2008-03-03 16:08:34 -0800453 dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454
Alan Cox95da3102008-07-22 11:09:07 +0100455 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100457 /* pass on to the driver specific version of this function
458 if it is available */
Alan Coxf34d7a52008-04-30 00:54:13 -0700459 if (port->serial->type->ioctl) {
Alan Cox95da3102008-07-22 11:09:07 +0100460 retval = port->serial->type->ioctl(tty, file, cmd, arg);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100461 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 retval = -ENOIOCTLCMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463 return retval;
464}
465
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100466static void serial_set_termios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200468 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800469 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470
Alan Cox95da3102008-07-22 11:09:07 +0100471 WARN_ON(!port->port.count);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100472 /* pass on to the driver specific version of this function
473 if it is available */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 if (port->serial->type->set_termios)
Alan Cox95da3102008-07-22 11:09:07 +0100475 port->serial->type->set_termios(tty, port, old);
Alan Cox33785092007-10-18 01:24:22 -0700476 else
477 tty_termios_copy_hw(tty->termios, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478}
479
Alan Cox9e989662008-07-22 11:18:03 +0100480static int serial_break(struct tty_struct *tty, int break_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200482 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483
Harvey Harrison441b62c2008-03-03 16:08:34 -0800484 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485
Alan Cox95da3102008-07-22 11:09:07 +0100486 WARN_ON(!port->port.count);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100487 /* pass on to the driver specific version of this function
488 if it is available */
Alan Cox6b447f042009-01-02 13:48:56 +0000489 if (port->serial->type->break_ctl)
Alan Cox95da3102008-07-22 11:09:07 +0100490 port->serial->type->break_ctl(tty, break_state);
Alan Cox9e989662008-07-22 11:18:03 +0100491 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492}
493
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700494static int serial_proc_show(struct seq_file *m, void *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495{
496 struct usb_serial *serial;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 char tmp[40];
499
Harvey Harrison441b62c2008-03-03 16:08:34 -0800500 dbg("%s", __func__);
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700501 seq_puts(m, "usbserinfo:1.0 driver:2.0\n");
502 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 serial = usb_serial_get_by_index(i);
504 if (serial == NULL)
505 continue;
506
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700507 seq_printf(m, "%d:", i);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700508 if (serial->type->driver.owner)
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700509 seq_printf(m, " module:%s",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100510 module_name(serial->type->driver.owner));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700511 seq_printf(m, " name:\"%s\"",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100512 serial->type->description);
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700513 seq_printf(m, " vendor:%04x product:%04x",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100514 le16_to_cpu(serial->dev->descriptor.idVendor),
515 le16_to_cpu(serial->dev->descriptor.idProduct));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700516 seq_printf(m, " num_ports:%d", serial->num_ports);
517 seq_printf(m, " port:%d", i - serial->minor + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 usb_make_path(serial->dev, tmp, sizeof(tmp));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700519 seq_printf(m, " path:%s", tmp);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100520
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700521 seq_putc(m, '\n');
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200522 usb_serial_put(serial);
Alan Stern8bc2c1b2009-09-01 11:38:59 -0400523 mutex_unlock(&serial->disc_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 }
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700525 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526}
527
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700528static int serial_proc_open(struct inode *inode, struct file *file)
529{
530 return single_open(file, serial_proc_show, NULL);
531}
532
533static const struct file_operations serial_proc_fops = {
534 .owner = THIS_MODULE,
535 .open = serial_proc_open,
536 .read = seq_read,
537 .llseek = seq_lseek,
538 .release = single_release,
539};
540
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100541static int serial_tiocmget(struct tty_struct *tty, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200543 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544
Harvey Harrison441b62c2008-03-03 16:08:34 -0800545 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546
Alan Cox95da3102008-07-22 11:09:07 +0100547 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 if (port->serial->type->tiocmget)
Alan Cox95da3102008-07-22 11:09:07 +0100549 return port->serial->type->tiocmget(tty, file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 return -EINVAL;
551}
552
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100553static int serial_tiocmset(struct tty_struct *tty, struct file *file,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 unsigned int set, unsigned int clear)
555{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200556 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557
Harvey Harrison441b62c2008-03-03 16:08:34 -0800558 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559
Alan Cox95da3102008-07-22 11:09:07 +0100560 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561 if (port->serial->type->tiocmset)
Alan Cox95da3102008-07-22 11:09:07 +0100562 return port->serial->type->tiocmset(tty, file, set, clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563 return -EINVAL;
564}
565
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700566/*
567 * We would be calling tty_wakeup here, but unfortunately some line
568 * disciplines have an annoying habit of calling tty->write from
569 * the write wakeup callback (e.g. n_hdlc.c).
570 */
571void usb_serial_port_softint(struct usb_serial_port *port)
572{
573 schedule_work(&port->work);
574}
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100575EXPORT_SYMBOL_GPL(usb_serial_port_softint);
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700576
David Howellsc4028952006-11-22 14:57:56 +0000577static void usb_serial_port_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578{
David Howellsc4028952006-11-22 14:57:56 +0000579 struct usb_serial_port *port =
580 container_of(work, struct usb_serial_port, work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 struct tty_struct *tty;
582
Harvey Harrison441b62c2008-03-03 16:08:34 -0800583 dbg("%s - port %d", __func__, port->number);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100584
Alan Cox4a90f092008-10-13 10:39:46 +0100585 tty = tty_port_tty_get(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 if (!tty)
587 return;
588
589 tty_wakeup(tty);
Alan Cox4a90f092008-10-13 10:39:46 +0100590 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591}
592
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100593static void kill_traffic(struct usb_serial_port *port)
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700594{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596 usb_kill_urb(port->write_urb);
Oliver Neukum5adceac2007-08-17 14:01:38 +0200597 /*
598 * This is tricky.
599 * Some drivers submit the read_urb in the
600 * handler for the write_urb or vice versa
601 * this order determines the order in which
602 * usb_kill_urb() must be used to reliably
603 * kill the URBs. As it is unknown here,
604 * both orders must be used in turn.
605 * The call below is not redundant.
606 */
607 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 usb_kill_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 usb_kill_urb(port->interrupt_out_urb);
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100610}
611
Alan Stern41bd34d2009-09-01 11:38:34 -0400612static void port_release(struct device *dev)
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100613{
Alan Stern41bd34d2009-09-01 11:38:34 -0400614 struct usb_serial_port *port = to_usb_serial_port(dev);
615
616 dbg ("%s - %s", __func__, dev_name(dev));
617
Alan Stern2d931482009-04-14 11:31:02 -0400618 /*
619 * Stop all the traffic before cancelling the work, so that
620 * nobody will restart it by calling usb_serial_port_softint.
621 */
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100622 kill_traffic(port);
Alan Stern2d931482009-04-14 11:31:02 -0400623 cancel_work_sync(&port->work);
624
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100625 usb_free_urb(port->read_urb);
626 usb_free_urb(port->write_urb);
627 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 usb_free_urb(port->interrupt_out_urb);
David VomLehn8e8dce02009-08-28 12:54:27 -0700629 if (!IS_ERR(port->write_fifo) && port->write_fifo)
630 kfifo_free(port->write_fifo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 kfree(port->bulk_in_buffer);
632 kfree(port->bulk_out_buffer);
633 kfree(port->interrupt_in_buffer);
634 kfree(port->interrupt_out_buffer);
635 kfree(port);
636}
637
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100638static struct usb_serial *create_serial(struct usb_device *dev,
639 struct usb_interface *interface,
640 struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641{
642 struct usb_serial *serial;
643
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100644 serial = kzalloc(sizeof(*serial), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645 if (!serial) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800646 dev_err(&dev->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 return NULL;
648 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649 serial->dev = usb_get_dev(dev);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700650 serial->type = driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651 serial->interface = interface;
652 kref_init(&serial->kref);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +0100653 mutex_init(&serial->disc_mutex);
Alan Stern0282b7f2008-07-29 12:01:04 -0400654 serial->minor = SERIAL_TTY_NO_MINOR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655
656 return serial;
657}
658
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100659static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf,
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100660 struct usb_serial_driver *drv)
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100661{
662 struct usb_dynid *dynid;
663
664 spin_lock(&drv->dynids.lock);
665 list_for_each_entry(dynid, &drv->dynids.list, node) {
666 if (usb_match_one_id(intf, &dynid->id)) {
667 spin_unlock(&drv->dynids.lock);
668 return &dynid->id;
669 }
670 }
671 spin_unlock(&drv->dynids.lock);
672 return NULL;
673}
674
675static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv,
676 struct usb_interface *intf)
677{
678 const struct usb_device_id *id;
679
680 id = usb_match_id(intf, drv->id_table);
681 if (id) {
682 dbg("static descriptor matches");
683 goto exit;
684 }
685 id = match_dynamic_id(intf, drv);
686 if (id)
687 dbg("dynamic descriptor matches");
688exit:
689 return id;
690}
691
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100692static struct usb_serial_driver *search_serial_device(
693 struct usb_interface *iface)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695 const struct usb_device_id *id;
Alan Stern063a2da2007-10-10 16:24:06 -0400696 struct usb_serial_driver *drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697
Adrian Bunk93b1fae2006-01-10 00:13:33 +0100698 /* Check if the usb id matches a known device */
Alan Stern063a2da2007-10-10 16:24:06 -0400699 list_for_each_entry(drv, &usb_serial_driver_list, driver_list) {
700 id = get_iface_id(drv, iface);
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100701 if (id)
Alan Stern063a2da2007-10-10 16:24:06 -0400702 return drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 }
704
705 return NULL;
706}
707
Alan Cox335f8512009-06-11 12:26:29 +0100708static int serial_carrier_raised(struct tty_port *port)
709{
710 struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
711 struct usb_serial_driver *drv = p->serial->type;
712 if (drv->carrier_raised)
713 return drv->carrier_raised(p);
714 /* No carrier control - don't block */
715 return 1;
716}
717
718static void serial_dtr_rts(struct tty_port *port, int on)
719{
720 struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
721 struct usb_serial_driver *drv = p->serial->type;
722 if (drv->dtr_rts)
723 drv->dtr_rts(p, on);
724}
725
726static const struct tty_port_operations serial_port_ops = {
727 .carrier_raised = serial_carrier_raised,
728 .dtr_rts = serial_dtr_rts,
729};
730
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731int usb_serial_probe(struct usb_interface *interface,
732 const struct usb_device_id *id)
733{
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100734 struct usb_device *dev = interface_to_usbdev(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 struct usb_serial *serial = NULL;
736 struct usb_serial_port *port;
737 struct usb_host_interface *iface_desc;
738 struct usb_endpoint_descriptor *endpoint;
739 struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS];
740 struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS];
741 struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];
742 struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700743 struct usb_serial_driver *type = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 int retval;
Andre Hauptdd9ca5d2008-06-18 15:56:00 +0200745 unsigned int minor;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 int buffer_size;
747 int i;
748 int num_interrupt_in = 0;
749 int num_interrupt_out = 0;
750 int num_bulk_in = 0;
751 int num_bulk_out = 0;
752 int num_ports = 0;
753 int max_endpoints;
754
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100755 lock_kernel(); /* guard against unloading a serial driver module */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 type = search_serial_device(interface);
757 if (!type) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100758 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 dbg("none matched");
760 return -ENODEV;
761 }
762
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100763 serial = create_serial(dev, interface, type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 if (!serial) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100765 unlock_kernel();
Harvey Harrison441b62c2008-03-03 16:08:34 -0800766 dev_err(&interface->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767 return -ENOMEM;
768 }
769
770 /* if this device type has a probe function, call it */
771 if (type->probe) {
772 const struct usb_device_id *id;
773
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700774 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100775 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100776 dev_err(&interface->dev,
777 "module get failed, exiting\n");
778 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 return -EIO;
780 }
781
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100782 id = get_iface_id(type, interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 retval = type->probe(serial, id);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700784 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785
786 if (retval) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100787 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100788 dbg("sub driver rejected device");
789 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 return retval;
791 }
792 }
793
794 /* descriptor matches, let's find the endpoints needed */
795 /* check out the endpoints */
796 iface_desc = interface->cur_altsetting;
797 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
798 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700799
800 if (usb_endpoint_is_bulk_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 /* we found a bulk in endpoint */
802 dbg("found bulk in on endpoint %d", i);
803 bulk_in_endpoint[num_bulk_in] = endpoint;
804 ++num_bulk_in;
805 }
806
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700807 if (usb_endpoint_is_bulk_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 /* we found a bulk out endpoint */
809 dbg("found bulk out on endpoint %d", i);
810 bulk_out_endpoint[num_bulk_out] = endpoint;
811 ++num_bulk_out;
812 }
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700813
814 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 /* we found a interrupt in endpoint */
816 dbg("found interrupt in on endpoint %d", i);
817 interrupt_in_endpoint[num_interrupt_in] = endpoint;
818 ++num_interrupt_in;
819 }
820
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700821 if (usb_endpoint_is_int_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 /* we found an interrupt out endpoint */
823 dbg("found interrupt out on endpoint %d", i);
824 interrupt_out_endpoint[num_interrupt_out] = endpoint;
825 ++num_interrupt_out;
826 }
827 }
828
829#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100830 /* BEGIN HORRIBLE HACK FOR PL2303 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 /* this is needed due to the looney way its endpoints are set up */
832 if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&
833 (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||
834 ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) &&
Johannes Steingraeber8fd80132006-09-16 16:17:34 +0200835 (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) ||
836 ((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) &&
Andreas Bombece816cf2008-09-14 01:58:55 +0200837 (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID)) ||
838 ((le16_to_cpu(dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) &&
839 (le16_to_cpu(dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_EF81))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 if (interface != dev->actconfig->interface[0]) {
841 /* check out the endpoints of the other interface*/
842 iface_desc = dev->actconfig->interface[0]->cur_altsetting;
843 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
844 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700845 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 /* we found a interrupt in endpoint */
847 dbg("found interrupt in for Prolific device on separate interface");
848 interrupt_in_endpoint[num_interrupt_in] = endpoint;
849 ++num_interrupt_in;
850 }
851 }
852 }
853
854 /* Now make sure the PL-2303 is configured correctly.
855 * If not, give up now and hope this hack will work
856 * properly during a later invocation of usb_serial_probe
857 */
858 if (num_bulk_in == 0 || num_bulk_out == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100859 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860 dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100861 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 return -ENODEV;
863 }
864 }
865 /* END HORRIBLE HACK FOR PL2303 */
866#endif
867
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868#ifdef CONFIG_USB_SERIAL_GENERIC
869 if (type == &usb_serial_generic_device) {
870 num_ports = num_bulk_out;
871 if (num_ports == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100872 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100873 dev_err(&interface->dev,
874 "Generic device with no bulk out, not allowed.\n");
875 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876 return -EIO;
877 }
878 }
879#endif
880 if (!num_ports) {
881 /* if this device type has a calc_num_ports function, call it */
882 if (type->calc_num_ports) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700883 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100884 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100885 dev_err(&interface->dev,
886 "module get failed, exiting\n");
887 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 return -EIO;
889 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100890 num_ports = type->calc_num_ports(serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700891 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 }
893 if (!num_ports)
894 num_ports = type->num_ports;
895 }
896
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 serial->num_ports = num_ports;
898 serial->num_bulk_in = num_bulk_in;
899 serial->num_bulk_out = num_bulk_out;
900 serial->num_interrupt_in = num_interrupt_in;
901 serial->num_interrupt_out = num_interrupt_out;
902
Alan Stern063a2da2007-10-10 16:24:06 -0400903 /* found all that we need */
904 dev_info(&interface->dev, "%s converter detected\n",
905 type->description);
906
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 /* create our ports, we need as many as the max endpoints */
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100908 /* we don't use num_ports here because some devices have more
909 endpoint pairs than ports */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 max_endpoints = max(num_bulk_in, num_bulk_out);
911 max_endpoints = max(max_endpoints, num_interrupt_in);
912 max_endpoints = max(max_endpoints, num_interrupt_out);
913 max_endpoints = max(max_endpoints, (int)serial->num_ports);
914 serial->num_port_pointers = max_endpoints;
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100915 unlock_kernel();
916
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100917 dbg("%s - setting up %d port structures for this device",
918 __func__, max_endpoints);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 for (i = 0; i < max_endpoints; ++i) {
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100920 port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 if (!port)
922 goto probe_error;
Alan Cox4a90f092008-10-13 10:39:46 +0100923 tty_port_init(&port->port);
Alan Cox335f8512009-06-11 12:26:29 +0100924 port->port.ops = &serial_port_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 port->serial = serial;
Greg Kroah-Hartman507ca9b2005-04-23 12:49:16 -0700926 spin_lock_init(&port->lock);
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300927 mutex_init(&port->mutex);
David Howellsc4028952006-11-22 14:57:56 +0000928 INIT_WORK(&port->work, usb_serial_port_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 serial->port[i] = port;
Alan Stern41bd34d2009-09-01 11:38:34 -0400930 port->dev.parent = &interface->dev;
931 port->dev.driver = NULL;
932 port->dev.bus = &usb_serial_bus_type;
933 port->dev.release = &port_release;
934 device_initialize(&port->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 }
936
937 /* set up the endpoint information */
938 for (i = 0; i < num_bulk_in; ++i) {
939 endpoint = bulk_in_endpoint[i];
940 port = serial->port[i];
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100941 port->read_urb = usb_alloc_urb(0, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 if (!port->read_urb) {
943 dev_err(&interface->dev, "No free urbs available\n");
944 goto probe_error;
945 }
946 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
947 port->bulk_in_size = buffer_size;
948 port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100949 port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 if (!port->bulk_in_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100951 dev_err(&interface->dev,
952 "Couldn't allocate bulk_in_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 goto probe_error;
954 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100955 usb_fill_bulk_urb(port->read_urb, dev,
956 usb_rcvbulkpipe(dev,
957 endpoint->bEndpointAddress),
958 port->bulk_in_buffer, buffer_size,
959 serial->type->read_bulk_callback, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 }
961
962 for (i = 0; i < num_bulk_out; ++i) {
963 endpoint = bulk_out_endpoint[i];
964 port = serial->port[i];
965 port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
966 if (!port->write_urb) {
967 dev_err(&interface->dev, "No free urbs available\n");
968 goto probe_error;
969 }
David VomLehn8e8dce02009-08-28 12:54:27 -0700970 port->write_fifo = kfifo_alloc(PAGE_SIZE, GFP_KERNEL,
971 &port->lock);
972 if (IS_ERR(port->write_fifo))
973 goto probe_error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
975 port->bulk_out_size = buffer_size;
976 port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100977 port->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 if (!port->bulk_out_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100979 dev_err(&interface->dev,
980 "Couldn't allocate bulk_out_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 goto probe_error;
982 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100983 usb_fill_bulk_urb(port->write_urb, dev,
984 usb_sndbulkpipe(dev,
985 endpoint->bEndpointAddress),
986 port->bulk_out_buffer, buffer_size,
987 serial->type->write_bulk_callback, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 }
989
990 if (serial->type->read_int_callback) {
991 for (i = 0; i < num_interrupt_in; ++i) {
992 endpoint = interrupt_in_endpoint[i];
993 port = serial->port[i];
994 port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
995 if (!port->interrupt_in_urb) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100996 dev_err(&interface->dev,
997 "No free urbs available\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 goto probe_error;
999 }
1000 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001001 port->interrupt_in_endpointAddress =
1002 endpoint->bEndpointAddress;
1003 port->interrupt_in_buffer = kmalloc(buffer_size,
1004 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005 if (!port->interrupt_in_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001006 dev_err(&interface->dev,
1007 "Couldn't allocate interrupt_in_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 goto probe_error;
1009 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001010 usb_fill_int_urb(port->interrupt_in_urb, dev,
1011 usb_rcvintpipe(dev,
1012 endpoint->bEndpointAddress),
1013 port->interrupt_in_buffer, buffer_size,
1014 serial->type->read_int_callback, port,
1015 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 }
1017 } else if (num_interrupt_in) {
1018 dbg("the device claims to support interrupt in transfers, but read_int_callback is not defined");
1019 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001020
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 if (serial->type->write_int_callback) {
1022 for (i = 0; i < num_interrupt_out; ++i) {
1023 endpoint = interrupt_out_endpoint[i];
1024 port = serial->port[i];
1025 port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
1026 if (!port->interrupt_out_urb) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001027 dev_err(&interface->dev,
1028 "No free urbs available\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 goto probe_error;
1030 }
1031 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
1032 port->interrupt_out_size = buffer_size;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001033 port->interrupt_out_endpointAddress =
1034 endpoint->bEndpointAddress;
1035 port->interrupt_out_buffer = kmalloc(buffer_size,
1036 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 if (!port->interrupt_out_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001038 dev_err(&interface->dev,
1039 "Couldn't allocate interrupt_out_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 goto probe_error;
1041 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001042 usb_fill_int_urb(port->interrupt_out_urb, dev,
1043 usb_sndintpipe(dev,
1044 endpoint->bEndpointAddress),
1045 port->interrupt_out_buffer, buffer_size,
1046 serial->type->write_int_callback, port,
1047 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 }
1049 } else if (num_interrupt_out) {
1050 dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined");
1051 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001052
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 /* if this device type has an attach function, call it */
1054 if (type->attach) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -07001055 if (!try_module_get(type->driver.owner)) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001056 dev_err(&interface->dev,
1057 "module get failed, exiting\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 goto probe_error;
1059 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001060 retval = type->attach(serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -07001061 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 if (retval < 0)
1063 goto probe_error;
1064 if (retval > 0) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001065 /* quietly accept this device, but don't bind to a
1066 serial port as it's about to disappear */
Alan Stern0a3c8542009-05-27 11:25:52 -04001067 serial->num_ports = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 goto exit;
1069 }
1070 }
1071
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001072 if (get_free_serial(serial, num_ports, &minor) == NULL) {
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001073 dev_err(&interface->dev, "No more free serial devices\n");
1074 goto probe_error;
1075 }
Oliver Neukumc744f992007-02-26 15:43:00 +01001076 serial->minor = minor;
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001077
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078 /* register all of the individual ports with the driver core */
1079 for (i = 0; i < num_ports; ++i) {
1080 port = serial->port[i];
Kay Sievers0031a062008-05-02 06:02:41 +02001081 dev_set_name(&port->dev, "ttyUSB%d", port->number);
Kay Sievers7071a3c2008-05-02 06:02:41 +02001082 dbg ("%s - registering %s", __func__, dev_name(&port->dev));
Alan Sternc706ebd2009-06-02 11:54:11 -04001083 port->dev_state = PORT_REGISTERING;
Alan Stern41bd34d2009-09-01 11:38:34 -04001084 retval = device_add(&port->dev);
Alan Sternc706ebd2009-06-02 11:54:11 -04001085 if (retval) {
Greg Kroah-Hartman13f4db92006-08-28 11:43:25 -07001086 dev_err(&port->dev, "Error registering port device, "
1087 "continuing\n");
Alan Sternc706ebd2009-06-02 11:54:11 -04001088 port->dev_state = PORT_UNREGISTERED;
1089 } else {
1090 port->dev_state = PORT_REGISTERED;
1091 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 }
1093
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001094 usb_serial_console_init(debug, minor);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095
1096exit:
1097 /* success */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001098 usb_set_intfdata(interface, serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099 return 0;
1100
1101probe_error:
Alan Stern41bd34d2009-09-01 11:38:34 -04001102 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 return -EIO;
1104}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001105EXPORT_SYMBOL_GPL(usb_serial_probe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106
1107void usb_serial_disconnect(struct usb_interface *interface)
1108{
1109 int i;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001110 struct usb_serial *serial = usb_get_intfdata(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 struct device *dev = &interface->dev;
1112 struct usb_serial_port *port;
1113
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +02001114 usb_serial_console_disconnect(serial);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001115 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001117 mutex_lock(&serial->disc_mutex);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001118 usb_set_intfdata(interface, NULL);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001119 /* must set a flag, to signal subdrivers */
1120 serial->disconnected = 1;
Alan Stern2d931482009-04-14 11:31:02 -04001121 mutex_unlock(&serial->disc_mutex);
1122
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001123 for (i = 0; i < serial->num_ports; ++i) {
1124 port = serial->port[i];
1125 if (port) {
Alan Cox4a90f092008-10-13 10:39:46 +01001126 struct tty_struct *tty = tty_port_tty_get(&port->port);
1127 if (tty) {
Alan Coxd2b39182009-09-19 13:13:23 -07001128 tty_vhangup(tty);
Alan Cox4a90f092008-10-13 10:39:46 +01001129 tty_kref_put(tty);
1130 }
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001131 kill_traffic(port);
Alan Stern2d931482009-04-14 11:31:02 -04001132 cancel_work_sync(&port->work);
Alan Sternc706ebd2009-06-02 11:54:11 -04001133 if (port->dev_state == PORT_REGISTERED) {
1134
1135 /* Make sure the port is bound so that the
1136 * driver's port_remove method is called.
1137 */
1138 if (!port->dev.driver) {
1139 int rc;
1140
1141 port->dev.driver =
1142 &serial->type->driver;
1143 rc = device_bind_driver(&port->dev);
1144 }
1145 port->dev_state = PORT_UNREGISTERING;
1146 device_del(&port->dev);
1147 port->dev_state = PORT_UNREGISTERED;
1148 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 }
Alan Sternf9c99bb2009-06-02 11:53:55 -04001151 serial->type->disconnect(serial);
Alan Stern2d931482009-04-14 11:31:02 -04001152
Alan Stern41bd34d2009-09-01 11:38:34 -04001153 /* let the last holder of this object cause it to be cleaned up */
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001154 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 dev_info(dev, "device disconnected\n");
1156}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001157EXPORT_SYMBOL_GPL(usb_serial_disconnect);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158
Oliver Neukumec225592007-04-27 20:54:57 +02001159int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
1160{
1161 struct usb_serial *serial = usb_get_intfdata(intf);
1162 struct usb_serial_port *port;
1163 int i, r = 0;
1164
Oliver Neukumf8bece82009-02-05 16:54:25 +01001165 serial->suspending = 1;
1166
Oliver Neukum81e5b232009-07-21 08:47:34 +02001167 if (serial->type->suspend) {
1168 r = serial->type->suspend(serial, message);
1169 if (r < 0)
1170 goto err_out;
1171 }
1172
Oliver Neukume31c1882007-07-23 08:58:39 +02001173 for (i = 0; i < serial->num_ports; ++i) {
1174 port = serial->port[i];
1175 if (port)
1176 kill_traffic(port);
Oliver Neukumec225592007-04-27 20:54:57 +02001177 }
1178
Oliver Neukum81e5b232009-07-21 08:47:34 +02001179err_out:
Oliver Neukumec225592007-04-27 20:54:57 +02001180 return r;
1181}
1182EXPORT_SYMBOL(usb_serial_suspend);
1183
1184int usb_serial_resume(struct usb_interface *intf)
1185{
1186 struct usb_serial *serial = usb_get_intfdata(intf);
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001187 int rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001188
Oliver Neukumf8bece82009-02-05 16:54:25 +01001189 serial->suspending = 0;
Sarah Sharp8abaee22007-10-25 10:58:43 -07001190 if (serial->type->resume)
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001191 rv = serial->type->resume(serial);
1192 else
1193 rv = usb_serial_generic_resume(serial);
Oliver Neukumf8bece82009-02-05 16:54:25 +01001194
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001195 return rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001196}
1197EXPORT_SYMBOL(usb_serial_resume);
1198
Jeff Dikeb68e31d2006-10-02 02:17:18 -07001199static const struct tty_operations serial_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 .open = serial_open,
1201 .close = serial_close,
1202 .write = serial_write,
Alan Cox335f8512009-06-11 12:26:29 +01001203 .hangup = serial_hangup,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 .write_room = serial_write_room,
1205 .ioctl = serial_ioctl,
1206 .set_termios = serial_set_termios,
1207 .throttle = serial_throttle,
1208 .unthrottle = serial_unthrottle,
1209 .break_ctl = serial_break,
1210 .chars_in_buffer = serial_chars_in_buffer,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 .tiocmget = serial_tiocmget,
1212 .tiocmset = serial_tiocmset,
Alan Stern74556122009-09-01 11:39:40 -04001213 .shutdown = serial_release,
Alan Coxfe1ae7f2009-09-19 13:13:33 -07001214 .install = serial_install,
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -07001215 .proc_fops = &serial_proc_fops,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216};
1217
Alan Cox335f8512009-06-11 12:26:29 +01001218
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219struct tty_driver *usb_serial_tty_driver;
1220
1221static int __init usb_serial_init(void)
1222{
1223 int i;
1224 int result;
1225
1226 usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS);
1227 if (!usb_serial_tty_driver)
1228 return -ENOMEM;
1229
1230 /* Initialize our global data */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001231 for (i = 0; i < SERIAL_TTY_MINORS; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 serial_table[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233
1234 result = bus_register(&usb_serial_bus_type);
1235 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001236 printk(KERN_ERR "usb-serial: %s - registering bus driver "
1237 "failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 goto exit_bus;
1239 }
1240
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241 usb_serial_tty_driver->owner = THIS_MODULE;
1242 usb_serial_tty_driver->driver_name = "usbserial";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243 usb_serial_tty_driver->name = "ttyUSB";
1244 usb_serial_tty_driver->major = SERIAL_TTY_MAJOR;
1245 usb_serial_tty_driver->minor_start = 0;
1246 usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
1247 usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001248 usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW |
1249 TTY_DRIVER_DYNAMIC_DEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250 usb_serial_tty_driver->init_termios = tty_std_termios;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001251 usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD
1252 | HUPCL | CLOCAL;
Alan Coxa5b6f602008-04-08 17:16:06 +01001253 usb_serial_tty_driver->init_termios.c_ispeed = 9600;
1254 usb_serial_tty_driver->init_termios.c_ospeed = 9600;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255 tty_set_operations(usb_serial_tty_driver, &serial_ops);
1256 result = tty_register_driver(usb_serial_tty_driver);
1257 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001258 printk(KERN_ERR "usb-serial: %s - tty_register_driver failed\n",
1259 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260 goto exit_reg_driver;
1261 }
1262
1263 /* register the USB driver */
1264 result = usb_register(&usb_serial_driver);
1265 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001266 printk(KERN_ERR "usb-serial: %s - usb_register failed\n",
1267 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 goto exit_tty;
1269 }
1270
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001271 /* register the generic driver, if we should */
1272 result = usb_serial_generic_register(debug);
1273 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001274 printk(KERN_ERR "usb-serial: %s - registering generic "
1275 "driver failed\n", __func__);
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001276 goto exit_generic;
1277 }
1278
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001279 printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280
1281 return result;
1282
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001283exit_generic:
1284 usb_deregister(&usb_serial_driver);
1285
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286exit_tty:
1287 tty_unregister_driver(usb_serial_tty_driver);
1288
1289exit_reg_driver:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290 bus_unregister(&usb_serial_bus_type);
1291
1292exit_bus:
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001293 printk(KERN_ERR "usb-serial: %s - returning with error %d\n",
1294 __func__, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295 put_tty_driver(usb_serial_tty_driver);
1296 return result;
1297}
1298
1299
1300static void __exit usb_serial_exit(void)
1301{
1302 usb_serial_console_exit();
1303
1304 usb_serial_generic_deregister();
1305
1306 usb_deregister(&usb_serial_driver);
1307 tty_unregister_driver(usb_serial_tty_driver);
1308 put_tty_driver(usb_serial_tty_driver);
1309 bus_unregister(&usb_serial_bus_type);
1310}
1311
1312
1313module_init(usb_serial_init);
1314module_exit(usb_serial_exit);
1315
1316#define set_to_generic_if_null(type, function) \
1317 do { \
1318 if (!type->function) { \
1319 type->function = usb_serial_generic_##function; \
1320 dbg("Had to override the " #function \
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001321 " usb serial operation with the generic one.");\
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322 } \
1323 } while (0)
1324
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001325static void fixup_generic(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326{
1327 set_to_generic_if_null(device, open);
1328 set_to_generic_if_null(device, write);
1329 set_to_generic_if_null(device, close);
1330 set_to_generic_if_null(device, write_room);
1331 set_to_generic_if_null(device, chars_in_buffer);
1332 set_to_generic_if_null(device, read_bulk_callback);
1333 set_to_generic_if_null(device, write_bulk_callback);
Alan Sternf9c99bb2009-06-02 11:53:55 -04001334 set_to_generic_if_null(device, disconnect);
1335 set_to_generic_if_null(device, release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336}
1337
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001338int usb_serial_register(struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001340 /* must be called with BKL held */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 int retval;
1342
Dave Younge4abe662009-02-14 21:21:13 +08001343 if (usb_disabled())
1344 return -ENODEV;
1345
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001346 fixup_generic(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001348 if (!driver->description)
1349 driver->description = driver->driver.name;
1350
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 /* Add this device to our list of devices */
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001352 list_add(&driver->driver_list, &usb_serial_driver_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001354 retval = usb_serial_bus_register(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355 if (retval) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001356 printk(KERN_ERR "usb-serial: problem %d when registering "
1357 "driver %s\n", retval, driver->description);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001358 list_del(&driver->driver_list);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001359 } else
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001360 printk(KERN_INFO "USB Serial support registered for %s\n",
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001361 driver->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362
1363 return retval;
1364}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001365EXPORT_SYMBOL_GPL(usb_serial_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366
1367
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001368void usb_serial_deregister(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001370 /* must be called with BKL held */
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001371 printk(KERN_INFO "USB Serial deregistering driver %s\n",
1372 device->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 list_del(&device->driver_list);
1374 usb_serial_bus_deregister(device);
1375}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376EXPORT_SYMBOL_GPL(usb_serial_deregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377
1378/* Module information */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001379MODULE_AUTHOR(DRIVER_AUTHOR);
1380MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381MODULE_LICENSE("GPL");
1382
1383module_param(debug, bool, S_IRUGO | S_IWUSR);
1384MODULE_PARM_DESC(debug, "Debug enabled or not");