blob: 9d7ca4868d37cf642ba47fa1f34caa122d14be92 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * USB Serial Converter driver
3 *
Greg Kroah-Hartman502b95c2005-06-20 21:15:16 -07004 * Copyright (C) 1999 - 2005 Greg Kroah-Hartman (greg@kroah.com)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 * Copyright (C) 2000 Peter Berger (pberger@brimson.com)
6 * Copyright (C) 2000 Al Borchers (borchers@steinerpoint.com)
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version
10 * 2 as published by the Free Software Foundation.
11 *
Greg Kroah-Hartman502b95c2005-06-20 21:15:16 -070012 * This driver was originally based on the ACM driver by Armin Fuerst (which was
Linus Torvalds1da177e2005-04-16 15:20:36 -070013 * based on a driver by Brad Keryan)
14 *
Alan Coxa8d6f0a2008-07-22 11:12:24 +010015 * See Documentation/usb/usb-serial.txt for more information on using this
16 * driver
Linus Torvalds1da177e2005-04-16 15:20:36 -070017 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 */
19
Linus Torvalds1da177e2005-04-16 15:20:36 -070020#include <linux/kernel.h>
21#include <linux/errno.h>
22#include <linux/init.h>
23#include <linux/slab.h>
Alexey Dobriyan405f5572009-07-11 22:08:37 +040024#include <linux/smp_lock.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <linux/tty.h>
26#include <linux/tty_driver.h>
27#include <linux/tty_flip.h>
28#include <linux/module.h>
29#include <linux/moduleparam.h>
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -070030#include <linux/seq_file.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <linux/spinlock.h>
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -030032#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/list.h>
Alan Coxa8d6f0a2008-07-22 11:12:24 +010034#include <linux/uaccess.h>
Alan Coxc56d3002009-07-28 00:34:58 +010035#include <linux/serial.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#include <linux/usb.h>
Greg Kroah-Hartmana9698882006-07-11 21:22:58 -070037#include <linux/usb/serial.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070038#include "pl2303.h"
39
40/*
41 * Version Information
42 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/"
44#define DRIVER_DESC "USB Serial Driver core"
45
46/* Driver structure we register with the USB core */
47static struct usb_driver usb_serial_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070048 .name = "usbserial",
49 .probe = usb_serial_probe,
50 .disconnect = usb_serial_disconnect,
Oliver Neukumec225592007-04-27 20:54:57 +020051 .suspend = usb_serial_suspend,
52 .resume = usb_serial_resume,
Greg Kroah-Hartmanba9dc652005-11-16 13:41:28 -080053 .no_dynamic_id = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -070054};
55
56/* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead
57 the MODULE_DEVICE_TABLE declarations in each serial driver
58 cause the "hotplug" program to pull in whatever module is necessary
59 via modprobe, and modprobe will load usbserial because the serial
60 drivers depend on it.
61*/
62
63static int debug;
Alan Coxa8d6f0a2008-07-22 11:12:24 +010064/* initially all NULL */
65static struct usb_serial *serial_table[SERIAL_TTY_MINORS];
Oliver Neukum3ddad822007-07-24 15:13:42 +020066static DEFINE_MUTEX(table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070067static LIST_HEAD(usb_serial_driver_list);
68
Alan Stern8bc2c1b2009-09-01 11:38:59 -040069/*
70 * Look up the serial structure. If it is found and it hasn't been
71 * disconnected, return with its disc_mutex held and its refcount
72 * incremented. Otherwise return NULL.
73 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070074struct usb_serial *usb_serial_get_by_index(unsigned index)
75{
Oliver Neukum34ef50e2007-01-13 07:29:26 +010076 struct usb_serial *serial;
77
Oliver Neukum3ddad822007-07-24 15:13:42 +020078 mutex_lock(&table_lock);
Oliver Neukum34ef50e2007-01-13 07:29:26 +010079 serial = serial_table[index];
Linus Torvalds1da177e2005-04-16 15:20:36 -070080
Alan Stern8bc2c1b2009-09-01 11:38:59 -040081 if (serial) {
82 mutex_lock(&serial->disc_mutex);
83 if (serial->disconnected) {
84 mutex_unlock(&serial->disc_mutex);
85 serial = NULL;
86 } else {
87 kref_get(&serial->kref);
88 }
89 }
Oliver Neukum3ddad822007-07-24 15:13:42 +020090 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070091 return serial;
92}
93
Alan Coxa8d6f0a2008-07-22 11:12:24 +010094static struct usb_serial *get_free_serial(struct usb_serial *serial,
95 int num_ports, unsigned int *minor)
Linus Torvalds1da177e2005-04-16 15:20:36 -070096{
97 unsigned int i, j;
98 int good_spot;
99
Harvey Harrison441b62c2008-03-03 16:08:34 -0800100 dbg("%s %d", __func__, num_ports);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101
102 *minor = 0;
Oliver Neukum3ddad822007-07-24 15:13:42 +0200103 mutex_lock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
105 if (serial_table[i])
106 continue;
107
108 good_spot = 1;
109 for (j = 1; j <= num_ports-1; ++j)
110 if ((i+j >= SERIAL_TTY_MINORS) || (serial_table[i+j])) {
111 good_spot = 0;
112 i += j;
113 break;
114 }
115 if (good_spot == 0)
116 continue;
117
118 *minor = i;
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100119 j = 0;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800120 dbg("%s - minor base = %d", __func__, *minor);
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100121 for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122 serial_table[i] = serial;
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100123 serial->port[j++]->number = i;
124 }
Oliver Neukum3ddad822007-07-24 15:13:42 +0200125 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126 return serial;
127 }
Oliver Neukum3ddad822007-07-24 15:13:42 +0200128 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129 return NULL;
130}
131
132static void return_serial(struct usb_serial *serial)
133{
134 int i;
135
Harvey Harrison441b62c2008-03-03 16:08:34 -0800136 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137
Alan Stern8bc2c1b2009-09-01 11:38:59 -0400138 mutex_lock(&table_lock);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100139 for (i = 0; i < serial->num_ports; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140 serial_table[serial->minor + i] = NULL;
Alan Stern8bc2c1b2009-09-01 11:38:59 -0400141 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142}
143
144static void destroy_serial(struct kref *kref)
145{
146 struct usb_serial *serial;
147 struct usb_serial_port *port;
148 int i;
149
150 serial = to_usb_serial(kref);
151
Harvey Harrison441b62c2008-03-03 16:08:34 -0800152 dbg("%s - %s", __func__, serial->type->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153
Jim Radford521b85a2007-03-13 08:30:50 -0700154 /* return the minor range that this device had */
Alan Stern0282b7f2008-07-29 12:01:04 -0400155 if (serial->minor != SERIAL_TTY_NO_MINOR)
156 return_serial(serial);
Jim Radford521b85a2007-03-13 08:30:50 -0700157
Alan Sternf9c99bb2009-06-02 11:53:55 -0400158 serial->type->release(serial);
159
Alan Stern41bd34d2009-09-01 11:38:34 -0400160 /* Now that nothing is using the ports, they can be freed */
161 for (i = 0; i < serial->num_port_pointers; ++i) {
Alan Sternf9c99bb2009-06-02 11:53:55 -0400162 port = serial->port[i];
Alan Stern41bd34d2009-09-01 11:38:34 -0400163 if (port) {
164 port->serial = NULL;
Alan Sternf9c99bb2009-06-02 11:53:55 -0400165 put_device(&port->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 }
167 }
168
169 usb_put_dev(serial->dev);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100170 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171}
172
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200173void usb_serial_put(struct usb_serial *serial)
174{
175 kref_put(&serial->kref, destroy_serial);
176}
177
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178/*****************************************************************************
179 * Driver tty interface functions
180 *****************************************************************************/
Alan Sternf5b09532009-09-01 11:38:44 -0400181
182/**
183 * serial_install - install tty
184 * @driver: the driver (USB in our case)
185 * @tty: the tty being created
186 *
187 * Create the termios objects for this tty. We use the default
188 * USB serial settings but permit them to be overridden by
189 * serial->type->init_termios.
Alan Sterncc56cd02009-09-01 11:39:13 -0400190 *
191 * This is the first place a new tty gets used. Hence this is where we
192 * acquire references to the usb_serial structure and the driver module,
193 * where we store a pointer to the port, and where we do an autoresume.
Alan Stern74556122009-09-01 11:39:40 -0400194 * All these actions are reversed in serial_release().
Alan Sternf5b09532009-09-01 11:38:44 -0400195 */
196static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
197{
198 int idx = tty->index;
199 struct usb_serial *serial;
Alan Sterncc56cd02009-09-01 11:39:13 -0400200 struct usb_serial_port *port;
201 int retval = -ENODEV;
202
Alan Sternff8324d2009-09-01 11:39:51 -0400203 dbg("%s", __func__);
204
Alan Sterncc56cd02009-09-01 11:39:13 -0400205 serial = usb_serial_get_by_index(idx);
206 if (!serial)
207 return retval;
208
209 port = serial->port[idx - serial->minor];
210 if (!port)
211 goto error_no_port;
212 if (!try_module_get(serial->type->driver.owner))
213 goto error_module_get;
214
Alan Stern7e29bb42009-09-01 11:39:22 -0400215 /* perform the standard setup */
216 retval = tty_init_termios(tty);
217 if (retval)
218 goto error_init_termios;
219
Alan Sterncc56cd02009-09-01 11:39:13 -0400220 retval = usb_autopm_get_interface(serial->interface);
221 if (retval)
222 goto error_get_interface;
Alan Sternf5b09532009-09-01 11:38:44 -0400223
Alan Sterncc56cd02009-09-01 11:39:13 -0400224 mutex_unlock(&serial->disc_mutex);
225
Alan Stern7e29bb42009-09-01 11:39:22 -0400226 /* allow the driver to update the settings */
227 if (serial->type->init_termios)
228 serial->type->init_termios(tty);
229
Alan Sterncc56cd02009-09-01 11:39:13 -0400230 tty->driver_data = port;
231
Alan Sternf5b09532009-09-01 11:38:44 -0400232 /* Final install (we use the default method) */
233 tty_driver_kref_get(driver);
234 tty->count++;
235 driver->ttys[idx] = tty;
Alan Sterncc56cd02009-09-01 11:39:13 -0400236 return retval;
237
Alan Sterncc56cd02009-09-01 11:39:13 -0400238 error_get_interface:
Alan Stern7e29bb42009-09-01 11:39:22 -0400239 error_init_termios:
Alan Sterncc56cd02009-09-01 11:39:13 -0400240 module_put(serial->type->driver.owner);
241 error_module_get:
242 error_no_port:
243 usb_serial_put(serial);
244 mutex_unlock(&serial->disc_mutex);
245 return retval;
Alan Sternf5b09532009-09-01 11:38:44 -0400246}
247
Alan Stern320348c2009-09-01 11:39:59 -0400248static int serial_open(struct tty_struct *tty, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249{
Alan Stern320348c2009-09-01 11:39:59 -0400250 struct usb_serial_port *port = tty->driver_data;
251 struct usb_serial *serial = port->serial;
252 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253
Alan Sternff8324d2009-09-01 11:39:51 -0400254 dbg("%s - port %d", __func__, port->number);
255
Alan Stern320348c2009-09-01 11:39:59 -0400256 spin_lock_irq(&port->port.lock);
257 if (!tty_hung_up_p(filp))
258 ++port->port.count;
259 spin_unlock_irq(&port->port.lock);
Alan Cox4a90f092008-10-13 10:39:46 +0100260 tty_port_tty_set(&port->port, tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261
Alan Stern320348c2009-09-01 11:39:59 -0400262 /* Do the device-specific open only if the hardware isn't
263 * already initialized.
264 */
265 if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) {
266 if (mutex_lock_interruptible(&port->mutex))
267 return -ERESTARTSYS;
Alan Stern2d931482009-04-14 11:31:02 -0400268 mutex_lock(&serial->disc_mutex);
Alan Stern320348c2009-09-01 11:39:59 -0400269 if (serial->disconnected)
270 retval = -ENODEV;
271 else
272 retval = port->serial->type->open(tty, port);
Alan Stern2d931482009-04-14 11:31:02 -0400273 mutex_unlock(&serial->disc_mutex);
Alan Stern320348c2009-09-01 11:39:59 -0400274 mutex_unlock(&port->mutex);
275 if (retval)
276 return retval;
Alan Coxc56d3002009-07-28 00:34:58 +0100277 set_bit(ASYNCB_INITIALIZED, &port->port.flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 }
Alan Stern320348c2009-09-01 11:39:59 -0400279
Alan Cox335f8512009-06-11 12:26:29 +0100280 /* Now do the correct tty layer semantics */
281 retval = tty_port_block_til_ready(&port->port, tty, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 return retval;
283}
284
Alan Cox335f8512009-06-11 12:26:29 +0100285/**
Alan Stern74556122009-09-01 11:39:40 -0400286 * serial_down - shut down hardware
Alan Sternf5b09532009-09-01 11:38:44 -0400287 * @port: port to shut down
Alan Cox335f8512009-06-11 12:26:29 +0100288 *
Alan Sternf5b09532009-09-01 11:38:44 -0400289 * Shut down a USB serial port unless it is the console. We never
290 * shut down the console hardware as it will always be in use.
Alan Cox335f8512009-06-11 12:26:29 +0100291 */
Alan Stern74556122009-09-01 11:39:40 -0400292static void serial_down(struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293{
Alan Cox335f8512009-06-11 12:26:29 +0100294 struct usb_serial_driver *drv = port->serial->type;
Alan Stern2d931482009-04-14 11:31:02 -0400295 struct usb_serial *serial;
296 struct module *owner;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297
Alan Sternf5b09532009-09-01 11:38:44 -0400298 /*
299 * The console is magical. Do not hang up the console hardware
300 * or there will be tears.
301 */
Alan Cox335f8512009-06-11 12:26:29 +0100302 if (port->console)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303 return;
304
Alan Sternff8324d2009-09-01 11:39:51 -0400305 /* Don't call the close method if the hardware hasn't been
306 * initialized.
307 */
308 if (!test_and_clear_bit(ASYNCB_INITIALIZED, &port->port.flags))
309 return;
310
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300311 mutex_lock(&port->mutex);
Alan Stern2d931482009-04-14 11:31:02 -0400312 serial = port->serial;
313 owner = serial->type->driver.owner;
Luiz Fernando Capitulino8a4613f2005-11-28 19:16:07 -0200314
Alan Cox335f8512009-06-11 12:26:29 +0100315 if (drv->close)
316 drv->close(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300318 mutex_unlock(&port->mutex);
Alan Cox335f8512009-06-11 12:26:29 +0100319}
320
Alan Sternf5b09532009-09-01 11:38:44 -0400321static void serial_hangup(struct tty_struct *tty)
Alan Cox335f8512009-06-11 12:26:29 +0100322{
Alan Cox4455e342009-09-19 13:13:24 -0700323 struct usb_serial_port *port = tty->driver_data;
Alan Sternff8324d2009-09-01 11:39:51 -0400324
325 dbg("%s - port %d", __func__, port->number);
326
Alan Stern74556122009-09-01 11:39:40 -0400327 serial_down(port);
Alan Sternf5b09532009-09-01 11:38:44 -0400328 tty_port_hangup(&port->port);
Alan Cox335f8512009-06-11 12:26:29 +0100329}
330
331static void serial_close(struct tty_struct *tty, struct file *filp)
332{
333 struct usb_serial_port *port = tty->driver_data;
334
335 dbg("%s - port %d", __func__, port->number);
336
Alan Sternff8324d2009-09-01 11:39:51 -0400337 if (tty_hung_up_p(filp))
338 return;
Alan Cox335f8512009-06-11 12:26:29 +0100339 if (tty_port_close_start(&port->port, tty, filp) == 0)
340 return;
Alan Stern74556122009-09-01 11:39:40 -0400341 serial_down(port);
Alan Cox335f8512009-06-11 12:26:29 +0100342 tty_port_close_end(&port->port, tty);
343 tty_port_tty_set(&port->port, NULL);
Alan Cox335f8512009-06-11 12:26:29 +0100344}
345
Alan Sternf5b09532009-09-01 11:38:44 -0400346/**
Alan Stern74556122009-09-01 11:39:40 -0400347 * serial_release - free resources post close/hangup
Alan Sternf5b09532009-09-01 11:38:44 -0400348 * @port: port to free up
349 *
350 * Do the resource freeing and refcount dropping for the port.
351 * Avoid freeing the console.
352 *
353 * Called when the last tty kref is dropped.
354 */
Alan Stern74556122009-09-01 11:39:40 -0400355static void serial_release(struct tty_struct *tty)
Alan Cox335f8512009-06-11 12:26:29 +0100356{
357 struct usb_serial_port *port = tty->driver_data;
Alan Sternf5b09532009-09-01 11:38:44 -0400358 struct usb_serial *serial;
359 struct module *owner;
360
361 /* The console is magical. Do not hang up the console hardware
362 * or there will be tears.
363 */
Alan Sterncc56cd02009-09-01 11:39:13 -0400364 if (port->console)
Alan Sternf5b09532009-09-01 11:38:44 -0400365 return;
366
Alan Sternff8324d2009-09-01 11:39:51 -0400367 dbg("%s - port %d", __func__, port->number);
368
Alan Stern74556122009-09-01 11:39:40 -0400369 /* Standard shutdown processing */
370 tty_shutdown(tty);
371
Alan Sterncc56cd02009-09-01 11:39:13 -0400372 tty->driver_data = NULL;
373
Alan Sternf5b09532009-09-01 11:38:44 -0400374 serial = port->serial;
375 owner = serial->type->driver.owner;
376
377 mutex_lock(&serial->disc_mutex);
378 if (!serial->disconnected)
379 usb_autopm_put_interface(serial->interface);
380 mutex_unlock(&serial->disc_mutex);
381
382 usb_serial_put(serial);
383 module_put(owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384}
385
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100386static int serial_write(struct tty_struct *tty, const unsigned char *buf,
387 int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200389 struct usb_serial_port *port = tty->driver_data;
Oliver Neukum3ff4fd92007-01-13 07:32:27 +0100390 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391
Alan Coxf34d7a52008-04-30 00:54:13 -0700392 if (port->serial->dev->state == USB_STATE_NOTATTACHED)
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200393 goto exit;
394
Harvey Harrison441b62c2008-03-03 16:08:34 -0800395 dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396
Alan Cox95da3102008-07-22 11:09:07 +0100397 /* count is managed under the mutex lock for the tty so cannot
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100398 drop to zero until after the last close completes */
Alan Cox95da3102008-07-22 11:09:07 +0100399 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400
401 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100402 retval = port->serial->type->write(tty, port, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403
404exit:
405 return retval;
406}
407
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100408static int serial_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200410 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800411 dbg("%s - port %d", __func__, port->number);
Alan Cox95da3102008-07-22 11:09:07 +0100412 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100414 return port->serial->type->write_room(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415}
416
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100417static int serial_chars_in_buffer(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200419 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800420 dbg("%s = port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421
Alan Coxeff69372009-01-02 13:47:06 +0000422 /* if the device was unplugged then any remaining characters
423 fell out of the connector ;) */
424 if (port->serial->disconnected)
425 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100427 return port->serial->type->chars_in_buffer(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428}
429
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100430static void serial_throttle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200432 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800433 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434
Alan Cox95da3102008-07-22 11:09:07 +0100435 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 /* pass on to the driver specific version of this function */
437 if (port->serial->type->throttle)
Alan Cox95da3102008-07-22 11:09:07 +0100438 port->serial->type->throttle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439}
440
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100441static void serial_unthrottle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200443 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800444 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445
Alan Cox95da3102008-07-22 11:09:07 +0100446 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 /* pass on to the driver specific version of this function */
448 if (port->serial->type->unthrottle)
Alan Cox95da3102008-07-22 11:09:07 +0100449 port->serial->type->unthrottle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450}
451
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100452static int serial_ioctl(struct tty_struct *tty, struct file *file,
453 unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200455 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456 int retval = -ENODEV;
457
Harvey Harrison441b62c2008-03-03 16:08:34 -0800458 dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459
Alan Cox95da3102008-07-22 11:09:07 +0100460 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100462 /* pass on to the driver specific version of this function
463 if it is available */
Alan Coxf34d7a52008-04-30 00:54:13 -0700464 if (port->serial->type->ioctl) {
Alan Cox95da3102008-07-22 11:09:07 +0100465 retval = port->serial->type->ioctl(tty, file, cmd, arg);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100466 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467 retval = -ENOIOCTLCMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468 return retval;
469}
470
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100471static void serial_set_termios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200473 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800474 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475
Alan Cox95da3102008-07-22 11:09:07 +0100476 WARN_ON(!port->port.count);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100477 /* pass on to the driver specific version of this function
478 if it is available */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479 if (port->serial->type->set_termios)
Alan Cox95da3102008-07-22 11:09:07 +0100480 port->serial->type->set_termios(tty, port, old);
Alan Cox33785092007-10-18 01:24:22 -0700481 else
482 tty_termios_copy_hw(tty->termios, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483}
484
Alan Cox9e989662008-07-22 11:18:03 +0100485static int serial_break(struct tty_struct *tty, int break_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200487 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488
Harvey Harrison441b62c2008-03-03 16:08:34 -0800489 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490
Alan Cox95da3102008-07-22 11:09:07 +0100491 WARN_ON(!port->port.count);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100492 /* pass on to the driver specific version of this function
493 if it is available */
Alan Cox6b447f042009-01-02 13:48:56 +0000494 if (port->serial->type->break_ctl)
Alan Cox95da3102008-07-22 11:09:07 +0100495 port->serial->type->break_ctl(tty, break_state);
Alan Cox9e989662008-07-22 11:18:03 +0100496 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497}
498
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700499static int serial_proc_show(struct seq_file *m, void *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500{
501 struct usb_serial *serial;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 char tmp[40];
504
Harvey Harrison441b62c2008-03-03 16:08:34 -0800505 dbg("%s", __func__);
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700506 seq_puts(m, "usbserinfo:1.0 driver:2.0\n");
507 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 serial = usb_serial_get_by_index(i);
509 if (serial == NULL)
510 continue;
511
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700512 seq_printf(m, "%d:", i);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700513 if (serial->type->driver.owner)
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700514 seq_printf(m, " module:%s",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100515 module_name(serial->type->driver.owner));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700516 seq_printf(m, " name:\"%s\"",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100517 serial->type->description);
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700518 seq_printf(m, " vendor:%04x product:%04x",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100519 le16_to_cpu(serial->dev->descriptor.idVendor),
520 le16_to_cpu(serial->dev->descriptor.idProduct));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700521 seq_printf(m, " num_ports:%d", serial->num_ports);
522 seq_printf(m, " port:%d", i - serial->minor + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 usb_make_path(serial->dev, tmp, sizeof(tmp));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700524 seq_printf(m, " path:%s", tmp);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100525
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700526 seq_putc(m, '\n');
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200527 usb_serial_put(serial);
Alan Stern8bc2c1b2009-09-01 11:38:59 -0400528 mutex_unlock(&serial->disc_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 }
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700530 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531}
532
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700533static int serial_proc_open(struct inode *inode, struct file *file)
534{
535 return single_open(file, serial_proc_show, NULL);
536}
537
538static const struct file_operations serial_proc_fops = {
539 .owner = THIS_MODULE,
540 .open = serial_proc_open,
541 .read = seq_read,
542 .llseek = seq_lseek,
543 .release = single_release,
544};
545
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100546static int serial_tiocmget(struct tty_struct *tty, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200548 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549
Harvey Harrison441b62c2008-03-03 16:08:34 -0800550 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551
Alan Cox95da3102008-07-22 11:09:07 +0100552 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 if (port->serial->type->tiocmget)
Alan Cox95da3102008-07-22 11:09:07 +0100554 return port->serial->type->tiocmget(tty, file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 return -EINVAL;
556}
557
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100558static int serial_tiocmset(struct tty_struct *tty, struct file *file,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 unsigned int set, unsigned int clear)
560{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200561 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562
Harvey Harrison441b62c2008-03-03 16:08:34 -0800563 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564
Alan Cox95da3102008-07-22 11:09:07 +0100565 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 if (port->serial->type->tiocmset)
Alan Cox95da3102008-07-22 11:09:07 +0100567 return port->serial->type->tiocmset(tty, file, set, clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568 return -EINVAL;
569}
570
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700571/*
572 * We would be calling tty_wakeup here, but unfortunately some line
573 * disciplines have an annoying habit of calling tty->write from
574 * the write wakeup callback (e.g. n_hdlc.c).
575 */
576void usb_serial_port_softint(struct usb_serial_port *port)
577{
578 schedule_work(&port->work);
579}
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100580EXPORT_SYMBOL_GPL(usb_serial_port_softint);
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700581
David Howellsc4028952006-11-22 14:57:56 +0000582static void usb_serial_port_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583{
David Howellsc4028952006-11-22 14:57:56 +0000584 struct usb_serial_port *port =
585 container_of(work, struct usb_serial_port, work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 struct tty_struct *tty;
587
Harvey Harrison441b62c2008-03-03 16:08:34 -0800588 dbg("%s - port %d", __func__, port->number);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100589
Alan Cox4a90f092008-10-13 10:39:46 +0100590 tty = tty_port_tty_get(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 if (!tty)
592 return;
593
594 tty_wakeup(tty);
Alan Cox4a90f092008-10-13 10:39:46 +0100595 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596}
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
Alan Stern41bd34d2009-09-01 11:38:34 -0400617static void port_release(struct device *dev)
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100618{
Alan Stern41bd34d2009-09-01 11:38:34 -0400619 struct usb_serial_port *port = to_usb_serial_port(dev);
620
621 dbg ("%s - %s", __func__, dev_name(dev));
622
Alan Stern2d931482009-04-14 11:31:02 -0400623 /*
624 * Stop all the traffic before cancelling the work, so that
625 * nobody will restart it by calling usb_serial_port_softint.
626 */
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100627 kill_traffic(port);
Alan Stern2d931482009-04-14 11:31:02 -0400628 cancel_work_sync(&port->work);
629
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100630 usb_free_urb(port->read_urb);
631 usb_free_urb(port->write_urb);
632 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 usb_free_urb(port->interrupt_out_urb);
634 kfree(port->bulk_in_buffer);
635 kfree(port->bulk_out_buffer);
636 kfree(port->interrupt_in_buffer);
637 kfree(port->interrupt_out_buffer);
638 kfree(port);
639}
640
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100641static struct usb_serial *create_serial(struct usb_device *dev,
642 struct usb_interface *interface,
643 struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644{
645 struct usb_serial *serial;
646
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100647 serial = kzalloc(sizeof(*serial), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 if (!serial) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800649 dev_err(&dev->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 return NULL;
651 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 serial->dev = usb_get_dev(dev);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700653 serial->type = driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 serial->interface = interface;
655 kref_init(&serial->kref);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +0100656 mutex_init(&serial->disc_mutex);
Alan Stern0282b7f2008-07-29 12:01:04 -0400657 serial->minor = SERIAL_TTY_NO_MINOR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658
659 return serial;
660}
661
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100662static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf,
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100663 struct usb_serial_driver *drv)
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100664{
665 struct usb_dynid *dynid;
666
667 spin_lock(&drv->dynids.lock);
668 list_for_each_entry(dynid, &drv->dynids.list, node) {
669 if (usb_match_one_id(intf, &dynid->id)) {
670 spin_unlock(&drv->dynids.lock);
671 return &dynid->id;
672 }
673 }
674 spin_unlock(&drv->dynids.lock);
675 return NULL;
676}
677
678static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv,
679 struct usb_interface *intf)
680{
681 const struct usb_device_id *id;
682
683 id = usb_match_id(intf, drv->id_table);
684 if (id) {
685 dbg("static descriptor matches");
686 goto exit;
687 }
688 id = match_dynamic_id(intf, drv);
689 if (id)
690 dbg("dynamic descriptor matches");
691exit:
692 return id;
693}
694
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100695static struct usb_serial_driver *search_serial_device(
696 struct usb_interface *iface)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 const struct usb_device_id *id;
Alan Stern063a2da2007-10-10 16:24:06 -0400699 struct usb_serial_driver *drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700
Adrian Bunk93b1fae2006-01-10 00:13:33 +0100701 /* Check if the usb id matches a known device */
Alan Stern063a2da2007-10-10 16:24:06 -0400702 list_for_each_entry(drv, &usb_serial_driver_list, driver_list) {
703 id = get_iface_id(drv, iface);
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100704 if (id)
Alan Stern063a2da2007-10-10 16:24:06 -0400705 return drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 }
707
708 return NULL;
709}
710
Alan Cox335f8512009-06-11 12:26:29 +0100711static int serial_carrier_raised(struct tty_port *port)
712{
713 struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
714 struct usb_serial_driver *drv = p->serial->type;
715 if (drv->carrier_raised)
716 return drv->carrier_raised(p);
717 /* No carrier control - don't block */
718 return 1;
719}
720
721static void serial_dtr_rts(struct tty_port *port, int on)
722{
723 struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
724 struct usb_serial_driver *drv = p->serial->type;
725 if (drv->dtr_rts)
726 drv->dtr_rts(p, on);
727}
728
729static const struct tty_port_operations serial_port_ops = {
730 .carrier_raised = serial_carrier_raised,
731 .dtr_rts = serial_dtr_rts,
732};
733
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734int usb_serial_probe(struct usb_interface *interface,
735 const struct usb_device_id *id)
736{
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100737 struct usb_device *dev = interface_to_usbdev(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738 struct usb_serial *serial = NULL;
739 struct usb_serial_port *port;
740 struct usb_host_interface *iface_desc;
741 struct usb_endpoint_descriptor *endpoint;
742 struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS];
743 struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS];
744 struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];
745 struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700746 struct usb_serial_driver *type = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747 int retval;
Andre Hauptdd9ca5d2008-06-18 15:56:00 +0200748 unsigned int minor;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 int buffer_size;
750 int i;
751 int num_interrupt_in = 0;
752 int num_interrupt_out = 0;
753 int num_bulk_in = 0;
754 int num_bulk_out = 0;
755 int num_ports = 0;
756 int max_endpoints;
757
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100758 lock_kernel(); /* guard against unloading a serial driver module */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 type = search_serial_device(interface);
760 if (!type) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100761 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 dbg("none matched");
763 return -ENODEV;
764 }
765
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100766 serial = create_serial(dev, interface, type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767 if (!serial) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100768 unlock_kernel();
Harvey Harrison441b62c2008-03-03 16:08:34 -0800769 dev_err(&interface->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 return -ENOMEM;
771 }
772
773 /* if this device type has a probe function, call it */
774 if (type->probe) {
775 const struct usb_device_id *id;
776
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700777 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100778 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100779 dev_err(&interface->dev,
780 "module get failed, exiting\n");
781 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782 return -EIO;
783 }
784
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100785 id = get_iface_id(type, interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786 retval = type->probe(serial, id);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700787 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788
789 if (retval) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100790 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100791 dbg("sub driver rejected device");
792 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793 return retval;
794 }
795 }
796
797 /* descriptor matches, let's find the endpoints needed */
798 /* check out the endpoints */
799 iface_desc = interface->cur_altsetting;
800 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
801 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700802
803 if (usb_endpoint_is_bulk_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 /* we found a bulk in endpoint */
805 dbg("found bulk in on endpoint %d", i);
806 bulk_in_endpoint[num_bulk_in] = endpoint;
807 ++num_bulk_in;
808 }
809
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700810 if (usb_endpoint_is_bulk_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 /* we found a bulk out endpoint */
812 dbg("found bulk out on endpoint %d", i);
813 bulk_out_endpoint[num_bulk_out] = endpoint;
814 ++num_bulk_out;
815 }
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700816
817 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818 /* we found a interrupt in endpoint */
819 dbg("found interrupt in on endpoint %d", i);
820 interrupt_in_endpoint[num_interrupt_in] = endpoint;
821 ++num_interrupt_in;
822 }
823
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700824 if (usb_endpoint_is_int_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 /* we found an interrupt out endpoint */
826 dbg("found interrupt out on endpoint %d", i);
827 interrupt_out_endpoint[num_interrupt_out] = endpoint;
828 ++num_interrupt_out;
829 }
830 }
831
832#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100833 /* BEGIN HORRIBLE HACK FOR PL2303 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 /* this is needed due to the looney way its endpoints are set up */
835 if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&
836 (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||
837 ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) &&
Johannes Steingraeber8fd80132006-09-16 16:17:34 +0200838 (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) ||
839 ((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) &&
Andreas Bombece816cf2008-09-14 01:58:55 +0200840 (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID)) ||
841 ((le16_to_cpu(dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) &&
842 (le16_to_cpu(dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_EF81))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 if (interface != dev->actconfig->interface[0]) {
844 /* check out the endpoints of the other interface*/
845 iface_desc = dev->actconfig->interface[0]->cur_altsetting;
846 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
847 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700848 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 /* we found a interrupt in endpoint */
850 dbg("found interrupt in for Prolific device on separate interface");
851 interrupt_in_endpoint[num_interrupt_in] = endpoint;
852 ++num_interrupt_in;
853 }
854 }
855 }
856
857 /* Now make sure the PL-2303 is configured correctly.
858 * If not, give up now and hope this hack will work
859 * properly during a later invocation of usb_serial_probe
860 */
861 if (num_bulk_in == 0 || num_bulk_out == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100862 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100864 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865 return -ENODEV;
866 }
867 }
868 /* END HORRIBLE HACK FOR PL2303 */
869#endif
870
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871#ifdef CONFIG_USB_SERIAL_GENERIC
872 if (type == &usb_serial_generic_device) {
873 num_ports = num_bulk_out;
874 if (num_ports == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100875 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100876 dev_err(&interface->dev,
877 "Generic device with no bulk out, not allowed.\n");
878 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879 return -EIO;
880 }
881 }
882#endif
883 if (!num_ports) {
884 /* if this device type has a calc_num_ports function, call it */
885 if (type->calc_num_ports) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700886 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100887 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100888 dev_err(&interface->dev,
889 "module get failed, exiting\n");
890 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 return -EIO;
892 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100893 num_ports = type->calc_num_ports(serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700894 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 }
896 if (!num_ports)
897 num_ports = type->num_ports;
898 }
899
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 serial->num_ports = num_ports;
901 serial->num_bulk_in = num_bulk_in;
902 serial->num_bulk_out = num_bulk_out;
903 serial->num_interrupt_in = num_interrupt_in;
904 serial->num_interrupt_out = num_interrupt_out;
905
Alan Stern063a2da2007-10-10 16:24:06 -0400906 /* found all that we need */
907 dev_info(&interface->dev, "%s converter detected\n",
908 type->description);
909
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 /* create our ports, we need as many as the max endpoints */
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100911 /* we don't use num_ports here because some devices have more
912 endpoint pairs than ports */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 max_endpoints = max(num_bulk_in, num_bulk_out);
914 max_endpoints = max(max_endpoints, num_interrupt_in);
915 max_endpoints = max(max_endpoints, num_interrupt_out);
916 max_endpoints = max(max_endpoints, (int)serial->num_ports);
917 serial->num_port_pointers = max_endpoints;
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100918 unlock_kernel();
919
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100920 dbg("%s - setting up %d port structures for this device",
921 __func__, max_endpoints);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 for (i = 0; i < max_endpoints; ++i) {
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100923 port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 if (!port)
925 goto probe_error;
Alan Cox4a90f092008-10-13 10:39:46 +0100926 tty_port_init(&port->port);
Alan Cox335f8512009-06-11 12:26:29 +0100927 port->port.ops = &serial_port_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 port->serial = serial;
Greg Kroah-Hartman507ca9b2005-04-23 12:49:16 -0700929 spin_lock_init(&port->lock);
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300930 mutex_init(&port->mutex);
David Howellsc4028952006-11-22 14:57:56 +0000931 INIT_WORK(&port->work, usb_serial_port_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 serial->port[i] = port;
Alan Stern41bd34d2009-09-01 11:38:34 -0400933 port->dev.parent = &interface->dev;
934 port->dev.driver = NULL;
935 port->dev.bus = &usb_serial_bus_type;
936 port->dev.release = &port_release;
937 device_initialize(&port->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 }
939
940 /* set up the endpoint information */
941 for (i = 0; i < num_bulk_in; ++i) {
942 endpoint = bulk_in_endpoint[i];
943 port = serial->port[i];
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100944 port->read_urb = usb_alloc_urb(0, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 if (!port->read_urb) {
946 dev_err(&interface->dev, "No free urbs available\n");
947 goto probe_error;
948 }
949 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
950 port->bulk_in_size = buffer_size;
951 port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100952 port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 if (!port->bulk_in_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100954 dev_err(&interface->dev,
955 "Couldn't allocate bulk_in_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 goto probe_error;
957 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100958 usb_fill_bulk_urb(port->read_urb, dev,
959 usb_rcvbulkpipe(dev,
960 endpoint->bEndpointAddress),
961 port->bulk_in_buffer, buffer_size,
962 serial->type->read_bulk_callback, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 }
964
965 for (i = 0; i < num_bulk_out; ++i) {
966 endpoint = bulk_out_endpoint[i];
967 port = serial->port[i];
968 port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
969 if (!port->write_urb) {
970 dev_err(&interface->dev, "No free urbs available\n");
971 goto probe_error;
972 }
973 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
974 port->bulk_out_size = buffer_size;
975 port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100976 port->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 if (!port->bulk_out_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100978 dev_err(&interface->dev,
979 "Couldn't allocate bulk_out_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 goto probe_error;
981 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100982 usb_fill_bulk_urb(port->write_urb, dev,
983 usb_sndbulkpipe(dev,
984 endpoint->bEndpointAddress),
985 port->bulk_out_buffer, buffer_size,
986 serial->type->write_bulk_callback, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 }
988
989 if (serial->type->read_int_callback) {
990 for (i = 0; i < num_interrupt_in; ++i) {
991 endpoint = interrupt_in_endpoint[i];
992 port = serial->port[i];
993 port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
994 if (!port->interrupt_in_urb) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100995 dev_err(&interface->dev,
996 "No free urbs available\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 goto probe_error;
998 }
999 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001000 port->interrupt_in_endpointAddress =
1001 endpoint->bEndpointAddress;
1002 port->interrupt_in_buffer = kmalloc(buffer_size,
1003 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 if (!port->interrupt_in_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001005 dev_err(&interface->dev,
1006 "Couldn't allocate interrupt_in_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 goto probe_error;
1008 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001009 usb_fill_int_urb(port->interrupt_in_urb, dev,
1010 usb_rcvintpipe(dev,
1011 endpoint->bEndpointAddress),
1012 port->interrupt_in_buffer, buffer_size,
1013 serial->type->read_int_callback, port,
1014 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 }
1016 } else if (num_interrupt_in) {
1017 dbg("the device claims to support interrupt in transfers, but read_int_callback is not defined");
1018 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001019
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 if (serial->type->write_int_callback) {
1021 for (i = 0; i < num_interrupt_out; ++i) {
1022 endpoint = interrupt_out_endpoint[i];
1023 port = serial->port[i];
1024 port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
1025 if (!port->interrupt_out_urb) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001026 dev_err(&interface->dev,
1027 "No free urbs available\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 goto probe_error;
1029 }
1030 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
1031 port->interrupt_out_size = buffer_size;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001032 port->interrupt_out_endpointAddress =
1033 endpoint->bEndpointAddress;
1034 port->interrupt_out_buffer = kmalloc(buffer_size,
1035 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 if (!port->interrupt_out_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001037 dev_err(&interface->dev,
1038 "Couldn't allocate interrupt_out_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 goto probe_error;
1040 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001041 usb_fill_int_urb(port->interrupt_out_urb, dev,
1042 usb_sndintpipe(dev,
1043 endpoint->bEndpointAddress),
1044 port->interrupt_out_buffer, buffer_size,
1045 serial->type->write_int_callback, port,
1046 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 }
1048 } else if (num_interrupt_out) {
1049 dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined");
1050 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001051
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 /* if this device type has an attach function, call it */
1053 if (type->attach) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -07001054 if (!try_module_get(type->driver.owner)) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001055 dev_err(&interface->dev,
1056 "module get failed, exiting\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 goto probe_error;
1058 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001059 retval = type->attach(serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -07001060 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 if (retval < 0)
1062 goto probe_error;
1063 if (retval > 0) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001064 /* quietly accept this device, but don't bind to a
1065 serial port as it's about to disappear */
Alan Stern0a3c8542009-05-27 11:25:52 -04001066 serial->num_ports = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 goto exit;
1068 }
1069 }
1070
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001071 if (get_free_serial(serial, num_ports, &minor) == NULL) {
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001072 dev_err(&interface->dev, "No more free serial devices\n");
1073 goto probe_error;
1074 }
Oliver Neukumc744f992007-02-26 15:43:00 +01001075 serial->minor = minor;
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001076
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077 /* register all of the individual ports with the driver core */
1078 for (i = 0; i < num_ports; ++i) {
1079 port = serial->port[i];
Kay Sievers0031a062008-05-02 06:02:41 +02001080 dev_set_name(&port->dev, "ttyUSB%d", port->number);
Kay Sievers7071a3c2008-05-02 06:02:41 +02001081 dbg ("%s - registering %s", __func__, dev_name(&port->dev));
Alan Sternc706ebd2009-06-02 11:54:11 -04001082 port->dev_state = PORT_REGISTERING;
Alan Stern41bd34d2009-09-01 11:38:34 -04001083 retval = device_add(&port->dev);
Alan Sternc706ebd2009-06-02 11:54:11 -04001084 if (retval) {
Greg Kroah-Hartman13f4db92006-08-28 11:43:25 -07001085 dev_err(&port->dev, "Error registering port device, "
1086 "continuing\n");
Alan Sternc706ebd2009-06-02 11:54:11 -04001087 port->dev_state = PORT_UNREGISTERED;
1088 } else {
1089 port->dev_state = PORT_REGISTERED;
1090 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 }
1092
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001093 usb_serial_console_init(debug, minor);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094
1095exit:
1096 /* success */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001097 usb_set_intfdata(interface, serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098 return 0;
1099
1100probe_error:
Alan Stern41bd34d2009-09-01 11:38:34 -04001101 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102 return -EIO;
1103}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001104EXPORT_SYMBOL_GPL(usb_serial_probe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105
1106void usb_serial_disconnect(struct usb_interface *interface)
1107{
1108 int i;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001109 struct usb_serial *serial = usb_get_intfdata(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 struct device *dev = &interface->dev;
1111 struct usb_serial_port *port;
1112
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +02001113 usb_serial_console_disconnect(serial);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001114 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001116 mutex_lock(&serial->disc_mutex);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001117 usb_set_intfdata(interface, NULL);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001118 /* must set a flag, to signal subdrivers */
1119 serial->disconnected = 1;
Alan Stern2d931482009-04-14 11:31:02 -04001120 mutex_unlock(&serial->disc_mutex);
1121
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001122 for (i = 0; i < serial->num_ports; ++i) {
1123 port = serial->port[i];
1124 if (port) {
Alan Cox4a90f092008-10-13 10:39:46 +01001125 struct tty_struct *tty = tty_port_tty_get(&port->port);
1126 if (tty) {
Alan Coxd2b39182009-09-19 13:13:23 -07001127 tty_vhangup(tty);
Alan Cox4a90f092008-10-13 10:39:46 +01001128 tty_kref_put(tty);
1129 }
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001130 kill_traffic(port);
Alan Stern2d931482009-04-14 11:31:02 -04001131 cancel_work_sync(&port->work);
Alan Sternc706ebd2009-06-02 11:54:11 -04001132 if (port->dev_state == PORT_REGISTERED) {
1133
1134 /* Make sure the port is bound so that the
1135 * driver's port_remove method is called.
1136 */
1137 if (!port->dev.driver) {
1138 int rc;
1139
1140 port->dev.driver =
1141 &serial->type->driver;
1142 rc = device_bind_driver(&port->dev);
1143 }
1144 port->dev_state = PORT_UNREGISTERING;
1145 device_del(&port->dev);
1146 port->dev_state = PORT_UNREGISTERED;
1147 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 }
Alan Sternf9c99bb2009-06-02 11:53:55 -04001150 serial->type->disconnect(serial);
Alan Stern2d931482009-04-14 11:31:02 -04001151
Alan Stern41bd34d2009-09-01 11:38:34 -04001152 /* let the last holder of this object cause it to be cleaned up */
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001153 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154 dev_info(dev, "device disconnected\n");
1155}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001156EXPORT_SYMBOL_GPL(usb_serial_disconnect);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157
Oliver Neukumec225592007-04-27 20:54:57 +02001158int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
1159{
1160 struct usb_serial *serial = usb_get_intfdata(intf);
1161 struct usb_serial_port *port;
1162 int i, r = 0;
1163
Oliver Neukumf8bece82009-02-05 16:54:25 +01001164 serial->suspending = 1;
1165
Oliver Neukume31c1882007-07-23 08:58:39 +02001166 for (i = 0; i < serial->num_ports; ++i) {
1167 port = serial->port[i];
1168 if (port)
1169 kill_traffic(port);
Oliver Neukumec225592007-04-27 20:54:57 +02001170 }
1171
1172 if (serial->type->suspend)
Oliver Neukume31c1882007-07-23 08:58:39 +02001173 r = serial->type->suspend(serial, message);
Oliver Neukumec225592007-04-27 20:54:57 +02001174
1175 return r;
1176}
1177EXPORT_SYMBOL(usb_serial_suspend);
1178
1179int usb_serial_resume(struct usb_interface *intf)
1180{
1181 struct usb_serial *serial = usb_get_intfdata(intf);
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001182 int rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001183
Oliver Neukumf8bece82009-02-05 16:54:25 +01001184 serial->suspending = 0;
Sarah Sharp8abaee22007-10-25 10:58:43 -07001185 if (serial->type->resume)
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001186 rv = serial->type->resume(serial);
1187 else
1188 rv = usb_serial_generic_resume(serial);
Oliver Neukumf8bece82009-02-05 16:54:25 +01001189
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001190 return rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001191}
1192EXPORT_SYMBOL(usb_serial_resume);
1193
Jeff Dikeb68e31d2006-10-02 02:17:18 -07001194static const struct tty_operations serial_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195 .open = serial_open,
1196 .close = serial_close,
1197 .write = serial_write,
Alan Cox335f8512009-06-11 12:26:29 +01001198 .hangup = serial_hangup,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199 .write_room = serial_write_room,
1200 .ioctl = serial_ioctl,
1201 .set_termios = serial_set_termios,
1202 .throttle = serial_throttle,
1203 .unthrottle = serial_unthrottle,
1204 .break_ctl = serial_break,
1205 .chars_in_buffer = serial_chars_in_buffer,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 .tiocmget = serial_tiocmget,
1207 .tiocmset = serial_tiocmset,
Alan Stern74556122009-09-01 11:39:40 -04001208 .shutdown = serial_release,
Alan Coxfe1ae7f2009-09-19 13:13:33 -07001209 .install = serial_install,
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -07001210 .proc_fops = &serial_proc_fops,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211};
1212
Alan Cox335f8512009-06-11 12:26:29 +01001213
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214struct tty_driver *usb_serial_tty_driver;
1215
1216static int __init usb_serial_init(void)
1217{
1218 int i;
1219 int result;
1220
1221 usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS);
1222 if (!usb_serial_tty_driver)
1223 return -ENOMEM;
1224
1225 /* Initialize our global data */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001226 for (i = 0; i < SERIAL_TTY_MINORS; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 serial_table[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228
1229 result = bus_register(&usb_serial_bus_type);
1230 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001231 printk(KERN_ERR "usb-serial: %s - registering bus driver "
1232 "failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233 goto exit_bus;
1234 }
1235
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236 usb_serial_tty_driver->owner = THIS_MODULE;
1237 usb_serial_tty_driver->driver_name = "usbserial";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 usb_serial_tty_driver->name = "ttyUSB";
1239 usb_serial_tty_driver->major = SERIAL_TTY_MAJOR;
1240 usb_serial_tty_driver->minor_start = 0;
1241 usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
1242 usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001243 usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW |
1244 TTY_DRIVER_DYNAMIC_DEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245 usb_serial_tty_driver->init_termios = tty_std_termios;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001246 usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD
1247 | HUPCL | CLOCAL;
Alan Coxa5b6f602008-04-08 17:16:06 +01001248 usb_serial_tty_driver->init_termios.c_ispeed = 9600;
1249 usb_serial_tty_driver->init_termios.c_ospeed = 9600;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250 tty_set_operations(usb_serial_tty_driver, &serial_ops);
1251 result = tty_register_driver(usb_serial_tty_driver);
1252 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001253 printk(KERN_ERR "usb-serial: %s - tty_register_driver failed\n",
1254 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255 goto exit_reg_driver;
1256 }
1257
1258 /* register the USB driver */
1259 result = usb_register(&usb_serial_driver);
1260 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001261 printk(KERN_ERR "usb-serial: %s - usb_register failed\n",
1262 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263 goto exit_tty;
1264 }
1265
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001266 /* register the generic driver, if we should */
1267 result = usb_serial_generic_register(debug);
1268 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001269 printk(KERN_ERR "usb-serial: %s - registering generic "
1270 "driver failed\n", __func__);
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001271 goto exit_generic;
1272 }
1273
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001274 printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275
1276 return result;
1277
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001278exit_generic:
1279 usb_deregister(&usb_serial_driver);
1280
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281exit_tty:
1282 tty_unregister_driver(usb_serial_tty_driver);
1283
1284exit_reg_driver:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285 bus_unregister(&usb_serial_bus_type);
1286
1287exit_bus:
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001288 printk(KERN_ERR "usb-serial: %s - returning with error %d\n",
1289 __func__, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290 put_tty_driver(usb_serial_tty_driver);
1291 return result;
1292}
1293
1294
1295static void __exit usb_serial_exit(void)
1296{
1297 usb_serial_console_exit();
1298
1299 usb_serial_generic_deregister();
1300
1301 usb_deregister(&usb_serial_driver);
1302 tty_unregister_driver(usb_serial_tty_driver);
1303 put_tty_driver(usb_serial_tty_driver);
1304 bus_unregister(&usb_serial_bus_type);
1305}
1306
1307
1308module_init(usb_serial_init);
1309module_exit(usb_serial_exit);
1310
1311#define set_to_generic_if_null(type, function) \
1312 do { \
1313 if (!type->function) { \
1314 type->function = usb_serial_generic_##function; \
1315 dbg("Had to override the " #function \
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001316 " usb serial operation with the generic one.");\
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 } \
1318 } while (0)
1319
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001320static void fixup_generic(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321{
1322 set_to_generic_if_null(device, open);
1323 set_to_generic_if_null(device, write);
1324 set_to_generic_if_null(device, close);
1325 set_to_generic_if_null(device, write_room);
1326 set_to_generic_if_null(device, chars_in_buffer);
1327 set_to_generic_if_null(device, read_bulk_callback);
1328 set_to_generic_if_null(device, write_bulk_callback);
Alan Sternf9c99bb2009-06-02 11:53:55 -04001329 set_to_generic_if_null(device, disconnect);
1330 set_to_generic_if_null(device, release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331}
1332
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001333int usb_serial_register(struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001335 /* must be called with BKL held */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 int retval;
1337
Dave Younge4abe662009-02-14 21:21:13 +08001338 if (usb_disabled())
1339 return -ENODEV;
1340
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001341 fixup_generic(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001343 if (!driver->description)
1344 driver->description = driver->driver.name;
1345
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346 /* Add this device to our list of devices */
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001347 list_add(&driver->driver_list, &usb_serial_driver_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001349 retval = usb_serial_bus_register(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350 if (retval) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001351 printk(KERN_ERR "usb-serial: problem %d when registering "
1352 "driver %s\n", retval, driver->description);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001353 list_del(&driver->driver_list);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001354 } else
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001355 printk(KERN_INFO "USB Serial support registered for %s\n",
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001356 driver->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357
1358 return retval;
1359}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001360EXPORT_SYMBOL_GPL(usb_serial_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361
1362
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001363void usb_serial_deregister(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001365 /* must be called with BKL held */
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001366 printk(KERN_INFO "USB Serial deregistering driver %s\n",
1367 device->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368 list_del(&device->driver_list);
1369 usb_serial_bus_deregister(device);
1370}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371EXPORT_SYMBOL_GPL(usb_serial_deregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372
1373/* Module information */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001374MODULE_AUTHOR(DRIVER_AUTHOR);
1375MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376MODULE_LICENSE("GPL");
1377
1378module_param(debug, bool, S_IRUGO | S_IWUSR);
1379MODULE_PARM_DESC(debug, "Debug enabled or not");