blob: 9a3258046c8cdc4daf4079208f4da556858ae841 [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 Coxa8d6f0a2008-07-22 11:12:24 +0100248static int serial_open (struct tty_struct *tty, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249{
250 struct usb_serial *serial;
251 struct usb_serial_port *port;
Alan Stern2d931482009-04-14 11:31:02 -0400252 int retval = 0;
Alan Coxc56d3002009-07-28 00:34:58 +0100253 int first = 0;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100254
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 Sternff8324d2009-09-01 11:39:51 -0400258 dbg("%s - port %d", __func__, port->number);
259
Alan Sterncc56cd02009-09-01 11:39:13 -0400260 if (mutex_lock_interruptible(&port->mutex))
261 return -ERESTARTSYS;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100262
Alan Cox95da3102008-07-22 11:09:07 +0100263 ++port->port.count;
Alan Cox4a90f092008-10-13 10:39:46 +0100264 tty_port_tty_set(&port->port, tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265
Jason Wessel6e406122009-06-22 11:32:20 -0500266 /* If the console is attached, the device is already open */
267 if (port->port.count == 1 && !port->console) {
Alan Coxc56d3002009-07-28 00:34:58 +0100268 first = 1;
Alan Stern2d931482009-04-14 11:31:02 -0400269 mutex_lock(&serial->disc_mutex);
Alan Stern2d931482009-04-14 11:31:02 -0400270
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100271 /* only call the device specific open if this
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 * is the first time the port is opened */
Alan Coxa509a7e2009-09-19 13:13:26 -0700273 retval = serial->type->open(tty, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 if (retval)
Alan Sterncc56cd02009-09-01 11:39:13 -0400275 goto bailout_module_put;
Alan Stern2d931482009-04-14 11:31:02 -0400276 mutex_unlock(&serial->disc_mutex);
Alan Coxc56d3002009-07-28 00:34:58 +0100277 set_bit(ASYNCB_INITIALIZED, &port->port.flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 }
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300279 mutex_unlock(&port->mutex);
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);
Alan Coxc56d3002009-07-28 00:34:58 +0100282 if (retval == 0) {
283 if (!first)
284 usb_serial_put(serial);
Alan Cox335f8512009-06-11 12:26:29 +0100285 return 0;
Alan Coxc56d3002009-07-28 00:34:58 +0100286 }
287 mutex_lock(&port->mutex);
288 if (first == 0)
289 goto bailout_mutex_unlock;
290 /* Undo the initial port actions */
291 mutex_lock(&serial->disc_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292bailout_module_put:
Alan Stern2d931482009-04-14 11:31:02 -0400293 mutex_unlock(&serial->disc_mutex);
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300294bailout_mutex_unlock:
Alan Cox95da3102008-07-22 11:09:07 +0100295 port->port.count = 0;
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300296 mutex_unlock(&port->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 return retval;
298}
299
Alan Cox335f8512009-06-11 12:26:29 +0100300/**
Alan Stern74556122009-09-01 11:39:40 -0400301 * serial_down - shut down hardware
Alan Sternf5b09532009-09-01 11:38:44 -0400302 * @port: port to shut down
Alan Cox335f8512009-06-11 12:26:29 +0100303 *
Alan Sternf5b09532009-09-01 11:38:44 -0400304 * Shut down a USB serial port unless it is the console. We never
305 * shut down the console hardware as it will always be in use.
Alan Cox335f8512009-06-11 12:26:29 +0100306 */
Alan Stern74556122009-09-01 11:39:40 -0400307static void serial_down(struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308{
Alan Cox335f8512009-06-11 12:26:29 +0100309 struct usb_serial_driver *drv = port->serial->type;
Alan Stern2d931482009-04-14 11:31:02 -0400310 struct usb_serial *serial;
311 struct module *owner;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312
Alan Sternf5b09532009-09-01 11:38:44 -0400313 /*
314 * The console is magical. Do not hang up the console hardware
315 * or there will be tears.
316 */
Alan Cox335f8512009-06-11 12:26:29 +0100317 if (port->console)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 return;
319
Alan Sternff8324d2009-09-01 11:39:51 -0400320 /* Don't call the close method if the hardware hasn't been
321 * initialized.
322 */
323 if (!test_and_clear_bit(ASYNCB_INITIALIZED, &port->port.flags))
324 return;
325
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300326 mutex_lock(&port->mutex);
Alan Stern2d931482009-04-14 11:31:02 -0400327 serial = port->serial;
328 owner = serial->type->driver.owner;
Luiz Fernando Capitulino8a4613f2005-11-28 19:16:07 -0200329
Alan Cox335f8512009-06-11 12:26:29 +0100330 if (drv->close)
331 drv->close(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300333 mutex_unlock(&port->mutex);
Alan Cox335f8512009-06-11 12:26:29 +0100334}
335
Alan Sternf5b09532009-09-01 11:38:44 -0400336static void serial_hangup(struct tty_struct *tty)
Alan Cox335f8512009-06-11 12:26:29 +0100337{
Alan Cox4455e342009-09-19 13:13:24 -0700338 struct usb_serial_port *port = tty->driver_data;
Alan Sternff8324d2009-09-01 11:39:51 -0400339
340 dbg("%s - port %d", __func__, port->number);
341
Alan Stern74556122009-09-01 11:39:40 -0400342 serial_down(port);
Alan Sternf5b09532009-09-01 11:38:44 -0400343 tty_port_hangup(&port->port);
Alan Cox335f8512009-06-11 12:26:29 +0100344}
345
346static void serial_close(struct tty_struct *tty, struct file *filp)
347{
348 struct usb_serial_port *port = tty->driver_data;
349
350 dbg("%s - port %d", __func__, port->number);
351
Alan Sternff8324d2009-09-01 11:39:51 -0400352 if (tty_hung_up_p(filp))
353 return;
Alan Cox335f8512009-06-11 12:26:29 +0100354 if (tty_port_close_start(&port->port, tty, filp) == 0)
355 return;
Alan Stern74556122009-09-01 11:39:40 -0400356 serial_down(port);
Alan Cox335f8512009-06-11 12:26:29 +0100357 tty_port_close_end(&port->port, tty);
358 tty_port_tty_set(&port->port, NULL);
Alan Cox335f8512009-06-11 12:26:29 +0100359}
360
Alan Sternf5b09532009-09-01 11:38:44 -0400361/**
Alan Stern74556122009-09-01 11:39:40 -0400362 * serial_release - free resources post close/hangup
Alan Sternf5b09532009-09-01 11:38:44 -0400363 * @port: port to free up
364 *
365 * Do the resource freeing and refcount dropping for the port.
366 * Avoid freeing the console.
367 *
368 * Called when the last tty kref is dropped.
369 */
Alan Stern74556122009-09-01 11:39:40 -0400370static void serial_release(struct tty_struct *tty)
Alan Cox335f8512009-06-11 12:26:29 +0100371{
372 struct usb_serial_port *port = tty->driver_data;
Alan Sternf5b09532009-09-01 11:38:44 -0400373 struct usb_serial *serial;
374 struct module *owner;
375
376 /* The console is magical. Do not hang up the console hardware
377 * or there will be tears.
378 */
Alan Sterncc56cd02009-09-01 11:39:13 -0400379 if (port->console)
Alan Sternf5b09532009-09-01 11:38:44 -0400380 return;
381
Alan Sternff8324d2009-09-01 11:39:51 -0400382 dbg("%s - port %d", __func__, port->number);
383
Alan Stern74556122009-09-01 11:39:40 -0400384 /* Standard shutdown processing */
385 tty_shutdown(tty);
386
Alan Sterncc56cd02009-09-01 11:39:13 -0400387 tty->driver_data = NULL;
388
Alan Sternf5b09532009-09-01 11:38:44 -0400389 serial = port->serial;
390 owner = serial->type->driver.owner;
391
392 mutex_lock(&serial->disc_mutex);
393 if (!serial->disconnected)
394 usb_autopm_put_interface(serial->interface);
395 mutex_unlock(&serial->disc_mutex);
396
397 usb_serial_put(serial);
398 module_put(owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399}
400
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100401static int serial_write(struct tty_struct *tty, const unsigned char *buf,
402 int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200404 struct usb_serial_port *port = tty->driver_data;
Oliver Neukum3ff4fd92007-01-13 07:32:27 +0100405 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406
Alan Coxf34d7a52008-04-30 00:54:13 -0700407 if (port->serial->dev->state == USB_STATE_NOTATTACHED)
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200408 goto exit;
409
Harvey Harrison441b62c2008-03-03 16:08:34 -0800410 dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411
Alan Cox95da3102008-07-22 11:09:07 +0100412 /* count is managed under the mutex lock for the tty so cannot
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100413 drop to zero until after the last close completes */
Alan Cox95da3102008-07-22 11:09:07 +0100414 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415
416 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100417 retval = port->serial->type->write(tty, port, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418
419exit:
420 return retval;
421}
422
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100423static int serial_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200425 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800426 dbg("%s - port %d", __func__, port->number);
Alan Cox95da3102008-07-22 11:09:07 +0100427 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100429 return port->serial->type->write_room(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430}
431
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100432static int serial_chars_in_buffer(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200434 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800435 dbg("%s = port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436
Alan Coxeff69372009-01-02 13:47:06 +0000437 /* if the device was unplugged then any remaining characters
438 fell out of the connector ;) */
439 if (port->serial->disconnected)
440 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100442 return port->serial->type->chars_in_buffer(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443}
444
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100445static void serial_throttle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200447 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800448 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449
Alan Cox95da3102008-07-22 11:09:07 +0100450 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 /* pass on to the driver specific version of this function */
452 if (port->serial->type->throttle)
Alan Cox95da3102008-07-22 11:09:07 +0100453 port->serial->type->throttle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454}
455
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100456static void serial_unthrottle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200458 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800459 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460
Alan Cox95da3102008-07-22 11:09:07 +0100461 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 /* pass on to the driver specific version of this function */
463 if (port->serial->type->unthrottle)
Alan Cox95da3102008-07-22 11:09:07 +0100464 port->serial->type->unthrottle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465}
466
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100467static int serial_ioctl(struct tty_struct *tty, struct file *file,
468 unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200470 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 int retval = -ENODEV;
472
Harvey Harrison441b62c2008-03-03 16:08:34 -0800473 dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474
Alan Cox95da3102008-07-22 11:09:07 +0100475 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100477 /* pass on to the driver specific version of this function
478 if it is available */
Alan Coxf34d7a52008-04-30 00:54:13 -0700479 if (port->serial->type->ioctl) {
Alan Cox95da3102008-07-22 11:09:07 +0100480 retval = port->serial->type->ioctl(tty, file, cmd, arg);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100481 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 retval = -ENOIOCTLCMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 return retval;
484}
485
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100486static void serial_set_termios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200488 struct usb_serial_port *port = tty->driver_data;
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 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494 if (port->serial->type->set_termios)
Alan Cox95da3102008-07-22 11:09:07 +0100495 port->serial->type->set_termios(tty, port, old);
Alan Cox33785092007-10-18 01:24:22 -0700496 else
497 tty_termios_copy_hw(tty->termios, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498}
499
Alan Cox9e989662008-07-22 11:18:03 +0100500static int serial_break(struct tty_struct *tty, int break_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200502 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503
Harvey Harrison441b62c2008-03-03 16:08:34 -0800504 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505
Alan Cox95da3102008-07-22 11:09:07 +0100506 WARN_ON(!port->port.count);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100507 /* pass on to the driver specific version of this function
508 if it is available */
Alan Cox6b447f042009-01-02 13:48:56 +0000509 if (port->serial->type->break_ctl)
Alan Cox95da3102008-07-22 11:09:07 +0100510 port->serial->type->break_ctl(tty, break_state);
Alan Cox9e989662008-07-22 11:18:03 +0100511 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512}
513
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700514static int serial_proc_show(struct seq_file *m, void *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515{
516 struct usb_serial *serial;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 char tmp[40];
519
Harvey Harrison441b62c2008-03-03 16:08:34 -0800520 dbg("%s", __func__);
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700521 seq_puts(m, "usbserinfo:1.0 driver:2.0\n");
522 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 serial = usb_serial_get_by_index(i);
524 if (serial == NULL)
525 continue;
526
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700527 seq_printf(m, "%d:", i);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700528 if (serial->type->driver.owner)
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700529 seq_printf(m, " module:%s",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100530 module_name(serial->type->driver.owner));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700531 seq_printf(m, " name:\"%s\"",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100532 serial->type->description);
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700533 seq_printf(m, " vendor:%04x product:%04x",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100534 le16_to_cpu(serial->dev->descriptor.idVendor),
535 le16_to_cpu(serial->dev->descriptor.idProduct));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700536 seq_printf(m, " num_ports:%d", serial->num_ports);
537 seq_printf(m, " port:%d", i - serial->minor + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 usb_make_path(serial->dev, tmp, sizeof(tmp));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700539 seq_printf(m, " path:%s", tmp);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100540
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700541 seq_putc(m, '\n');
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200542 usb_serial_put(serial);
Alan Stern8bc2c1b2009-09-01 11:38:59 -0400543 mutex_unlock(&serial->disc_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 }
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700545 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546}
547
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700548static int serial_proc_open(struct inode *inode, struct file *file)
549{
550 return single_open(file, serial_proc_show, NULL);
551}
552
553static const struct file_operations serial_proc_fops = {
554 .owner = THIS_MODULE,
555 .open = serial_proc_open,
556 .read = seq_read,
557 .llseek = seq_lseek,
558 .release = single_release,
559};
560
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100561static int serial_tiocmget(struct tty_struct *tty, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200563 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564
Harvey Harrison441b62c2008-03-03 16:08:34 -0800565 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566
Alan Cox95da3102008-07-22 11:09:07 +0100567 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568 if (port->serial->type->tiocmget)
Alan Cox95da3102008-07-22 11:09:07 +0100569 return port->serial->type->tiocmget(tty, file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 return -EINVAL;
571}
572
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100573static int serial_tiocmset(struct tty_struct *tty, struct file *file,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 unsigned int set, unsigned int clear)
575{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200576 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577
Harvey Harrison441b62c2008-03-03 16:08:34 -0800578 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579
Alan Cox95da3102008-07-22 11:09:07 +0100580 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 if (port->serial->type->tiocmset)
Alan Cox95da3102008-07-22 11:09:07 +0100582 return port->serial->type->tiocmset(tty, file, set, clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 return -EINVAL;
584}
585
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700586/*
587 * We would be calling tty_wakeup here, but unfortunately some line
588 * disciplines have an annoying habit of calling tty->write from
589 * the write wakeup callback (e.g. n_hdlc.c).
590 */
591void usb_serial_port_softint(struct usb_serial_port *port)
592{
593 schedule_work(&port->work);
594}
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100595EXPORT_SYMBOL_GPL(usb_serial_port_softint);
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700596
David Howellsc4028952006-11-22 14:57:56 +0000597static void usb_serial_port_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598{
David Howellsc4028952006-11-22 14:57:56 +0000599 struct usb_serial_port *port =
600 container_of(work, struct usb_serial_port, work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601 struct tty_struct *tty;
602
Harvey Harrison441b62c2008-03-03 16:08:34 -0800603 dbg("%s - port %d", __func__, port->number);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100604
Alan Cox4a90f092008-10-13 10:39:46 +0100605 tty = tty_port_tty_get(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 if (!tty)
607 return;
608
609 tty_wakeup(tty);
Alan Cox4a90f092008-10-13 10:39:46 +0100610 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611}
612
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100613static void kill_traffic(struct usb_serial_port *port)
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700614{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 usb_kill_urb(port->write_urb);
Oliver Neukum5adceac2007-08-17 14:01:38 +0200617 /*
618 * This is tricky.
619 * Some drivers submit the read_urb in the
620 * handler for the write_urb or vice versa
621 * this order determines the order in which
622 * usb_kill_urb() must be used to reliably
623 * kill the URBs. As it is unknown here,
624 * both orders must be used in turn.
625 * The call below is not redundant.
626 */
627 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 usb_kill_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629 usb_kill_urb(port->interrupt_out_urb);
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100630}
631
Alan Stern41bd34d2009-09-01 11:38:34 -0400632static void port_release(struct device *dev)
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100633{
Alan Stern41bd34d2009-09-01 11:38:34 -0400634 struct usb_serial_port *port = to_usb_serial_port(dev);
635
636 dbg ("%s - %s", __func__, dev_name(dev));
637
Alan Stern2d931482009-04-14 11:31:02 -0400638 /*
639 * Stop all the traffic before cancelling the work, so that
640 * nobody will restart it by calling usb_serial_port_softint.
641 */
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100642 kill_traffic(port);
Alan Stern2d931482009-04-14 11:31:02 -0400643 cancel_work_sync(&port->work);
644
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100645 usb_free_urb(port->read_urb);
646 usb_free_urb(port->write_urb);
647 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 usb_free_urb(port->interrupt_out_urb);
649 kfree(port->bulk_in_buffer);
650 kfree(port->bulk_out_buffer);
651 kfree(port->interrupt_in_buffer);
652 kfree(port->interrupt_out_buffer);
653 kfree(port);
654}
655
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100656static struct usb_serial *create_serial(struct usb_device *dev,
657 struct usb_interface *interface,
658 struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659{
660 struct usb_serial *serial;
661
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100662 serial = kzalloc(sizeof(*serial), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 if (!serial) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800664 dev_err(&dev->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 return NULL;
666 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667 serial->dev = usb_get_dev(dev);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700668 serial->type = driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669 serial->interface = interface;
670 kref_init(&serial->kref);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +0100671 mutex_init(&serial->disc_mutex);
Alan Stern0282b7f2008-07-29 12:01:04 -0400672 serial->minor = SERIAL_TTY_NO_MINOR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673
674 return serial;
675}
676
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100677static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf,
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100678 struct usb_serial_driver *drv)
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100679{
680 struct usb_dynid *dynid;
681
682 spin_lock(&drv->dynids.lock);
683 list_for_each_entry(dynid, &drv->dynids.list, node) {
684 if (usb_match_one_id(intf, &dynid->id)) {
685 spin_unlock(&drv->dynids.lock);
686 return &dynid->id;
687 }
688 }
689 spin_unlock(&drv->dynids.lock);
690 return NULL;
691}
692
693static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv,
694 struct usb_interface *intf)
695{
696 const struct usb_device_id *id;
697
698 id = usb_match_id(intf, drv->id_table);
699 if (id) {
700 dbg("static descriptor matches");
701 goto exit;
702 }
703 id = match_dynamic_id(intf, drv);
704 if (id)
705 dbg("dynamic descriptor matches");
706exit:
707 return id;
708}
709
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100710static struct usb_serial_driver *search_serial_device(
711 struct usb_interface *iface)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713 const struct usb_device_id *id;
Alan Stern063a2da2007-10-10 16:24:06 -0400714 struct usb_serial_driver *drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715
Adrian Bunk93b1fae2006-01-10 00:13:33 +0100716 /* Check if the usb id matches a known device */
Alan Stern063a2da2007-10-10 16:24:06 -0400717 list_for_each_entry(drv, &usb_serial_driver_list, driver_list) {
718 id = get_iface_id(drv, iface);
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100719 if (id)
Alan Stern063a2da2007-10-10 16:24:06 -0400720 return drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 }
722
723 return NULL;
724}
725
Alan Cox335f8512009-06-11 12:26:29 +0100726static int serial_carrier_raised(struct tty_port *port)
727{
728 struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
729 struct usb_serial_driver *drv = p->serial->type;
730 if (drv->carrier_raised)
731 return drv->carrier_raised(p);
732 /* No carrier control - don't block */
733 return 1;
734}
735
736static void serial_dtr_rts(struct tty_port *port, int on)
737{
738 struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
739 struct usb_serial_driver *drv = p->serial->type;
740 if (drv->dtr_rts)
741 drv->dtr_rts(p, on);
742}
743
744static const struct tty_port_operations serial_port_ops = {
745 .carrier_raised = serial_carrier_raised,
746 .dtr_rts = serial_dtr_rts,
747};
748
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749int usb_serial_probe(struct usb_interface *interface,
750 const struct usb_device_id *id)
751{
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100752 struct usb_device *dev = interface_to_usbdev(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 struct usb_serial *serial = NULL;
754 struct usb_serial_port *port;
755 struct usb_host_interface *iface_desc;
756 struct usb_endpoint_descriptor *endpoint;
757 struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS];
758 struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS];
759 struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];
760 struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700761 struct usb_serial_driver *type = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 int retval;
Andre Hauptdd9ca5d2008-06-18 15:56:00 +0200763 unsigned int minor;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 int buffer_size;
765 int i;
766 int num_interrupt_in = 0;
767 int num_interrupt_out = 0;
768 int num_bulk_in = 0;
769 int num_bulk_out = 0;
770 int num_ports = 0;
771 int max_endpoints;
772
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100773 lock_kernel(); /* guard against unloading a serial driver module */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 type = search_serial_device(interface);
775 if (!type) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100776 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777 dbg("none matched");
778 return -ENODEV;
779 }
780
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100781 serial = create_serial(dev, interface, type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782 if (!serial) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100783 unlock_kernel();
Harvey Harrison441b62c2008-03-03 16:08:34 -0800784 dev_err(&interface->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785 return -ENOMEM;
786 }
787
788 /* if this device type has a probe function, call it */
789 if (type->probe) {
790 const struct usb_device_id *id;
791
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700792 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100793 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100794 dev_err(&interface->dev,
795 "module get failed, exiting\n");
796 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 return -EIO;
798 }
799
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100800 id = get_iface_id(type, interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 retval = type->probe(serial, id);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700802 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803
804 if (retval) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100805 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100806 dbg("sub driver rejected device");
807 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 return retval;
809 }
810 }
811
812 /* descriptor matches, let's find the endpoints needed */
813 /* check out the endpoints */
814 iface_desc = interface->cur_altsetting;
815 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
816 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700817
818 if (usb_endpoint_is_bulk_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 /* we found a bulk in endpoint */
820 dbg("found bulk in on endpoint %d", i);
821 bulk_in_endpoint[num_bulk_in] = endpoint;
822 ++num_bulk_in;
823 }
824
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700825 if (usb_endpoint_is_bulk_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826 /* we found a bulk out endpoint */
827 dbg("found bulk out on endpoint %d", i);
828 bulk_out_endpoint[num_bulk_out] = endpoint;
829 ++num_bulk_out;
830 }
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700831
832 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 /* we found a interrupt in endpoint */
834 dbg("found interrupt in on endpoint %d", i);
835 interrupt_in_endpoint[num_interrupt_in] = endpoint;
836 ++num_interrupt_in;
837 }
838
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700839 if (usb_endpoint_is_int_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 /* we found an interrupt out endpoint */
841 dbg("found interrupt out on endpoint %d", i);
842 interrupt_out_endpoint[num_interrupt_out] = endpoint;
843 ++num_interrupt_out;
844 }
845 }
846
847#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100848 /* BEGIN HORRIBLE HACK FOR PL2303 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 /* this is needed due to the looney way its endpoints are set up */
850 if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&
851 (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||
852 ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) &&
Johannes Steingraeber8fd80132006-09-16 16:17:34 +0200853 (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) ||
854 ((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) &&
Andreas Bombece816cf2008-09-14 01:58:55 +0200855 (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID)) ||
856 ((le16_to_cpu(dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) &&
857 (le16_to_cpu(dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_EF81))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 if (interface != dev->actconfig->interface[0]) {
859 /* check out the endpoints of the other interface*/
860 iface_desc = dev->actconfig->interface[0]->cur_altsetting;
861 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
862 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700863 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 /* we found a interrupt in endpoint */
865 dbg("found interrupt in for Prolific device on separate interface");
866 interrupt_in_endpoint[num_interrupt_in] = endpoint;
867 ++num_interrupt_in;
868 }
869 }
870 }
871
872 /* Now make sure the PL-2303 is configured correctly.
873 * If not, give up now and hope this hack will work
874 * properly during a later invocation of usb_serial_probe
875 */
876 if (num_bulk_in == 0 || num_bulk_out == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100877 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878 dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100879 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 return -ENODEV;
881 }
882 }
883 /* END HORRIBLE HACK FOR PL2303 */
884#endif
885
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886#ifdef CONFIG_USB_SERIAL_GENERIC
887 if (type == &usb_serial_generic_device) {
888 num_ports = num_bulk_out;
889 if (num_ports == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100890 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100891 dev_err(&interface->dev,
892 "Generic device with no bulk out, not allowed.\n");
893 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 return -EIO;
895 }
896 }
897#endif
898 if (!num_ports) {
899 /* if this device type has a calc_num_ports function, call it */
900 if (type->calc_num_ports) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700901 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100902 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100903 dev_err(&interface->dev,
904 "module get failed, exiting\n");
905 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 return -EIO;
907 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100908 num_ports = type->calc_num_ports(serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700909 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 }
911 if (!num_ports)
912 num_ports = type->num_ports;
913 }
914
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 serial->num_ports = num_ports;
916 serial->num_bulk_in = num_bulk_in;
917 serial->num_bulk_out = num_bulk_out;
918 serial->num_interrupt_in = num_interrupt_in;
919 serial->num_interrupt_out = num_interrupt_out;
920
Alan Stern063a2da2007-10-10 16:24:06 -0400921 /* found all that we need */
922 dev_info(&interface->dev, "%s converter detected\n",
923 type->description);
924
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 /* create our ports, we need as many as the max endpoints */
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100926 /* we don't use num_ports here because some devices have more
927 endpoint pairs than ports */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 max_endpoints = max(num_bulk_in, num_bulk_out);
929 max_endpoints = max(max_endpoints, num_interrupt_in);
930 max_endpoints = max(max_endpoints, num_interrupt_out);
931 max_endpoints = max(max_endpoints, (int)serial->num_ports);
932 serial->num_port_pointers = max_endpoints;
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100933 unlock_kernel();
934
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100935 dbg("%s - setting up %d port structures for this device",
936 __func__, max_endpoints);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937 for (i = 0; i < max_endpoints; ++i) {
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100938 port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939 if (!port)
940 goto probe_error;
Alan Cox4a90f092008-10-13 10:39:46 +0100941 tty_port_init(&port->port);
Alan Cox335f8512009-06-11 12:26:29 +0100942 port->port.ops = &serial_port_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 port->serial = serial;
Greg Kroah-Hartman507ca9b2005-04-23 12:49:16 -0700944 spin_lock_init(&port->lock);
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300945 mutex_init(&port->mutex);
David Howellsc4028952006-11-22 14:57:56 +0000946 INIT_WORK(&port->work, usb_serial_port_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947 serial->port[i] = port;
Alan Stern41bd34d2009-09-01 11:38:34 -0400948 port->dev.parent = &interface->dev;
949 port->dev.driver = NULL;
950 port->dev.bus = &usb_serial_bus_type;
951 port->dev.release = &port_release;
952 device_initialize(&port->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 }
954
955 /* set up the endpoint information */
956 for (i = 0; i < num_bulk_in; ++i) {
957 endpoint = bulk_in_endpoint[i];
958 port = serial->port[i];
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100959 port->read_urb = usb_alloc_urb(0, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 if (!port->read_urb) {
961 dev_err(&interface->dev, "No free urbs available\n");
962 goto probe_error;
963 }
964 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
965 port->bulk_in_size = buffer_size;
966 port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100967 port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 if (!port->bulk_in_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100969 dev_err(&interface->dev,
970 "Couldn't allocate bulk_in_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971 goto probe_error;
972 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100973 usb_fill_bulk_urb(port->read_urb, dev,
974 usb_rcvbulkpipe(dev,
975 endpoint->bEndpointAddress),
976 port->bulk_in_buffer, buffer_size,
977 serial->type->read_bulk_callback, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 }
979
980 for (i = 0; i < num_bulk_out; ++i) {
981 endpoint = bulk_out_endpoint[i];
982 port = serial->port[i];
983 port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
984 if (!port->write_urb) {
985 dev_err(&interface->dev, "No free urbs available\n");
986 goto probe_error;
987 }
988 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
989 port->bulk_out_size = buffer_size;
990 port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100991 port->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 if (!port->bulk_out_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100993 dev_err(&interface->dev,
994 "Couldn't allocate bulk_out_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995 goto probe_error;
996 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100997 usb_fill_bulk_urb(port->write_urb, dev,
998 usb_sndbulkpipe(dev,
999 endpoint->bEndpointAddress),
1000 port->bulk_out_buffer, buffer_size,
1001 serial->type->write_bulk_callback, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 }
1003
1004 if (serial->type->read_int_callback) {
1005 for (i = 0; i < num_interrupt_in; ++i) {
1006 endpoint = interrupt_in_endpoint[i];
1007 port = serial->port[i];
1008 port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
1009 if (!port->interrupt_in_urb) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001010 dev_err(&interface->dev,
1011 "No free urbs available\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 goto probe_error;
1013 }
1014 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001015 port->interrupt_in_endpointAddress =
1016 endpoint->bEndpointAddress;
1017 port->interrupt_in_buffer = kmalloc(buffer_size,
1018 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 if (!port->interrupt_in_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001020 dev_err(&interface->dev,
1021 "Couldn't allocate interrupt_in_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 goto probe_error;
1023 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001024 usb_fill_int_urb(port->interrupt_in_urb, dev,
1025 usb_rcvintpipe(dev,
1026 endpoint->bEndpointAddress),
1027 port->interrupt_in_buffer, buffer_size,
1028 serial->type->read_int_callback, port,
1029 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 }
1031 } else if (num_interrupt_in) {
1032 dbg("the device claims to support interrupt in transfers, but read_int_callback is not defined");
1033 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001034
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 if (serial->type->write_int_callback) {
1036 for (i = 0; i < num_interrupt_out; ++i) {
1037 endpoint = interrupt_out_endpoint[i];
1038 port = serial->port[i];
1039 port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
1040 if (!port->interrupt_out_urb) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001041 dev_err(&interface->dev,
1042 "No free urbs available\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 goto probe_error;
1044 }
1045 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
1046 port->interrupt_out_size = buffer_size;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001047 port->interrupt_out_endpointAddress =
1048 endpoint->bEndpointAddress;
1049 port->interrupt_out_buffer = kmalloc(buffer_size,
1050 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 if (!port->interrupt_out_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001052 dev_err(&interface->dev,
1053 "Couldn't allocate interrupt_out_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 goto probe_error;
1055 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001056 usb_fill_int_urb(port->interrupt_out_urb, dev,
1057 usb_sndintpipe(dev,
1058 endpoint->bEndpointAddress),
1059 port->interrupt_out_buffer, buffer_size,
1060 serial->type->write_int_callback, port,
1061 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 }
1063 } else if (num_interrupt_out) {
1064 dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined");
1065 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001066
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 /* if this device type has an attach function, call it */
1068 if (type->attach) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -07001069 if (!try_module_get(type->driver.owner)) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001070 dev_err(&interface->dev,
1071 "module get failed, exiting\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 goto probe_error;
1073 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001074 retval = type->attach(serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -07001075 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 if (retval < 0)
1077 goto probe_error;
1078 if (retval > 0) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001079 /* quietly accept this device, but don't bind to a
1080 serial port as it's about to disappear */
Alan Stern0a3c8542009-05-27 11:25:52 -04001081 serial->num_ports = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 goto exit;
1083 }
1084 }
1085
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001086 if (get_free_serial(serial, num_ports, &minor) == NULL) {
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001087 dev_err(&interface->dev, "No more free serial devices\n");
1088 goto probe_error;
1089 }
Oliver Neukumc744f992007-02-26 15:43:00 +01001090 serial->minor = minor;
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001091
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 /* register all of the individual ports with the driver core */
1093 for (i = 0; i < num_ports; ++i) {
1094 port = serial->port[i];
Kay Sievers0031a062008-05-02 06:02:41 +02001095 dev_set_name(&port->dev, "ttyUSB%d", port->number);
Kay Sievers7071a3c2008-05-02 06:02:41 +02001096 dbg ("%s - registering %s", __func__, dev_name(&port->dev));
Alan Sternc706ebd2009-06-02 11:54:11 -04001097 port->dev_state = PORT_REGISTERING;
Alan Stern41bd34d2009-09-01 11:38:34 -04001098 retval = device_add(&port->dev);
Alan Sternc706ebd2009-06-02 11:54:11 -04001099 if (retval) {
Greg Kroah-Hartman13f4db92006-08-28 11:43:25 -07001100 dev_err(&port->dev, "Error registering port device, "
1101 "continuing\n");
Alan Sternc706ebd2009-06-02 11:54:11 -04001102 port->dev_state = PORT_UNREGISTERED;
1103 } else {
1104 port->dev_state = PORT_REGISTERED;
1105 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106 }
1107
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001108 usb_serial_console_init(debug, minor);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109
1110exit:
1111 /* success */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001112 usb_set_intfdata(interface, serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 return 0;
1114
1115probe_error:
Alan Stern41bd34d2009-09-01 11:38:34 -04001116 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 return -EIO;
1118}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001119EXPORT_SYMBOL_GPL(usb_serial_probe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120
1121void usb_serial_disconnect(struct usb_interface *interface)
1122{
1123 int i;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001124 struct usb_serial *serial = usb_get_intfdata(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 struct device *dev = &interface->dev;
1126 struct usb_serial_port *port;
1127
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +02001128 usb_serial_console_disconnect(serial);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001129 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001131 mutex_lock(&serial->disc_mutex);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001132 usb_set_intfdata(interface, NULL);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001133 /* must set a flag, to signal subdrivers */
1134 serial->disconnected = 1;
Alan Stern2d931482009-04-14 11:31:02 -04001135 mutex_unlock(&serial->disc_mutex);
1136
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001137 for (i = 0; i < serial->num_ports; ++i) {
1138 port = serial->port[i];
1139 if (port) {
Alan Cox4a90f092008-10-13 10:39:46 +01001140 struct tty_struct *tty = tty_port_tty_get(&port->port);
1141 if (tty) {
Alan Coxd2b39182009-09-19 13:13:23 -07001142 tty_vhangup(tty);
Alan Cox4a90f092008-10-13 10:39:46 +01001143 tty_kref_put(tty);
1144 }
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001145 kill_traffic(port);
Alan Stern2d931482009-04-14 11:31:02 -04001146 cancel_work_sync(&port->work);
Alan Sternc706ebd2009-06-02 11:54:11 -04001147 if (port->dev_state == PORT_REGISTERED) {
1148
1149 /* Make sure the port is bound so that the
1150 * driver's port_remove method is called.
1151 */
1152 if (!port->dev.driver) {
1153 int rc;
1154
1155 port->dev.driver =
1156 &serial->type->driver;
1157 rc = device_bind_driver(&port->dev);
1158 }
1159 port->dev_state = PORT_UNREGISTERING;
1160 device_del(&port->dev);
1161 port->dev_state = PORT_UNREGISTERED;
1162 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 }
Alan Sternf9c99bb2009-06-02 11:53:55 -04001165 serial->type->disconnect(serial);
Alan Stern2d931482009-04-14 11:31:02 -04001166
Alan Stern41bd34d2009-09-01 11:38:34 -04001167 /* let the last holder of this object cause it to be cleaned up */
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001168 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 dev_info(dev, "device disconnected\n");
1170}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001171EXPORT_SYMBOL_GPL(usb_serial_disconnect);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172
Oliver Neukumec225592007-04-27 20:54:57 +02001173int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
1174{
1175 struct usb_serial *serial = usb_get_intfdata(intf);
1176 struct usb_serial_port *port;
1177 int i, r = 0;
1178
Oliver Neukumf8bece82009-02-05 16:54:25 +01001179 serial->suspending = 1;
1180
Oliver Neukume31c1882007-07-23 08:58:39 +02001181 for (i = 0; i < serial->num_ports; ++i) {
1182 port = serial->port[i];
1183 if (port)
1184 kill_traffic(port);
Oliver Neukumec225592007-04-27 20:54:57 +02001185 }
1186
1187 if (serial->type->suspend)
Oliver Neukume31c1882007-07-23 08:58:39 +02001188 r = serial->type->suspend(serial, message);
Oliver Neukumec225592007-04-27 20:54:57 +02001189
1190 return r;
1191}
1192EXPORT_SYMBOL(usb_serial_suspend);
1193
1194int usb_serial_resume(struct usb_interface *intf)
1195{
1196 struct usb_serial *serial = usb_get_intfdata(intf);
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001197 int rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001198
Oliver Neukumf8bece82009-02-05 16:54:25 +01001199 serial->suspending = 0;
Sarah Sharp8abaee22007-10-25 10:58:43 -07001200 if (serial->type->resume)
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001201 rv = serial->type->resume(serial);
1202 else
1203 rv = usb_serial_generic_resume(serial);
Oliver Neukumf8bece82009-02-05 16:54:25 +01001204
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001205 return rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001206}
1207EXPORT_SYMBOL(usb_serial_resume);
1208
Jeff Dikeb68e31d2006-10-02 02:17:18 -07001209static const struct tty_operations serial_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210 .open = serial_open,
1211 .close = serial_close,
1212 .write = serial_write,
Alan Cox335f8512009-06-11 12:26:29 +01001213 .hangup = serial_hangup,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 .write_room = serial_write_room,
1215 .ioctl = serial_ioctl,
1216 .set_termios = serial_set_termios,
1217 .throttle = serial_throttle,
1218 .unthrottle = serial_unthrottle,
1219 .break_ctl = serial_break,
1220 .chars_in_buffer = serial_chars_in_buffer,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 .tiocmget = serial_tiocmget,
1222 .tiocmset = serial_tiocmset,
Alan Stern74556122009-09-01 11:39:40 -04001223 .shutdown = serial_release,
Alan Coxfe1ae7f2009-09-19 13:13:33 -07001224 .install = serial_install,
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -07001225 .proc_fops = &serial_proc_fops,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226};
1227
Alan Cox335f8512009-06-11 12:26:29 +01001228
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229struct tty_driver *usb_serial_tty_driver;
1230
1231static int __init usb_serial_init(void)
1232{
1233 int i;
1234 int result;
1235
1236 usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS);
1237 if (!usb_serial_tty_driver)
1238 return -ENOMEM;
1239
1240 /* Initialize our global data */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001241 for (i = 0; i < SERIAL_TTY_MINORS; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 serial_table[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243
1244 result = bus_register(&usb_serial_bus_type);
1245 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001246 printk(KERN_ERR "usb-serial: %s - registering bus driver "
1247 "failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248 goto exit_bus;
1249 }
1250
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 usb_serial_tty_driver->owner = THIS_MODULE;
1252 usb_serial_tty_driver->driver_name = "usbserial";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253 usb_serial_tty_driver->name = "ttyUSB";
1254 usb_serial_tty_driver->major = SERIAL_TTY_MAJOR;
1255 usb_serial_tty_driver->minor_start = 0;
1256 usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
1257 usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001258 usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW |
1259 TTY_DRIVER_DYNAMIC_DEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260 usb_serial_tty_driver->init_termios = tty_std_termios;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001261 usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD
1262 | HUPCL | CLOCAL;
Alan Coxa5b6f602008-04-08 17:16:06 +01001263 usb_serial_tty_driver->init_termios.c_ispeed = 9600;
1264 usb_serial_tty_driver->init_termios.c_ospeed = 9600;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265 tty_set_operations(usb_serial_tty_driver, &serial_ops);
1266 result = tty_register_driver(usb_serial_tty_driver);
1267 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001268 printk(KERN_ERR "usb-serial: %s - tty_register_driver failed\n",
1269 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270 goto exit_reg_driver;
1271 }
1272
1273 /* register the USB driver */
1274 result = usb_register(&usb_serial_driver);
1275 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001276 printk(KERN_ERR "usb-serial: %s - usb_register failed\n",
1277 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 goto exit_tty;
1279 }
1280
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001281 /* register the generic driver, if we should */
1282 result = usb_serial_generic_register(debug);
1283 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001284 printk(KERN_ERR "usb-serial: %s - registering generic "
1285 "driver failed\n", __func__);
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001286 goto exit_generic;
1287 }
1288
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001289 printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290
1291 return result;
1292
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001293exit_generic:
1294 usb_deregister(&usb_serial_driver);
1295
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296exit_tty:
1297 tty_unregister_driver(usb_serial_tty_driver);
1298
1299exit_reg_driver:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 bus_unregister(&usb_serial_bus_type);
1301
1302exit_bus:
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001303 printk(KERN_ERR "usb-serial: %s - returning with error %d\n",
1304 __func__, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305 put_tty_driver(usb_serial_tty_driver);
1306 return result;
1307}
1308
1309
1310static void __exit usb_serial_exit(void)
1311{
1312 usb_serial_console_exit();
1313
1314 usb_serial_generic_deregister();
1315
1316 usb_deregister(&usb_serial_driver);
1317 tty_unregister_driver(usb_serial_tty_driver);
1318 put_tty_driver(usb_serial_tty_driver);
1319 bus_unregister(&usb_serial_bus_type);
1320}
1321
1322
1323module_init(usb_serial_init);
1324module_exit(usb_serial_exit);
1325
1326#define set_to_generic_if_null(type, function) \
1327 do { \
1328 if (!type->function) { \
1329 type->function = usb_serial_generic_##function; \
1330 dbg("Had to override the " #function \
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001331 " usb serial operation with the generic one.");\
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332 } \
1333 } while (0)
1334
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001335static void fixup_generic(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336{
1337 set_to_generic_if_null(device, open);
1338 set_to_generic_if_null(device, write);
1339 set_to_generic_if_null(device, close);
1340 set_to_generic_if_null(device, write_room);
1341 set_to_generic_if_null(device, chars_in_buffer);
1342 set_to_generic_if_null(device, read_bulk_callback);
1343 set_to_generic_if_null(device, write_bulk_callback);
Alan Sternf9c99bb2009-06-02 11:53:55 -04001344 set_to_generic_if_null(device, disconnect);
1345 set_to_generic_if_null(device, release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346}
1347
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001348int usb_serial_register(struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001350 /* must be called with BKL held */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 int retval;
1352
Dave Younge4abe662009-02-14 21:21:13 +08001353 if (usb_disabled())
1354 return -ENODEV;
1355
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001356 fixup_generic(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001358 if (!driver->description)
1359 driver->description = driver->driver.name;
1360
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 /* Add this device to our list of devices */
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001362 list_add(&driver->driver_list, &usb_serial_driver_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001364 retval = usb_serial_bus_register(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 if (retval) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001366 printk(KERN_ERR "usb-serial: problem %d when registering "
1367 "driver %s\n", retval, driver->description);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001368 list_del(&driver->driver_list);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001369 } else
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001370 printk(KERN_INFO "USB Serial support registered for %s\n",
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001371 driver->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372
1373 return retval;
1374}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001375EXPORT_SYMBOL_GPL(usb_serial_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376
1377
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001378void usb_serial_deregister(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001380 /* must be called with BKL held */
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001381 printk(KERN_INFO "USB Serial deregistering driver %s\n",
1382 device->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383 list_del(&device->driver_list);
1384 usb_serial_bus_deregister(device);
1385}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386EXPORT_SYMBOL_GPL(usb_serial_deregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387
1388/* Module information */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001389MODULE_AUTHOR(DRIVER_AUTHOR);
1390MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391MODULE_LICENSE("GPL");
1392
1393module_param(debug, bool, S_IRUGO | S_IWUSR);
1394MODULE_PARM_DESC(debug, "Debug enabled or not");