blob: 1bc0a24b896b22a62d112ccf6e0368eb9bf011ce [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.
194 * All these actions are reversed in serial_do_free().
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
203 serial = usb_serial_get_by_index(idx);
204 if (!serial)
205 return retval;
206
207 port = serial->port[idx - serial->minor];
208 if (!port)
209 goto error_no_port;
210 if (!try_module_get(serial->type->driver.owner))
211 goto error_module_get;
212
Alan Stern7e29bb42009-09-01 11:39:22 -0400213 /* perform the standard setup */
214 retval = tty_init_termios(tty);
215 if (retval)
216 goto error_init_termios;
217
Alan Sterncc56cd02009-09-01 11:39:13 -0400218 retval = usb_autopm_get_interface(serial->interface);
219 if (retval)
220 goto error_get_interface;
Alan Sternf5b09532009-09-01 11:38:44 -0400221
Alan Sterncc56cd02009-09-01 11:39:13 -0400222 mutex_unlock(&serial->disc_mutex);
223
Alan Stern7e29bb42009-09-01 11:39:22 -0400224 /* allow the driver to update the settings */
225 if (serial->type->init_termios)
226 serial->type->init_termios(tty);
227
Alan Sterncc56cd02009-09-01 11:39:13 -0400228 tty->driver_data = port;
229
Alan Sternf5b09532009-09-01 11:38:44 -0400230 /* Final install (we use the default method) */
231 tty_driver_kref_get(driver);
232 tty->count++;
233 driver->ttys[idx] = tty;
Alan Sterncc56cd02009-09-01 11:39:13 -0400234 return retval;
235
Alan Sterncc56cd02009-09-01 11:39:13 -0400236 error_get_interface:
Alan Stern7e29bb42009-09-01 11:39:22 -0400237 error_init_termios:
Alan Sterncc56cd02009-09-01 11:39:13 -0400238 module_put(serial->type->driver.owner);
239 error_module_get:
240 error_no_port:
241 usb_serial_put(serial);
242 mutex_unlock(&serial->disc_mutex);
243 return retval;
Alan Sternf5b09532009-09-01 11:38:44 -0400244}
245
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100246static int serial_open (struct tty_struct *tty, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247{
248 struct usb_serial *serial;
249 struct usb_serial_port *port;
Alan Stern2d931482009-04-14 11:31:02 -0400250 int retval = 0;
Alan Coxc56d3002009-07-28 00:34:58 +0100251 int first = 0;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100252
Harvey Harrison441b62c2008-03-03 16:08:34 -0800253 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254
Alan Sterncc56cd02009-09-01 11:39:13 -0400255 port = tty->driver_data;
256 serial = port->serial;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257
Alan Sterncc56cd02009-09-01 11:39:13 -0400258 if (mutex_lock_interruptible(&port->mutex))
259 return -ERESTARTSYS;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100260
Alan Cox95da3102008-07-22 11:09:07 +0100261 ++port->port.count;
Alan Cox4a90f092008-10-13 10:39:46 +0100262 tty_port_tty_set(&port->port, tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263
Jason Wessel6e406122009-06-22 11:32:20 -0500264 /* If the console is attached, the device is already open */
265 if (port->port.count == 1 && !port->console) {
Alan Coxc56d3002009-07-28 00:34:58 +0100266 first = 1;
Alan Stern2d931482009-04-14 11:31:02 -0400267 mutex_lock(&serial->disc_mutex);
Alan Stern2d931482009-04-14 11:31:02 -0400268
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100269 /* only call the device specific open if this
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 * is the first time the port is opened */
Alan Coxa509a7e2009-09-19 13:13:26 -0700271 retval = serial->type->open(tty, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 if (retval)
Alan Sterncc56cd02009-09-01 11:39:13 -0400273 goto bailout_module_put;
Alan Stern2d931482009-04-14 11:31:02 -0400274 mutex_unlock(&serial->disc_mutex);
Alan Coxc56d3002009-07-28 00:34:58 +0100275 set_bit(ASYNCB_INITIALIZED, &port->port.flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276 }
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300277 mutex_unlock(&port->mutex);
Alan Cox335f8512009-06-11 12:26:29 +0100278 /* Now do the correct tty layer semantics */
279 retval = tty_port_block_til_ready(&port->port, tty, filp);
Alan Coxc56d3002009-07-28 00:34:58 +0100280 if (retval == 0) {
281 if (!first)
282 usb_serial_put(serial);
Alan Cox335f8512009-06-11 12:26:29 +0100283 return 0;
Alan Coxc56d3002009-07-28 00:34:58 +0100284 }
285 mutex_lock(&port->mutex);
286 if (first == 0)
287 goto bailout_mutex_unlock;
288 /* Undo the initial port actions */
289 mutex_lock(&serial->disc_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290bailout_module_put:
Alan Stern2d931482009-04-14 11:31:02 -0400291 mutex_unlock(&serial->disc_mutex);
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300292bailout_mutex_unlock:
Alan Cox95da3102008-07-22 11:09:07 +0100293 port->port.count = 0;
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300294 mutex_unlock(&port->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 return retval;
296}
297
Alan Cox335f8512009-06-11 12:26:29 +0100298/**
Alan Sternf5b09532009-09-01 11:38:44 -0400299 * serial_do_down - shut down hardware
300 * @port: port to shut down
Alan Cox335f8512009-06-11 12:26:29 +0100301 *
Alan Sternf5b09532009-09-01 11:38:44 -0400302 * Shut down a USB serial port unless it is the console. We never
303 * shut down the console hardware as it will always be in use.
Alan Cox335f8512009-06-11 12:26:29 +0100304 */
305static void serial_do_down(struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306{
Alan Cox335f8512009-06-11 12:26:29 +0100307 struct usb_serial_driver *drv = port->serial->type;
Alan Stern2d931482009-04-14 11:31:02 -0400308 struct usb_serial *serial;
309 struct module *owner;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310
Alan Sternf5b09532009-09-01 11:38:44 -0400311 /*
312 * The console is magical. Do not hang up the console hardware
313 * or there will be tears.
314 */
Alan Cox335f8512009-06-11 12:26:29 +0100315 if (port->console)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316 return;
317
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300318 mutex_lock(&port->mutex);
Alan Stern2d931482009-04-14 11:31:02 -0400319 serial = port->serial;
320 owner = serial->type->driver.owner;
Luiz Fernando Capitulino8a4613f2005-11-28 19:16:07 -0200321
Alan Cox335f8512009-06-11 12:26:29 +0100322 if (drv->close)
323 drv->close(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300325 mutex_unlock(&port->mutex);
Alan Cox335f8512009-06-11 12:26:29 +0100326}
327
Alan Sternf5b09532009-09-01 11:38:44 -0400328static void serial_hangup(struct tty_struct *tty)
Alan Cox335f8512009-06-11 12:26:29 +0100329{
Alan Cox4455e342009-09-19 13:13:24 -0700330 struct usb_serial_port *port = tty->driver_data;
Alan Sternf5b09532009-09-01 11:38:44 -0400331 serial_do_down(port);
332 tty_port_hangup(&port->port);
333 /* We must not free port yet - the USB serial layer depends on it's
334 continued existence */
Alan Cox335f8512009-06-11 12:26:29 +0100335}
336
337static void serial_close(struct tty_struct *tty, struct file *filp)
338{
339 struct usb_serial_port *port = tty->driver_data;
340
341 dbg("%s - port %d", __func__, port->number);
342
Alan Cox335f8512009-06-11 12:26:29 +0100343 if (tty_port_close_start(&port->port, tty, filp) == 0)
344 return;
Alan Sternf5b09532009-09-01 11:38:44 -0400345 serial_do_down(port);
Alan Cox335f8512009-06-11 12:26:29 +0100346 tty_port_close_end(&port->port, tty);
347 tty_port_tty_set(&port->port, NULL);
Alan Cox335f8512009-06-11 12:26:29 +0100348}
349
Alan Sternf5b09532009-09-01 11:38:44 -0400350/**
351 * serial_do_free - free resources post close/hangup
352 * @port: port to free up
353 *
354 * Do the resource freeing and refcount dropping for the port.
355 * Avoid freeing the console.
356 *
357 * Called when the last tty kref is dropped.
358 */
359static void serial_do_free(struct tty_struct *tty)
Alan Cox335f8512009-06-11 12:26:29 +0100360{
361 struct usb_serial_port *port = tty->driver_data;
Alan Sternf5b09532009-09-01 11:38:44 -0400362 struct usb_serial *serial;
363 struct module *owner;
364
365 /* The console is magical. Do not hang up the console hardware
366 * or there will be tears.
367 */
Alan Sterncc56cd02009-09-01 11:39:13 -0400368 if (port->console)
Alan Sternf5b09532009-09-01 11:38:44 -0400369 return;
370
Alan Sterncc56cd02009-09-01 11:39:13 -0400371 tty->driver_data = NULL;
372
Alan Sternf5b09532009-09-01 11:38:44 -0400373 serial = port->serial;
374 owner = serial->type->driver.owner;
375
376 mutex_lock(&serial->disc_mutex);
377 if (!serial->disconnected)
378 usb_autopm_put_interface(serial->interface);
379 mutex_unlock(&serial->disc_mutex);
380
381 usb_serial_put(serial);
382 module_put(owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383}
384
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100385static int serial_write(struct tty_struct *tty, const unsigned char *buf,
386 int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200388 struct usb_serial_port *port = tty->driver_data;
Oliver Neukum3ff4fd92007-01-13 07:32:27 +0100389 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390
Alan Coxf34d7a52008-04-30 00:54:13 -0700391 if (port->serial->dev->state == USB_STATE_NOTATTACHED)
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200392 goto exit;
393
Harvey Harrison441b62c2008-03-03 16:08:34 -0800394 dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395
Alan Cox95da3102008-07-22 11:09:07 +0100396 /* count is managed under the mutex lock for the tty so cannot
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100397 drop to zero until after the last close completes */
Alan Cox95da3102008-07-22 11:09:07 +0100398 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399
400 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100401 retval = port->serial->type->write(tty, port, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402
403exit:
404 return retval;
405}
406
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100407static int serial_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200409 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800410 dbg("%s - port %d", __func__, port->number);
Alan Cox95da3102008-07-22 11:09:07 +0100411 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100413 return port->serial->type->write_room(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414}
415
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100416static int serial_chars_in_buffer(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200418 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800419 dbg("%s = port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420
Alan Coxeff69372009-01-02 13:47:06 +0000421 /* if the device was unplugged then any remaining characters
422 fell out of the connector ;) */
423 if (port->serial->disconnected)
424 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100426 return port->serial->type->chars_in_buffer(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427}
428
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100429static void serial_throttle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200431 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800432 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433
Alan Cox95da3102008-07-22 11:09:07 +0100434 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 /* pass on to the driver specific version of this function */
436 if (port->serial->type->throttle)
Alan Cox95da3102008-07-22 11:09:07 +0100437 port->serial->type->throttle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438}
439
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100440static void serial_unthrottle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200442 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800443 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444
Alan Cox95da3102008-07-22 11:09:07 +0100445 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446 /* pass on to the driver specific version of this function */
447 if (port->serial->type->unthrottle)
Alan Cox95da3102008-07-22 11:09:07 +0100448 port->serial->type->unthrottle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449}
450
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100451static int serial_ioctl(struct tty_struct *tty, struct file *file,
452 unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200454 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 int retval = -ENODEV;
456
Harvey Harrison441b62c2008-03-03 16:08:34 -0800457 dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458
Alan Cox95da3102008-07-22 11:09:07 +0100459 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100461 /* pass on to the driver specific version of this function
462 if it is available */
Alan Coxf34d7a52008-04-30 00:54:13 -0700463 if (port->serial->type->ioctl) {
Alan Cox95da3102008-07-22 11:09:07 +0100464 retval = port->serial->type->ioctl(tty, file, cmd, arg);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100465 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 retval = -ENOIOCTLCMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467 return retval;
468}
469
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100470static void serial_set_termios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200472 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800473 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474
Alan Cox95da3102008-07-22 11:09:07 +0100475 WARN_ON(!port->port.count);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100476 /* pass on to the driver specific version of this function
477 if it is available */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 if (port->serial->type->set_termios)
Alan Cox95da3102008-07-22 11:09:07 +0100479 port->serial->type->set_termios(tty, port, old);
Alan Cox33785092007-10-18 01:24:22 -0700480 else
481 tty_termios_copy_hw(tty->termios, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482}
483
Alan Cox9e989662008-07-22 11:18:03 +0100484static int serial_break(struct tty_struct *tty, int break_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200486 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487
Harvey Harrison441b62c2008-03-03 16:08:34 -0800488 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489
Alan Cox95da3102008-07-22 11:09:07 +0100490 WARN_ON(!port->port.count);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100491 /* pass on to the driver specific version of this function
492 if it is available */
Alan Cox6b447f042009-01-02 13:48:56 +0000493 if (port->serial->type->break_ctl)
Alan Cox95da3102008-07-22 11:09:07 +0100494 port->serial->type->break_ctl(tty, break_state);
Alan Cox9e989662008-07-22 11:18:03 +0100495 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496}
497
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700498static int serial_proc_show(struct seq_file *m, void *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499{
500 struct usb_serial *serial;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 char tmp[40];
503
Harvey Harrison441b62c2008-03-03 16:08:34 -0800504 dbg("%s", __func__);
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700505 seq_puts(m, "usbserinfo:1.0 driver:2.0\n");
506 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 serial = usb_serial_get_by_index(i);
508 if (serial == NULL)
509 continue;
510
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700511 seq_printf(m, "%d:", i);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700512 if (serial->type->driver.owner)
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700513 seq_printf(m, " module:%s",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100514 module_name(serial->type->driver.owner));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700515 seq_printf(m, " name:\"%s\"",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100516 serial->type->description);
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700517 seq_printf(m, " vendor:%04x product:%04x",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100518 le16_to_cpu(serial->dev->descriptor.idVendor),
519 le16_to_cpu(serial->dev->descriptor.idProduct));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700520 seq_printf(m, " num_ports:%d", serial->num_ports);
521 seq_printf(m, " port:%d", i - serial->minor + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 usb_make_path(serial->dev, tmp, sizeof(tmp));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700523 seq_printf(m, " path:%s", tmp);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100524
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700525 seq_putc(m, '\n');
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200526 usb_serial_put(serial);
Alan Stern8bc2c1b2009-09-01 11:38:59 -0400527 mutex_unlock(&serial->disc_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 }
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700529 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530}
531
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700532static int serial_proc_open(struct inode *inode, struct file *file)
533{
534 return single_open(file, serial_proc_show, NULL);
535}
536
537static const struct file_operations serial_proc_fops = {
538 .owner = THIS_MODULE,
539 .open = serial_proc_open,
540 .read = seq_read,
541 .llseek = seq_lseek,
542 .release = single_release,
543};
544
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100545static int serial_tiocmget(struct tty_struct *tty, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200547 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548
Harvey Harrison441b62c2008-03-03 16:08:34 -0800549 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550
Alan Cox95da3102008-07-22 11:09:07 +0100551 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 if (port->serial->type->tiocmget)
Alan Cox95da3102008-07-22 11:09:07 +0100553 return port->serial->type->tiocmget(tty, file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 return -EINVAL;
555}
556
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100557static int serial_tiocmset(struct tty_struct *tty, struct file *file,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 unsigned int set, unsigned int clear)
559{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200560 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561
Harvey Harrison441b62c2008-03-03 16:08:34 -0800562 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563
Alan Cox95da3102008-07-22 11:09:07 +0100564 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 if (port->serial->type->tiocmset)
Alan Cox95da3102008-07-22 11:09:07 +0100566 return port->serial->type->tiocmset(tty, file, set, clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567 return -EINVAL;
568}
569
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700570/*
571 * We would be calling tty_wakeup here, but unfortunately some line
572 * disciplines have an annoying habit of calling tty->write from
573 * the write wakeup callback (e.g. n_hdlc.c).
574 */
575void usb_serial_port_softint(struct usb_serial_port *port)
576{
577 schedule_work(&port->work);
578}
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100579EXPORT_SYMBOL_GPL(usb_serial_port_softint);
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700580
David Howellsc4028952006-11-22 14:57:56 +0000581static void usb_serial_port_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582{
David Howellsc4028952006-11-22 14:57:56 +0000583 struct usb_serial_port *port =
584 container_of(work, struct usb_serial_port, work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585 struct tty_struct *tty;
586
Harvey Harrison441b62c2008-03-03 16:08:34 -0800587 dbg("%s - port %d", __func__, port->number);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100588
Alan Cox4a90f092008-10-13 10:39:46 +0100589 tty = tty_port_tty_get(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 if (!tty)
591 return;
592
593 tty_wakeup(tty);
Alan Cox4a90f092008-10-13 10:39:46 +0100594 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595}
596
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100597static void kill_traffic(struct usb_serial_port *port)
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700598{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 usb_kill_urb(port->write_urb);
Oliver Neukum5adceac2007-08-17 14:01:38 +0200601 /*
602 * This is tricky.
603 * Some drivers submit the read_urb in the
604 * handler for the write_urb or vice versa
605 * this order determines the order in which
606 * usb_kill_urb() must be used to reliably
607 * kill the URBs. As it is unknown here,
608 * both orders must be used in turn.
609 * The call below is not redundant.
610 */
611 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612 usb_kill_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 usb_kill_urb(port->interrupt_out_urb);
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100614}
615
Alan Stern41bd34d2009-09-01 11:38:34 -0400616static void port_release(struct device *dev)
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100617{
Alan Stern41bd34d2009-09-01 11:38:34 -0400618 struct usb_serial_port *port = to_usb_serial_port(dev);
619
620 dbg ("%s - %s", __func__, dev_name(dev));
621
Alan Stern2d931482009-04-14 11:31:02 -0400622 /*
623 * Stop all the traffic before cancelling the work, so that
624 * nobody will restart it by calling usb_serial_port_softint.
625 */
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100626 kill_traffic(port);
Alan Stern2d931482009-04-14 11:31:02 -0400627 cancel_work_sync(&port->work);
628
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100629 usb_free_urb(port->read_urb);
630 usb_free_urb(port->write_urb);
631 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 usb_free_urb(port->interrupt_out_urb);
633 kfree(port->bulk_in_buffer);
634 kfree(port->bulk_out_buffer);
635 kfree(port->interrupt_in_buffer);
636 kfree(port->interrupt_out_buffer);
637 kfree(port);
638}
639
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100640static struct usb_serial *create_serial(struct usb_device *dev,
641 struct usb_interface *interface,
642 struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643{
644 struct usb_serial *serial;
645
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100646 serial = kzalloc(sizeof(*serial), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 if (!serial) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800648 dev_err(&dev->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649 return NULL;
650 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651 serial->dev = usb_get_dev(dev);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700652 serial->type = driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 serial->interface = interface;
654 kref_init(&serial->kref);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +0100655 mutex_init(&serial->disc_mutex);
Alan Stern0282b7f2008-07-29 12:01:04 -0400656 serial->minor = SERIAL_TTY_NO_MINOR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657
658 return serial;
659}
660
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100661static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf,
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100662 struct usb_serial_driver *drv)
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100663{
664 struct usb_dynid *dynid;
665
666 spin_lock(&drv->dynids.lock);
667 list_for_each_entry(dynid, &drv->dynids.list, node) {
668 if (usb_match_one_id(intf, &dynid->id)) {
669 spin_unlock(&drv->dynids.lock);
670 return &dynid->id;
671 }
672 }
673 spin_unlock(&drv->dynids.lock);
674 return NULL;
675}
676
677static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv,
678 struct usb_interface *intf)
679{
680 const struct usb_device_id *id;
681
682 id = usb_match_id(intf, drv->id_table);
683 if (id) {
684 dbg("static descriptor matches");
685 goto exit;
686 }
687 id = match_dynamic_id(intf, drv);
688 if (id)
689 dbg("dynamic descriptor matches");
690exit:
691 return id;
692}
693
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100694static struct usb_serial_driver *search_serial_device(
695 struct usb_interface *iface)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 const struct usb_device_id *id;
Alan Stern063a2da2007-10-10 16:24:06 -0400698 struct usb_serial_driver *drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699
Adrian Bunk93b1fae2006-01-10 00:13:33 +0100700 /* Check if the usb id matches a known device */
Alan Stern063a2da2007-10-10 16:24:06 -0400701 list_for_each_entry(drv, &usb_serial_driver_list, driver_list) {
702 id = get_iface_id(drv, iface);
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100703 if (id)
Alan Stern063a2da2007-10-10 16:24:06 -0400704 return drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 }
706
707 return NULL;
708}
709
Alan Cox335f8512009-06-11 12:26:29 +0100710static int serial_carrier_raised(struct tty_port *port)
711{
712 struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
713 struct usb_serial_driver *drv = p->serial->type;
714 if (drv->carrier_raised)
715 return drv->carrier_raised(p);
716 /* No carrier control - don't block */
717 return 1;
718}
719
720static void serial_dtr_rts(struct tty_port *port, int on)
721{
722 struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
723 struct usb_serial_driver *drv = p->serial->type;
724 if (drv->dtr_rts)
725 drv->dtr_rts(p, on);
726}
727
728static const struct tty_port_operations serial_port_ops = {
729 .carrier_raised = serial_carrier_raised,
730 .dtr_rts = serial_dtr_rts,
731};
732
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733int usb_serial_probe(struct usb_interface *interface,
734 const struct usb_device_id *id)
735{
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100736 struct usb_device *dev = interface_to_usbdev(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 struct usb_serial *serial = NULL;
738 struct usb_serial_port *port;
739 struct usb_host_interface *iface_desc;
740 struct usb_endpoint_descriptor *endpoint;
741 struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS];
742 struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS];
743 struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];
744 struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700745 struct usb_serial_driver *type = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 int retval;
Andre Hauptdd9ca5d2008-06-18 15:56:00 +0200747 unsigned int minor;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 int buffer_size;
749 int i;
750 int num_interrupt_in = 0;
751 int num_interrupt_out = 0;
752 int num_bulk_in = 0;
753 int num_bulk_out = 0;
754 int num_ports = 0;
755 int max_endpoints;
756
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100757 lock_kernel(); /* guard against unloading a serial driver module */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 type = search_serial_device(interface);
759 if (!type) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100760 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 dbg("none matched");
762 return -ENODEV;
763 }
764
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100765 serial = create_serial(dev, interface, type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 if (!serial) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100767 unlock_kernel();
Harvey Harrison441b62c2008-03-03 16:08:34 -0800768 dev_err(&interface->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769 return -ENOMEM;
770 }
771
772 /* if this device type has a probe function, call it */
773 if (type->probe) {
774 const struct usb_device_id *id;
775
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700776 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100777 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100778 dev_err(&interface->dev,
779 "module get failed, exiting\n");
780 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 return -EIO;
782 }
783
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100784 id = get_iface_id(type, interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785 retval = type->probe(serial, id);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700786 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787
788 if (retval) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100789 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100790 dbg("sub driver rejected device");
791 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 return retval;
793 }
794 }
795
796 /* descriptor matches, let's find the endpoints needed */
797 /* check out the endpoints */
798 iface_desc = interface->cur_altsetting;
799 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
800 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700801
802 if (usb_endpoint_is_bulk_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 /* we found a bulk in endpoint */
804 dbg("found bulk in on endpoint %d", i);
805 bulk_in_endpoint[num_bulk_in] = endpoint;
806 ++num_bulk_in;
807 }
808
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700809 if (usb_endpoint_is_bulk_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 /* we found a bulk out endpoint */
811 dbg("found bulk out on endpoint %d", i);
812 bulk_out_endpoint[num_bulk_out] = endpoint;
813 ++num_bulk_out;
814 }
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700815
816 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 /* we found a interrupt in endpoint */
818 dbg("found interrupt in on endpoint %d", i);
819 interrupt_in_endpoint[num_interrupt_in] = endpoint;
820 ++num_interrupt_in;
821 }
822
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700823 if (usb_endpoint_is_int_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 /* we found an interrupt out endpoint */
825 dbg("found interrupt out on endpoint %d", i);
826 interrupt_out_endpoint[num_interrupt_out] = endpoint;
827 ++num_interrupt_out;
828 }
829 }
830
831#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100832 /* BEGIN HORRIBLE HACK FOR PL2303 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 /* this is needed due to the looney way its endpoints are set up */
834 if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&
835 (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||
836 ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) &&
Johannes Steingraeber8fd80132006-09-16 16:17:34 +0200837 (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) ||
838 ((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) &&
Andreas Bombece816cf2008-09-14 01:58:55 +0200839 (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID)) ||
840 ((le16_to_cpu(dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) &&
841 (le16_to_cpu(dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_EF81))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 if (interface != dev->actconfig->interface[0]) {
843 /* check out the endpoints of the other interface*/
844 iface_desc = dev->actconfig->interface[0]->cur_altsetting;
845 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
846 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700847 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 /* we found a interrupt in endpoint */
849 dbg("found interrupt in for Prolific device on separate interface");
850 interrupt_in_endpoint[num_interrupt_in] = endpoint;
851 ++num_interrupt_in;
852 }
853 }
854 }
855
856 /* Now make sure the PL-2303 is configured correctly.
857 * If not, give up now and hope this hack will work
858 * properly during a later invocation of usb_serial_probe
859 */
860 if (num_bulk_in == 0 || num_bulk_out == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100861 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100863 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 return -ENODEV;
865 }
866 }
867 /* END HORRIBLE HACK FOR PL2303 */
868#endif
869
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870#ifdef CONFIG_USB_SERIAL_GENERIC
871 if (type == &usb_serial_generic_device) {
872 num_ports = num_bulk_out;
873 if (num_ports == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100874 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100875 dev_err(&interface->dev,
876 "Generic device with no bulk out, not allowed.\n");
877 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878 return -EIO;
879 }
880 }
881#endif
882 if (!num_ports) {
883 /* if this device type has a calc_num_ports function, call it */
884 if (type->calc_num_ports) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700885 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100886 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100887 dev_err(&interface->dev,
888 "module get failed, exiting\n");
889 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 return -EIO;
891 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100892 num_ports = type->calc_num_ports(serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700893 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 }
895 if (!num_ports)
896 num_ports = type->num_ports;
897 }
898
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 serial->num_ports = num_ports;
900 serial->num_bulk_in = num_bulk_in;
901 serial->num_bulk_out = num_bulk_out;
902 serial->num_interrupt_in = num_interrupt_in;
903 serial->num_interrupt_out = num_interrupt_out;
904
Alan Stern063a2da2007-10-10 16:24:06 -0400905 /* found all that we need */
906 dev_info(&interface->dev, "%s converter detected\n",
907 type->description);
908
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 /* create our ports, we need as many as the max endpoints */
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100910 /* we don't use num_ports here because some devices have more
911 endpoint pairs than ports */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 max_endpoints = max(num_bulk_in, num_bulk_out);
913 max_endpoints = max(max_endpoints, num_interrupt_in);
914 max_endpoints = max(max_endpoints, num_interrupt_out);
915 max_endpoints = max(max_endpoints, (int)serial->num_ports);
916 serial->num_port_pointers = max_endpoints;
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100917 unlock_kernel();
918
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100919 dbg("%s - setting up %d port structures for this device",
920 __func__, max_endpoints);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 for (i = 0; i < max_endpoints; ++i) {
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100922 port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923 if (!port)
924 goto probe_error;
Alan Cox4a90f092008-10-13 10:39:46 +0100925 tty_port_init(&port->port);
Alan Cox335f8512009-06-11 12:26:29 +0100926 port->port.ops = &serial_port_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 port->serial = serial;
Greg Kroah-Hartman507ca9b2005-04-23 12:49:16 -0700928 spin_lock_init(&port->lock);
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300929 mutex_init(&port->mutex);
David Howellsc4028952006-11-22 14:57:56 +0000930 INIT_WORK(&port->work, usb_serial_port_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 serial->port[i] = port;
Alan Stern41bd34d2009-09-01 11:38:34 -0400932 port->dev.parent = &interface->dev;
933 port->dev.driver = NULL;
934 port->dev.bus = &usb_serial_bus_type;
935 port->dev.release = &port_release;
936 device_initialize(&port->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937 }
938
939 /* set up the endpoint information */
940 for (i = 0; i < num_bulk_in; ++i) {
941 endpoint = bulk_in_endpoint[i];
942 port = serial->port[i];
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100943 port->read_urb = usb_alloc_urb(0, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944 if (!port->read_urb) {
945 dev_err(&interface->dev, "No free urbs available\n");
946 goto probe_error;
947 }
948 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
949 port->bulk_in_size = buffer_size;
950 port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100951 port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952 if (!port->bulk_in_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100953 dev_err(&interface->dev,
954 "Couldn't allocate bulk_in_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955 goto probe_error;
956 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100957 usb_fill_bulk_urb(port->read_urb, dev,
958 usb_rcvbulkpipe(dev,
959 endpoint->bEndpointAddress),
960 port->bulk_in_buffer, buffer_size,
961 serial->type->read_bulk_callback, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 }
963
964 for (i = 0; i < num_bulk_out; ++i) {
965 endpoint = bulk_out_endpoint[i];
966 port = serial->port[i];
967 port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
968 if (!port->write_urb) {
969 dev_err(&interface->dev, "No free urbs available\n");
970 goto probe_error;
971 }
972 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
973 port->bulk_out_size = buffer_size;
974 port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100975 port->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976 if (!port->bulk_out_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100977 dev_err(&interface->dev,
978 "Couldn't allocate bulk_out_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979 goto probe_error;
980 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100981 usb_fill_bulk_urb(port->write_urb, dev,
982 usb_sndbulkpipe(dev,
983 endpoint->bEndpointAddress),
984 port->bulk_out_buffer, buffer_size,
985 serial->type->write_bulk_callback, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986 }
987
988 if (serial->type->read_int_callback) {
989 for (i = 0; i < num_interrupt_in; ++i) {
990 endpoint = interrupt_in_endpoint[i];
991 port = serial->port[i];
992 port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
993 if (!port->interrupt_in_urb) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100994 dev_err(&interface->dev,
995 "No free urbs available\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 goto probe_error;
997 }
998 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100999 port->interrupt_in_endpointAddress =
1000 endpoint->bEndpointAddress;
1001 port->interrupt_in_buffer = kmalloc(buffer_size,
1002 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 if (!port->interrupt_in_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001004 dev_err(&interface->dev,
1005 "Couldn't allocate interrupt_in_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 goto probe_error;
1007 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001008 usb_fill_int_urb(port->interrupt_in_urb, dev,
1009 usb_rcvintpipe(dev,
1010 endpoint->bEndpointAddress),
1011 port->interrupt_in_buffer, buffer_size,
1012 serial->type->read_int_callback, port,
1013 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 }
1015 } else if (num_interrupt_in) {
1016 dbg("the device claims to support interrupt in transfers, but read_int_callback is not defined");
1017 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001018
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 if (serial->type->write_int_callback) {
1020 for (i = 0; i < num_interrupt_out; ++i) {
1021 endpoint = interrupt_out_endpoint[i];
1022 port = serial->port[i];
1023 port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
1024 if (!port->interrupt_out_urb) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001025 dev_err(&interface->dev,
1026 "No free urbs available\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 goto probe_error;
1028 }
1029 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
1030 port->interrupt_out_size = buffer_size;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001031 port->interrupt_out_endpointAddress =
1032 endpoint->bEndpointAddress;
1033 port->interrupt_out_buffer = kmalloc(buffer_size,
1034 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 if (!port->interrupt_out_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001036 dev_err(&interface->dev,
1037 "Couldn't allocate interrupt_out_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 goto probe_error;
1039 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001040 usb_fill_int_urb(port->interrupt_out_urb, dev,
1041 usb_sndintpipe(dev,
1042 endpoint->bEndpointAddress),
1043 port->interrupt_out_buffer, buffer_size,
1044 serial->type->write_int_callback, port,
1045 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046 }
1047 } else if (num_interrupt_out) {
1048 dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined");
1049 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001050
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 /* if this device type has an attach function, call it */
1052 if (type->attach) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -07001053 if (!try_module_get(type->driver.owner)) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001054 dev_err(&interface->dev,
1055 "module get failed, exiting\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 goto probe_error;
1057 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001058 retval = type->attach(serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -07001059 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060 if (retval < 0)
1061 goto probe_error;
1062 if (retval > 0) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001063 /* quietly accept this device, but don't bind to a
1064 serial port as it's about to disappear */
Alan Stern0a3c8542009-05-27 11:25:52 -04001065 serial->num_ports = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 goto exit;
1067 }
1068 }
1069
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001070 if (get_free_serial(serial, num_ports, &minor) == NULL) {
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001071 dev_err(&interface->dev, "No more free serial devices\n");
1072 goto probe_error;
1073 }
Oliver Neukumc744f992007-02-26 15:43:00 +01001074 serial->minor = minor;
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001075
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 /* register all of the individual ports with the driver core */
1077 for (i = 0; i < num_ports; ++i) {
1078 port = serial->port[i];
Kay Sievers0031a062008-05-02 06:02:41 +02001079 dev_set_name(&port->dev, "ttyUSB%d", port->number);
Kay Sievers7071a3c2008-05-02 06:02:41 +02001080 dbg ("%s - registering %s", __func__, dev_name(&port->dev));
Alan Sternc706ebd2009-06-02 11:54:11 -04001081 port->dev_state = PORT_REGISTERING;
Alan Stern41bd34d2009-09-01 11:38:34 -04001082 retval = device_add(&port->dev);
Alan Sternc706ebd2009-06-02 11:54:11 -04001083 if (retval) {
Greg Kroah-Hartman13f4db92006-08-28 11:43:25 -07001084 dev_err(&port->dev, "Error registering port device, "
1085 "continuing\n");
Alan Sternc706ebd2009-06-02 11:54:11 -04001086 port->dev_state = PORT_UNREGISTERED;
1087 } else {
1088 port->dev_state = PORT_REGISTERED;
1089 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 }
1091
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001092 usb_serial_console_init(debug, minor);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093
1094exit:
1095 /* success */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001096 usb_set_intfdata(interface, serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 return 0;
1098
1099probe_error:
Alan Stern41bd34d2009-09-01 11:38:34 -04001100 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101 return -EIO;
1102}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001103EXPORT_SYMBOL_GPL(usb_serial_probe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104
1105void usb_serial_disconnect(struct usb_interface *interface)
1106{
1107 int i;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001108 struct usb_serial *serial = usb_get_intfdata(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 struct device *dev = &interface->dev;
1110 struct usb_serial_port *port;
1111
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +02001112 usb_serial_console_disconnect(serial);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001113 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001115 mutex_lock(&serial->disc_mutex);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001116 usb_set_intfdata(interface, NULL);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001117 /* must set a flag, to signal subdrivers */
1118 serial->disconnected = 1;
Alan Stern2d931482009-04-14 11:31:02 -04001119 mutex_unlock(&serial->disc_mutex);
1120
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001121 for (i = 0; i < serial->num_ports; ++i) {
1122 port = serial->port[i];
1123 if (port) {
Alan Cox4a90f092008-10-13 10:39:46 +01001124 struct tty_struct *tty = tty_port_tty_get(&port->port);
1125 if (tty) {
Alan Coxd2b39182009-09-19 13:13:23 -07001126 tty_vhangup(tty);
Alan Cox4a90f092008-10-13 10:39:46 +01001127 tty_kref_put(tty);
1128 }
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001129 kill_traffic(port);
Alan Stern2d931482009-04-14 11:31:02 -04001130 cancel_work_sync(&port->work);
Alan Sternc706ebd2009-06-02 11:54:11 -04001131 if (port->dev_state == PORT_REGISTERED) {
1132
1133 /* Make sure the port is bound so that the
1134 * driver's port_remove method is called.
1135 */
1136 if (!port->dev.driver) {
1137 int rc;
1138
1139 port->dev.driver =
1140 &serial->type->driver;
1141 rc = device_bind_driver(&port->dev);
1142 }
1143 port->dev_state = PORT_UNREGISTERING;
1144 device_del(&port->dev);
1145 port->dev_state = PORT_UNREGISTERED;
1146 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 }
Alan Sternf9c99bb2009-06-02 11:53:55 -04001149 serial->type->disconnect(serial);
Alan Stern2d931482009-04-14 11:31:02 -04001150
Alan Stern41bd34d2009-09-01 11:38:34 -04001151 /* let the last holder of this object cause it to be cleaned up */
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001152 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153 dev_info(dev, "device disconnected\n");
1154}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001155EXPORT_SYMBOL_GPL(usb_serial_disconnect);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156
Oliver Neukumec225592007-04-27 20:54:57 +02001157int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
1158{
1159 struct usb_serial *serial = usb_get_intfdata(intf);
1160 struct usb_serial_port *port;
1161 int i, r = 0;
1162
Oliver Neukumf8bece82009-02-05 16:54:25 +01001163 serial->suspending = 1;
1164
Oliver Neukume31c1882007-07-23 08:58:39 +02001165 for (i = 0; i < serial->num_ports; ++i) {
1166 port = serial->port[i];
1167 if (port)
1168 kill_traffic(port);
Oliver Neukumec225592007-04-27 20:54:57 +02001169 }
1170
1171 if (serial->type->suspend)
Oliver Neukume31c1882007-07-23 08:58:39 +02001172 r = serial->type->suspend(serial, message);
Oliver Neukumec225592007-04-27 20:54:57 +02001173
1174 return r;
1175}
1176EXPORT_SYMBOL(usb_serial_suspend);
1177
1178int usb_serial_resume(struct usb_interface *intf)
1179{
1180 struct usb_serial *serial = usb_get_intfdata(intf);
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001181 int rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001182
Oliver Neukumf8bece82009-02-05 16:54:25 +01001183 serial->suspending = 0;
Sarah Sharp8abaee22007-10-25 10:58:43 -07001184 if (serial->type->resume)
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001185 rv = serial->type->resume(serial);
1186 else
1187 rv = usb_serial_generic_resume(serial);
Oliver Neukumf8bece82009-02-05 16:54:25 +01001188
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001189 return rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001190}
1191EXPORT_SYMBOL(usb_serial_resume);
1192
Jeff Dikeb68e31d2006-10-02 02:17:18 -07001193static const struct tty_operations serial_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194 .open = serial_open,
1195 .close = serial_close,
1196 .write = serial_write,
Alan Cox335f8512009-06-11 12:26:29 +01001197 .hangup = serial_hangup,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 .write_room = serial_write_room,
1199 .ioctl = serial_ioctl,
1200 .set_termios = serial_set_termios,
1201 .throttle = serial_throttle,
1202 .unthrottle = serial_unthrottle,
1203 .break_ctl = serial_break,
1204 .chars_in_buffer = serial_chars_in_buffer,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205 .tiocmget = serial_tiocmget,
1206 .tiocmset = serial_tiocmset,
Alan Coxfe1ae7f2009-09-19 13:13:33 -07001207 .shutdown = serial_do_free,
1208 .install = serial_install,
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -07001209 .proc_fops = &serial_proc_fops,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210};
1211
Alan Cox335f8512009-06-11 12:26:29 +01001212
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213struct tty_driver *usb_serial_tty_driver;
1214
1215static int __init usb_serial_init(void)
1216{
1217 int i;
1218 int result;
1219
1220 usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS);
1221 if (!usb_serial_tty_driver)
1222 return -ENOMEM;
1223
1224 /* Initialize our global data */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001225 for (i = 0; i < SERIAL_TTY_MINORS; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226 serial_table[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227
1228 result = bus_register(&usb_serial_bus_type);
1229 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001230 printk(KERN_ERR "usb-serial: %s - registering bus driver "
1231 "failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 goto exit_bus;
1233 }
1234
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235 usb_serial_tty_driver->owner = THIS_MODULE;
1236 usb_serial_tty_driver->driver_name = "usbserial";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237 usb_serial_tty_driver->name = "ttyUSB";
1238 usb_serial_tty_driver->major = SERIAL_TTY_MAJOR;
1239 usb_serial_tty_driver->minor_start = 0;
1240 usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
1241 usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001242 usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW |
1243 TTY_DRIVER_DYNAMIC_DEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 usb_serial_tty_driver->init_termios = tty_std_termios;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001245 usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD
1246 | HUPCL | CLOCAL;
Alan Coxa5b6f602008-04-08 17:16:06 +01001247 usb_serial_tty_driver->init_termios.c_ispeed = 9600;
1248 usb_serial_tty_driver->init_termios.c_ospeed = 9600;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249 tty_set_operations(usb_serial_tty_driver, &serial_ops);
1250 result = tty_register_driver(usb_serial_tty_driver);
1251 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001252 printk(KERN_ERR "usb-serial: %s - tty_register_driver failed\n",
1253 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254 goto exit_reg_driver;
1255 }
1256
1257 /* register the USB driver */
1258 result = usb_register(&usb_serial_driver);
1259 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001260 printk(KERN_ERR "usb-serial: %s - usb_register failed\n",
1261 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262 goto exit_tty;
1263 }
1264
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001265 /* register the generic driver, if we should */
1266 result = usb_serial_generic_register(debug);
1267 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001268 printk(KERN_ERR "usb-serial: %s - registering generic "
1269 "driver failed\n", __func__);
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001270 goto exit_generic;
1271 }
1272
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001273 printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274
1275 return result;
1276
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001277exit_generic:
1278 usb_deregister(&usb_serial_driver);
1279
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280exit_tty:
1281 tty_unregister_driver(usb_serial_tty_driver);
1282
1283exit_reg_driver:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284 bus_unregister(&usb_serial_bus_type);
1285
1286exit_bus:
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001287 printk(KERN_ERR "usb-serial: %s - returning with error %d\n",
1288 __func__, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289 put_tty_driver(usb_serial_tty_driver);
1290 return result;
1291}
1292
1293
1294static void __exit usb_serial_exit(void)
1295{
1296 usb_serial_console_exit();
1297
1298 usb_serial_generic_deregister();
1299
1300 usb_deregister(&usb_serial_driver);
1301 tty_unregister_driver(usb_serial_tty_driver);
1302 put_tty_driver(usb_serial_tty_driver);
1303 bus_unregister(&usb_serial_bus_type);
1304}
1305
1306
1307module_init(usb_serial_init);
1308module_exit(usb_serial_exit);
1309
1310#define set_to_generic_if_null(type, function) \
1311 do { \
1312 if (!type->function) { \
1313 type->function = usb_serial_generic_##function; \
1314 dbg("Had to override the " #function \
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001315 " usb serial operation with the generic one.");\
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316 } \
1317 } while (0)
1318
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001319static void fixup_generic(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320{
1321 set_to_generic_if_null(device, open);
1322 set_to_generic_if_null(device, write);
1323 set_to_generic_if_null(device, close);
1324 set_to_generic_if_null(device, write_room);
1325 set_to_generic_if_null(device, chars_in_buffer);
1326 set_to_generic_if_null(device, read_bulk_callback);
1327 set_to_generic_if_null(device, write_bulk_callback);
Alan Sternf9c99bb2009-06-02 11:53:55 -04001328 set_to_generic_if_null(device, disconnect);
1329 set_to_generic_if_null(device, release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330}
1331
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001332int usb_serial_register(struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001334 /* must be called with BKL held */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335 int retval;
1336
Dave Younge4abe662009-02-14 21:21:13 +08001337 if (usb_disabled())
1338 return -ENODEV;
1339
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001340 fixup_generic(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001342 if (!driver->description)
1343 driver->description = driver->driver.name;
1344
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 /* Add this device to our list of devices */
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001346 list_add(&driver->driver_list, &usb_serial_driver_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001348 retval = usb_serial_bus_register(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 if (retval) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001350 printk(KERN_ERR "usb-serial: problem %d when registering "
1351 "driver %s\n", retval, driver->description);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001352 list_del(&driver->driver_list);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001353 } else
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001354 printk(KERN_INFO "USB Serial support registered for %s\n",
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001355 driver->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356
1357 return retval;
1358}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001359EXPORT_SYMBOL_GPL(usb_serial_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360
1361
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001362void usb_serial_deregister(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001364 /* must be called with BKL held */
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001365 printk(KERN_INFO "USB Serial deregistering driver %s\n",
1366 device->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 list_del(&device->driver_list);
1368 usb_serial_bus_deregister(device);
1369}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370EXPORT_SYMBOL_GPL(usb_serial_deregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371
1372/* Module information */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001373MODULE_AUTHOR(DRIVER_AUTHOR);
1374MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375MODULE_LICENSE("GPL");
1376
1377module_param(debug, bool, S_IRUGO | S_IWUSR);
1378MODULE_PARM_DESC(debug, "Debug enabled or not");