blob: 87802ea8bbc8241927e1b56809ef6c72abac00f7 [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.
190 */
191static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
192{
193 int idx = tty->index;
194 struct usb_serial *serial;
195 int retval;
196
197 /* If the termios setup has yet to be done */
198 if (tty->driver->termios[idx] == NULL) {
199 /* perform the standard setup */
200 retval = tty_init_termios(tty);
201 if (retval)
202 return retval;
203 /* allow the driver to update it */
204 serial = usb_serial_get_by_index(tty->index);
Alan Stern8bc2c1b2009-09-01 11:38:59 -0400205 if (serial) {
206 if (serial->type->init_termios)
207 serial->type->init_termios(tty);
208 usb_serial_put(serial);
209 mutex_unlock(&serial->disc_mutex);
210 }
Alan Sternf5b09532009-09-01 11:38:44 -0400211 }
212 /* Final install (we use the default method) */
213 tty_driver_kref_get(driver);
214 tty->count++;
215 driver->ttys[idx] = tty;
216 return 0;
217}
218
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100219static int serial_open (struct tty_struct *tty, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220{
221 struct usb_serial *serial;
222 struct usb_serial_port *port;
223 unsigned int portNumber;
Alan Stern2d931482009-04-14 11:31:02 -0400224 int retval = 0;
Alan Coxc56d3002009-07-28 00:34:58 +0100225 int first = 0;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100226
Harvey Harrison441b62c2008-03-03 16:08:34 -0800227 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228
229 /* get the serial object associated with this tty pointer */
230 serial = usb_serial_get_by_index(tty->index);
231 if (!serial) {
232 tty->driver_data = NULL;
233 return -ENODEV;
234 }
235
236 portNumber = tty->index - serial->minor;
237 port = serial->port[portNumber];
Alan Stern2d931482009-04-14 11:31:02 -0400238 if (!port || serial->disconnected)
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300239 retval = -ENODEV;
Alan Stern2d931482009-04-14 11:31:02 -0400240 /*
241 * Note: Our locking order requirement does not allow port->mutex
242 * to be acquired while serial->disc_mutex is held.
243 */
244 mutex_unlock(&serial->disc_mutex);
245 if (retval)
246 goto bailout_serial_put;
James Woodcock331879f2009-02-11 15:06:53 +0000247
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300248 if (mutex_lock_interruptible(&port->mutex)) {
249 retval = -ERESTARTSYS;
Alan Stern41bd34d2009-09-01 11:38:34 -0400250 goto bailout_serial_put;
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300251 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100252
Alan Cox95da3102008-07-22 11:09:07 +0100253 ++port->port.count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254
Paul Fulghumca854852006-04-13 22:28:17 +0200255 /* set up our port structure making the tty driver
256 * remember our port object, and us it */
257 tty->driver_data = port;
Alan Cox4a90f092008-10-13 10:39:46 +0100258 tty_port_tty_set(&port->port, tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259
Jason Wessel6e406122009-06-22 11:32:20 -0500260 /* If the console is attached, the device is already open */
261 if (port->port.count == 1 && !port->console) {
Alan Coxc56d3002009-07-28 00:34:58 +0100262 first = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 /* lock this module before we call it
264 * this may fail, which means we must bail out,
265 * safe because we are called with BKL held */
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700266 if (!try_module_get(serial->type->driver.owner)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267 retval = -ENODEV;
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300268 goto bailout_mutex_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269 }
270
Alan Stern2d931482009-04-14 11:31:02 -0400271 mutex_lock(&serial->disc_mutex);
272 if (serial->disconnected)
273 retval = -ENODEV;
274 else
275 retval = usb_autopm_get_interface(serial->interface);
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800276 if (retval)
277 goto bailout_module_put;
Alan Stern2d931482009-04-14 11:31:02 -0400278
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100279 /* only call the device specific open if this
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 * is the first time the port is opened */
Alan Coxa509a7e2009-09-19 13:13:26 -0700281 retval = serial->type->open(tty, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 if (retval)
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800283 goto bailout_interface_put;
Alan Stern2d931482009-04-14 11:31:02 -0400284 mutex_unlock(&serial->disc_mutex);
Alan Coxc56d3002009-07-28 00:34:58 +0100285 set_bit(ASYNCB_INITIALIZED, &port->port.flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 }
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300287 mutex_unlock(&port->mutex);
Alan Cox335f8512009-06-11 12:26:29 +0100288 /* Now do the correct tty layer semantics */
289 retval = tty_port_block_til_ready(&port->port, tty, filp);
Alan Coxc56d3002009-07-28 00:34:58 +0100290 if (retval == 0) {
291 if (!first)
292 usb_serial_put(serial);
Alan Cox335f8512009-06-11 12:26:29 +0100293 return 0;
Alan Coxc56d3002009-07-28 00:34:58 +0100294 }
295 mutex_lock(&port->mutex);
296 if (first == 0)
297 goto bailout_mutex_unlock;
298 /* Undo the initial port actions */
299 mutex_lock(&serial->disc_mutex);
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800300bailout_interface_put:
301 usb_autopm_put_interface(serial->interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302bailout_module_put:
Alan Stern2d931482009-04-14 11:31:02 -0400303 mutex_unlock(&serial->disc_mutex);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700304 module_put(serial->type->driver.owner);
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300305bailout_mutex_unlock:
Alan Cox95da3102008-07-22 11:09:07 +0100306 port->port.count = 0;
Frank Gevaertsb059c812006-06-14 15:52:05 +0200307 tty->driver_data = NULL;
Alan Cox4a90f092008-10-13 10:39:46 +0100308 tty_port_tty_set(&port->port, NULL);
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300309 mutex_unlock(&port->mutex);
Alan Stern2d931482009-04-14 11:31:02 -0400310bailout_serial_put:
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200311 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312 return retval;
313}
314
Alan Cox335f8512009-06-11 12:26:29 +0100315/**
Alan Sternf5b09532009-09-01 11:38:44 -0400316 * serial_do_down - shut down hardware
317 * @port: port to shut down
Alan Cox335f8512009-06-11 12:26:29 +0100318 *
Alan Sternf5b09532009-09-01 11:38:44 -0400319 * Shut down a USB serial port unless it is the console. We never
320 * shut down the console hardware as it will always be in use.
Alan Cox335f8512009-06-11 12:26:29 +0100321 */
322static void serial_do_down(struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323{
Alan Cox335f8512009-06-11 12:26:29 +0100324 struct usb_serial_driver *drv = port->serial->type;
Alan Stern2d931482009-04-14 11:31:02 -0400325 struct usb_serial *serial;
326 struct module *owner;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327
Alan Sternf5b09532009-09-01 11:38:44 -0400328 /*
329 * The console is magical. Do not hang up the console hardware
330 * or there will be tears.
331 */
Alan Cox335f8512009-06-11 12:26:29 +0100332 if (port->console)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 return;
334
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300335 mutex_lock(&port->mutex);
Alan Stern2d931482009-04-14 11:31:02 -0400336 serial = port->serial;
337 owner = serial->type->driver.owner;
Luiz Fernando Capitulino8a4613f2005-11-28 19:16:07 -0200338
Alan Cox335f8512009-06-11 12:26:29 +0100339 if (drv->close)
340 drv->close(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300342 mutex_unlock(&port->mutex);
Alan Cox335f8512009-06-11 12:26:29 +0100343}
344
Alan Sternf5b09532009-09-01 11:38:44 -0400345static void serial_hangup(struct tty_struct *tty)
Alan Cox335f8512009-06-11 12:26:29 +0100346{
Alan Cox4455e342009-09-19 13:13:24 -0700347 struct usb_serial_port *port = tty->driver_data;
Alan Sternf5b09532009-09-01 11:38:44 -0400348 serial_do_down(port);
349 tty_port_hangup(&port->port);
350 /* We must not free port yet - the USB serial layer depends on it's
351 continued existence */
Alan Cox335f8512009-06-11 12:26:29 +0100352}
353
354static void serial_close(struct tty_struct *tty, struct file *filp)
355{
356 struct usb_serial_port *port = tty->driver_data;
357
Thadeu Lima de Souza Cascardof4fa4462009-06-25 14:41:37 +0100358 if (!port)
359 return;
360
Alan Cox335f8512009-06-11 12:26:29 +0100361 dbg("%s - port %d", __func__, port->number);
362
Alan Cox335f8512009-06-11 12:26:29 +0100363 if (tty_port_close_start(&port->port, tty, filp) == 0)
364 return;
Alan Sternf5b09532009-09-01 11:38:44 -0400365 serial_do_down(port);
Alan Cox335f8512009-06-11 12:26:29 +0100366 tty_port_close_end(&port->port, tty);
367 tty_port_tty_set(&port->port, NULL);
Alan Cox4455e342009-09-19 13:13:24 -0700368
Alan Cox335f8512009-06-11 12:26:29 +0100369}
370
Alan Sternf5b09532009-09-01 11:38:44 -0400371/**
372 * serial_do_free - free resources post close/hangup
373 * @port: port to free up
374 *
375 * Do the resource freeing and refcount dropping for the port.
376 * Avoid freeing the console.
377 *
378 * Called when the last tty kref is dropped.
379 */
380static void serial_do_free(struct tty_struct *tty)
Alan Cox335f8512009-06-11 12:26:29 +0100381{
382 struct usb_serial_port *port = tty->driver_data;
Alan Sternf5b09532009-09-01 11:38:44 -0400383 struct usb_serial *serial;
384 struct module *owner;
385
386 /* The console is magical. Do not hang up the console hardware
387 * or there will be tears.
388 */
389 if (port == NULL || port->console)
390 return;
391
392 serial = port->serial;
393 owner = serial->type->driver.owner;
394
395 mutex_lock(&serial->disc_mutex);
396 if (!serial->disconnected)
397 usb_autopm_put_interface(serial->interface);
398 mutex_unlock(&serial->disc_mutex);
399
400 usb_serial_put(serial);
401 module_put(owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402}
403
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100404static int serial_write(struct tty_struct *tty, const unsigned char *buf,
405 int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200407 struct usb_serial_port *port = tty->driver_data;
Oliver Neukum3ff4fd92007-01-13 07:32:27 +0100408 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409
Alan Coxf34d7a52008-04-30 00:54:13 -0700410 if (port->serial->dev->state == USB_STATE_NOTATTACHED)
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200411 goto exit;
412
Harvey Harrison441b62c2008-03-03 16:08:34 -0800413 dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414
Alan Cox95da3102008-07-22 11:09:07 +0100415 /* count is managed under the mutex lock for the tty so cannot
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100416 drop to zero until after the last close completes */
Alan Cox95da3102008-07-22 11:09:07 +0100417 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418
419 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100420 retval = port->serial->type->write(tty, port, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421
422exit:
423 return retval;
424}
425
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100426static int serial_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200428 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800429 dbg("%s - port %d", __func__, port->number);
Alan Cox95da3102008-07-22 11:09:07 +0100430 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100432 return port->serial->type->write_room(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433}
434
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100435static int serial_chars_in_buffer(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200437 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800438 dbg("%s = port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439
Alan Coxeff69372009-01-02 13:47:06 +0000440 /* if the device was unplugged then any remaining characters
441 fell out of the connector ;) */
442 if (port->serial->disconnected)
443 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100445 return port->serial->type->chars_in_buffer(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446}
447
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100448static void serial_throttle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200450 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800451 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452
Alan Cox95da3102008-07-22 11:09:07 +0100453 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 /* pass on to the driver specific version of this function */
455 if (port->serial->type->throttle)
Alan Cox95da3102008-07-22 11:09:07 +0100456 port->serial->type->throttle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457}
458
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100459static void serial_unthrottle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200461 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800462 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463
Alan Cox95da3102008-07-22 11:09:07 +0100464 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465 /* pass on to the driver specific version of this function */
466 if (port->serial->type->unthrottle)
Alan Cox95da3102008-07-22 11:09:07 +0100467 port->serial->type->unthrottle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468}
469
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100470static int serial_ioctl(struct tty_struct *tty, struct file *file,
471 unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200473 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 int retval = -ENODEV;
475
Harvey Harrison441b62c2008-03-03 16:08:34 -0800476 dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477
Alan Cox95da3102008-07-22 11:09:07 +0100478 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100480 /* pass on to the driver specific version of this function
481 if it is available */
Alan Coxf34d7a52008-04-30 00:54:13 -0700482 if (port->serial->type->ioctl) {
Alan Cox95da3102008-07-22 11:09:07 +0100483 retval = port->serial->type->ioctl(tty, file, cmd, arg);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100484 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 retval = -ENOIOCTLCMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 return retval;
487}
488
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100489static void serial_set_termios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200491 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800492 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493
Alan Cox95da3102008-07-22 11:09:07 +0100494 WARN_ON(!port->port.count);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100495 /* pass on to the driver specific version of this function
496 if it is available */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 if (port->serial->type->set_termios)
Alan Cox95da3102008-07-22 11:09:07 +0100498 port->serial->type->set_termios(tty, port, old);
Alan Cox33785092007-10-18 01:24:22 -0700499 else
500 tty_termios_copy_hw(tty->termios, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501}
502
Alan Cox9e989662008-07-22 11:18:03 +0100503static int serial_break(struct tty_struct *tty, int break_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200505 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506
Harvey Harrison441b62c2008-03-03 16:08:34 -0800507 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508
Alan Cox95da3102008-07-22 11:09:07 +0100509 WARN_ON(!port->port.count);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100510 /* pass on to the driver specific version of this function
511 if it is available */
Alan Cox6b447f042009-01-02 13:48:56 +0000512 if (port->serial->type->break_ctl)
Alan Cox95da3102008-07-22 11:09:07 +0100513 port->serial->type->break_ctl(tty, break_state);
Alan Cox9e989662008-07-22 11:18:03 +0100514 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515}
516
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700517static int serial_proc_show(struct seq_file *m, void *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518{
519 struct usb_serial *serial;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 char tmp[40];
522
Harvey Harrison441b62c2008-03-03 16:08:34 -0800523 dbg("%s", __func__);
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700524 seq_puts(m, "usbserinfo:1.0 driver:2.0\n");
525 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 serial = usb_serial_get_by_index(i);
527 if (serial == NULL)
528 continue;
529
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700530 seq_printf(m, "%d:", i);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700531 if (serial->type->driver.owner)
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700532 seq_printf(m, " module:%s",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100533 module_name(serial->type->driver.owner));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700534 seq_printf(m, " name:\"%s\"",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100535 serial->type->description);
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700536 seq_printf(m, " vendor:%04x product:%04x",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100537 le16_to_cpu(serial->dev->descriptor.idVendor),
538 le16_to_cpu(serial->dev->descriptor.idProduct));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700539 seq_printf(m, " num_ports:%d", serial->num_ports);
540 seq_printf(m, " port:%d", i - serial->minor + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 usb_make_path(serial->dev, tmp, sizeof(tmp));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700542 seq_printf(m, " path:%s", tmp);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100543
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700544 seq_putc(m, '\n');
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200545 usb_serial_put(serial);
Alan Stern8bc2c1b2009-09-01 11:38:59 -0400546 mutex_unlock(&serial->disc_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 }
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700548 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549}
550
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700551static int serial_proc_open(struct inode *inode, struct file *file)
552{
553 return single_open(file, serial_proc_show, NULL);
554}
555
556static const struct file_operations serial_proc_fops = {
557 .owner = THIS_MODULE,
558 .open = serial_proc_open,
559 .read = seq_read,
560 .llseek = seq_lseek,
561 .release = single_release,
562};
563
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100564static int serial_tiocmget(struct tty_struct *tty, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200566 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567
Harvey Harrison441b62c2008-03-03 16:08:34 -0800568 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569
Alan Cox95da3102008-07-22 11:09:07 +0100570 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571 if (port->serial->type->tiocmget)
Alan Cox95da3102008-07-22 11:09:07 +0100572 return port->serial->type->tiocmget(tty, file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 return -EINVAL;
574}
575
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100576static int serial_tiocmset(struct tty_struct *tty, struct file *file,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 unsigned int set, unsigned int clear)
578{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200579 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580
Harvey Harrison441b62c2008-03-03 16:08:34 -0800581 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582
Alan Cox95da3102008-07-22 11:09:07 +0100583 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584 if (port->serial->type->tiocmset)
Alan Cox95da3102008-07-22 11:09:07 +0100585 return port->serial->type->tiocmset(tty, file, set, clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 return -EINVAL;
587}
588
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700589/*
590 * We would be calling tty_wakeup here, but unfortunately some line
591 * disciplines have an annoying habit of calling tty->write from
592 * the write wakeup callback (e.g. n_hdlc.c).
593 */
594void usb_serial_port_softint(struct usb_serial_port *port)
595{
596 schedule_work(&port->work);
597}
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100598EXPORT_SYMBOL_GPL(usb_serial_port_softint);
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700599
David Howellsc4028952006-11-22 14:57:56 +0000600static void usb_serial_port_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601{
David Howellsc4028952006-11-22 14:57:56 +0000602 struct usb_serial_port *port =
603 container_of(work, struct usb_serial_port, work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 struct tty_struct *tty;
605
Harvey Harrison441b62c2008-03-03 16:08:34 -0800606 dbg("%s - port %d", __func__, port->number);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100607
Alan Cox4a90f092008-10-13 10:39:46 +0100608 tty = tty_port_tty_get(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 if (!tty)
610 return;
611
612 tty_wakeup(tty);
Alan Cox4a90f092008-10-13 10:39:46 +0100613 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614}
615
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100616static void kill_traffic(struct usb_serial_port *port)
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700617{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 usb_kill_urb(port->write_urb);
Oliver Neukum5adceac2007-08-17 14:01:38 +0200620 /*
621 * This is tricky.
622 * Some drivers submit the read_urb in the
623 * handler for the write_urb or vice versa
624 * this order determines the order in which
625 * usb_kill_urb() must be used to reliably
626 * kill the URBs. As it is unknown here,
627 * both orders must be used in turn.
628 * The call below is not redundant.
629 */
630 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 usb_kill_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 usb_kill_urb(port->interrupt_out_urb);
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100633}
634
Alan Stern41bd34d2009-09-01 11:38:34 -0400635static void port_release(struct device *dev)
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100636{
Alan Stern41bd34d2009-09-01 11:38:34 -0400637 struct usb_serial_port *port = to_usb_serial_port(dev);
638
639 dbg ("%s - %s", __func__, dev_name(dev));
640
Alan Stern2d931482009-04-14 11:31:02 -0400641 /*
642 * Stop all the traffic before cancelling the work, so that
643 * nobody will restart it by calling usb_serial_port_softint.
644 */
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100645 kill_traffic(port);
Alan Stern2d931482009-04-14 11:31:02 -0400646 cancel_work_sync(&port->work);
647
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100648 usb_free_urb(port->read_urb);
649 usb_free_urb(port->write_urb);
650 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651 usb_free_urb(port->interrupt_out_urb);
652 kfree(port->bulk_in_buffer);
653 kfree(port->bulk_out_buffer);
654 kfree(port->interrupt_in_buffer);
655 kfree(port->interrupt_out_buffer);
656 kfree(port);
657}
658
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100659static struct usb_serial *create_serial(struct usb_device *dev,
660 struct usb_interface *interface,
661 struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662{
663 struct usb_serial *serial;
664
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100665 serial = kzalloc(sizeof(*serial), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 if (!serial) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800667 dev_err(&dev->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668 return NULL;
669 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 serial->dev = usb_get_dev(dev);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700671 serial->type = driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 serial->interface = interface;
673 kref_init(&serial->kref);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +0100674 mutex_init(&serial->disc_mutex);
Alan Stern0282b7f2008-07-29 12:01:04 -0400675 serial->minor = SERIAL_TTY_NO_MINOR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676
677 return serial;
678}
679
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100680static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf,
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100681 struct usb_serial_driver *drv)
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100682{
683 struct usb_dynid *dynid;
684
685 spin_lock(&drv->dynids.lock);
686 list_for_each_entry(dynid, &drv->dynids.list, node) {
687 if (usb_match_one_id(intf, &dynid->id)) {
688 spin_unlock(&drv->dynids.lock);
689 return &dynid->id;
690 }
691 }
692 spin_unlock(&drv->dynids.lock);
693 return NULL;
694}
695
696static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv,
697 struct usb_interface *intf)
698{
699 const struct usb_device_id *id;
700
701 id = usb_match_id(intf, drv->id_table);
702 if (id) {
703 dbg("static descriptor matches");
704 goto exit;
705 }
706 id = match_dynamic_id(intf, drv);
707 if (id)
708 dbg("dynamic descriptor matches");
709exit:
710 return id;
711}
712
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100713static struct usb_serial_driver *search_serial_device(
714 struct usb_interface *iface)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716 const struct usb_device_id *id;
Alan Stern063a2da2007-10-10 16:24:06 -0400717 struct usb_serial_driver *drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718
Adrian Bunk93b1fae2006-01-10 00:13:33 +0100719 /* Check if the usb id matches a known device */
Alan Stern063a2da2007-10-10 16:24:06 -0400720 list_for_each_entry(drv, &usb_serial_driver_list, driver_list) {
721 id = get_iface_id(drv, iface);
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100722 if (id)
Alan Stern063a2da2007-10-10 16:24:06 -0400723 return drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 }
725
726 return NULL;
727}
728
Alan Cox335f8512009-06-11 12:26:29 +0100729static int serial_carrier_raised(struct tty_port *port)
730{
731 struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
732 struct usb_serial_driver *drv = p->serial->type;
733 if (drv->carrier_raised)
734 return drv->carrier_raised(p);
735 /* No carrier control - don't block */
736 return 1;
737}
738
739static void serial_dtr_rts(struct tty_port *port, int on)
740{
741 struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
742 struct usb_serial_driver *drv = p->serial->type;
743 if (drv->dtr_rts)
744 drv->dtr_rts(p, on);
745}
746
747static const struct tty_port_operations serial_port_ops = {
748 .carrier_raised = serial_carrier_raised,
749 .dtr_rts = serial_dtr_rts,
750};
751
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752int usb_serial_probe(struct usb_interface *interface,
753 const struct usb_device_id *id)
754{
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100755 struct usb_device *dev = interface_to_usbdev(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 struct usb_serial *serial = NULL;
757 struct usb_serial_port *port;
758 struct usb_host_interface *iface_desc;
759 struct usb_endpoint_descriptor *endpoint;
760 struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS];
761 struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS];
762 struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];
763 struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700764 struct usb_serial_driver *type = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 int retval;
Andre Hauptdd9ca5d2008-06-18 15:56:00 +0200766 unsigned int minor;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767 int buffer_size;
768 int i;
769 int num_interrupt_in = 0;
770 int num_interrupt_out = 0;
771 int num_bulk_in = 0;
772 int num_bulk_out = 0;
773 int num_ports = 0;
774 int max_endpoints;
775
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100776 lock_kernel(); /* guard against unloading a serial driver module */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777 type = search_serial_device(interface);
778 if (!type) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100779 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 dbg("none matched");
781 return -ENODEV;
782 }
783
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100784 serial = create_serial(dev, interface, type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785 if (!serial) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100786 unlock_kernel();
Harvey Harrison441b62c2008-03-03 16:08:34 -0800787 dev_err(&interface->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 return -ENOMEM;
789 }
790
791 /* if this device type has a probe function, call it */
792 if (type->probe) {
793 const struct usb_device_id *id;
794
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700795 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100796 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100797 dev_err(&interface->dev,
798 "module get failed, exiting\n");
799 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 return -EIO;
801 }
802
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100803 id = get_iface_id(type, interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 retval = type->probe(serial, id);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700805 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806
807 if (retval) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100808 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100809 dbg("sub driver rejected device");
810 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 return retval;
812 }
813 }
814
815 /* descriptor matches, let's find the endpoints needed */
816 /* check out the endpoints */
817 iface_desc = interface->cur_altsetting;
818 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
819 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700820
821 if (usb_endpoint_is_bulk_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 /* we found a bulk in endpoint */
823 dbg("found bulk in on endpoint %d", i);
824 bulk_in_endpoint[num_bulk_in] = endpoint;
825 ++num_bulk_in;
826 }
827
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700828 if (usb_endpoint_is_bulk_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 /* we found a bulk out endpoint */
830 dbg("found bulk out on endpoint %d", i);
831 bulk_out_endpoint[num_bulk_out] = endpoint;
832 ++num_bulk_out;
833 }
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700834
835 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 /* we found a interrupt in endpoint */
837 dbg("found interrupt in on endpoint %d", i);
838 interrupt_in_endpoint[num_interrupt_in] = endpoint;
839 ++num_interrupt_in;
840 }
841
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700842 if (usb_endpoint_is_int_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 /* we found an interrupt out endpoint */
844 dbg("found interrupt out on endpoint %d", i);
845 interrupt_out_endpoint[num_interrupt_out] = endpoint;
846 ++num_interrupt_out;
847 }
848 }
849
850#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100851 /* BEGIN HORRIBLE HACK FOR PL2303 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 /* this is needed due to the looney way its endpoints are set up */
853 if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&
854 (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||
855 ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) &&
Johannes Steingraeber8fd80132006-09-16 16:17:34 +0200856 (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) ||
857 ((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) &&
Andreas Bombece816cf2008-09-14 01:58:55 +0200858 (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID)) ||
859 ((le16_to_cpu(dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) &&
860 (le16_to_cpu(dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_EF81))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 if (interface != dev->actconfig->interface[0]) {
862 /* check out the endpoints of the other interface*/
863 iface_desc = dev->actconfig->interface[0]->cur_altsetting;
864 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
865 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700866 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867 /* we found a interrupt in endpoint */
868 dbg("found interrupt in for Prolific device on separate interface");
869 interrupt_in_endpoint[num_interrupt_in] = endpoint;
870 ++num_interrupt_in;
871 }
872 }
873 }
874
875 /* Now make sure the PL-2303 is configured correctly.
876 * If not, give up now and hope this hack will work
877 * properly during a later invocation of usb_serial_probe
878 */
879 if (num_bulk_in == 0 || num_bulk_out == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100880 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100882 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 return -ENODEV;
884 }
885 }
886 /* END HORRIBLE HACK FOR PL2303 */
887#endif
888
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889#ifdef CONFIG_USB_SERIAL_GENERIC
890 if (type == &usb_serial_generic_device) {
891 num_ports = num_bulk_out;
892 if (num_ports == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100893 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100894 dev_err(&interface->dev,
895 "Generic device with no bulk out, not allowed.\n");
896 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 return -EIO;
898 }
899 }
900#endif
901 if (!num_ports) {
902 /* if this device type has a calc_num_ports function, call it */
903 if (type->calc_num_ports) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700904 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100905 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100906 dev_err(&interface->dev,
907 "module get failed, exiting\n");
908 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 return -EIO;
910 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100911 num_ports = type->calc_num_ports(serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700912 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 }
914 if (!num_ports)
915 num_ports = type->num_ports;
916 }
917
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 serial->num_ports = num_ports;
919 serial->num_bulk_in = num_bulk_in;
920 serial->num_bulk_out = num_bulk_out;
921 serial->num_interrupt_in = num_interrupt_in;
922 serial->num_interrupt_out = num_interrupt_out;
923
Alan Stern063a2da2007-10-10 16:24:06 -0400924 /* found all that we need */
925 dev_info(&interface->dev, "%s converter detected\n",
926 type->description);
927
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 /* create our ports, we need as many as the max endpoints */
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100929 /* we don't use num_ports here because some devices have more
930 endpoint pairs than ports */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 max_endpoints = max(num_bulk_in, num_bulk_out);
932 max_endpoints = max(max_endpoints, num_interrupt_in);
933 max_endpoints = max(max_endpoints, num_interrupt_out);
934 max_endpoints = max(max_endpoints, (int)serial->num_ports);
935 serial->num_port_pointers = max_endpoints;
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100936 unlock_kernel();
937
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100938 dbg("%s - setting up %d port structures for this device",
939 __func__, max_endpoints);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 for (i = 0; i < max_endpoints; ++i) {
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100941 port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 if (!port)
943 goto probe_error;
Alan Cox4a90f092008-10-13 10:39:46 +0100944 tty_port_init(&port->port);
Alan Cox335f8512009-06-11 12:26:29 +0100945 port->port.ops = &serial_port_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 port->serial = serial;
Greg Kroah-Hartman507ca9b2005-04-23 12:49:16 -0700947 spin_lock_init(&port->lock);
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300948 mutex_init(&port->mutex);
David Howellsc4028952006-11-22 14:57:56 +0000949 INIT_WORK(&port->work, usb_serial_port_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 serial->port[i] = port;
Alan Stern41bd34d2009-09-01 11:38:34 -0400951 port->dev.parent = &interface->dev;
952 port->dev.driver = NULL;
953 port->dev.bus = &usb_serial_bus_type;
954 port->dev.release = &port_release;
955 device_initialize(&port->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 }
957
958 /* set up the endpoint information */
959 for (i = 0; i < num_bulk_in; ++i) {
960 endpoint = bulk_in_endpoint[i];
961 port = serial->port[i];
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100962 port->read_urb = usb_alloc_urb(0, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 if (!port->read_urb) {
964 dev_err(&interface->dev, "No free urbs available\n");
965 goto probe_error;
966 }
967 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
968 port->bulk_in_size = buffer_size;
969 port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100970 port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971 if (!port->bulk_in_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100972 dev_err(&interface->dev,
973 "Couldn't allocate bulk_in_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 goto probe_error;
975 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100976 usb_fill_bulk_urb(port->read_urb, dev,
977 usb_rcvbulkpipe(dev,
978 endpoint->bEndpointAddress),
979 port->bulk_in_buffer, buffer_size,
980 serial->type->read_bulk_callback, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 }
982
983 for (i = 0; i < num_bulk_out; ++i) {
984 endpoint = bulk_out_endpoint[i];
985 port = serial->port[i];
986 port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
987 if (!port->write_urb) {
988 dev_err(&interface->dev, "No free urbs available\n");
989 goto probe_error;
990 }
991 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
992 port->bulk_out_size = buffer_size;
993 port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100994 port->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995 if (!port->bulk_out_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100996 dev_err(&interface->dev,
997 "Couldn't allocate bulk_out_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 goto probe_error;
999 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001000 usb_fill_bulk_urb(port->write_urb, dev,
1001 usb_sndbulkpipe(dev,
1002 endpoint->bEndpointAddress),
1003 port->bulk_out_buffer, buffer_size,
1004 serial->type->write_bulk_callback, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005 }
1006
1007 if (serial->type->read_int_callback) {
1008 for (i = 0; i < num_interrupt_in; ++i) {
1009 endpoint = interrupt_in_endpoint[i];
1010 port = serial->port[i];
1011 port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
1012 if (!port->interrupt_in_urb) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001013 dev_err(&interface->dev,
1014 "No free urbs available\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 goto probe_error;
1016 }
1017 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001018 port->interrupt_in_endpointAddress =
1019 endpoint->bEndpointAddress;
1020 port->interrupt_in_buffer = kmalloc(buffer_size,
1021 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 if (!port->interrupt_in_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001023 dev_err(&interface->dev,
1024 "Couldn't allocate interrupt_in_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 goto probe_error;
1026 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001027 usb_fill_int_urb(port->interrupt_in_urb, dev,
1028 usb_rcvintpipe(dev,
1029 endpoint->bEndpointAddress),
1030 port->interrupt_in_buffer, buffer_size,
1031 serial->type->read_int_callback, port,
1032 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 }
1034 } else if (num_interrupt_in) {
1035 dbg("the device claims to support interrupt in transfers, but read_int_callback is not defined");
1036 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001037
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 if (serial->type->write_int_callback) {
1039 for (i = 0; i < num_interrupt_out; ++i) {
1040 endpoint = interrupt_out_endpoint[i];
1041 port = serial->port[i];
1042 port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
1043 if (!port->interrupt_out_urb) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001044 dev_err(&interface->dev,
1045 "No free urbs available\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046 goto probe_error;
1047 }
1048 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
1049 port->interrupt_out_size = buffer_size;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001050 port->interrupt_out_endpointAddress =
1051 endpoint->bEndpointAddress;
1052 port->interrupt_out_buffer = kmalloc(buffer_size,
1053 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 if (!port->interrupt_out_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001055 dev_err(&interface->dev,
1056 "Couldn't allocate interrupt_out_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 goto probe_error;
1058 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001059 usb_fill_int_urb(port->interrupt_out_urb, dev,
1060 usb_sndintpipe(dev,
1061 endpoint->bEndpointAddress),
1062 port->interrupt_out_buffer, buffer_size,
1063 serial->type->write_int_callback, port,
1064 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065 }
1066 } else if (num_interrupt_out) {
1067 dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined");
1068 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001069
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 /* if this device type has an attach function, call it */
1071 if (type->attach) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -07001072 if (!try_module_get(type->driver.owner)) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001073 dev_err(&interface->dev,
1074 "module get failed, exiting\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075 goto probe_error;
1076 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001077 retval = type->attach(serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -07001078 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 if (retval < 0)
1080 goto probe_error;
1081 if (retval > 0) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001082 /* quietly accept this device, but don't bind to a
1083 serial port as it's about to disappear */
Alan Stern0a3c8542009-05-27 11:25:52 -04001084 serial->num_ports = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 goto exit;
1086 }
1087 }
1088
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001089 if (get_free_serial(serial, num_ports, &minor) == NULL) {
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001090 dev_err(&interface->dev, "No more free serial devices\n");
1091 goto probe_error;
1092 }
Oliver Neukumc744f992007-02-26 15:43:00 +01001093 serial->minor = minor;
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001094
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095 /* register all of the individual ports with the driver core */
1096 for (i = 0; i < num_ports; ++i) {
1097 port = serial->port[i];
Kay Sievers0031a062008-05-02 06:02:41 +02001098 dev_set_name(&port->dev, "ttyUSB%d", port->number);
Kay Sievers7071a3c2008-05-02 06:02:41 +02001099 dbg ("%s - registering %s", __func__, dev_name(&port->dev));
Alan Sternc706ebd2009-06-02 11:54:11 -04001100 port->dev_state = PORT_REGISTERING;
Alan Stern41bd34d2009-09-01 11:38:34 -04001101 retval = device_add(&port->dev);
Alan Sternc706ebd2009-06-02 11:54:11 -04001102 if (retval) {
Greg Kroah-Hartman13f4db92006-08-28 11:43:25 -07001103 dev_err(&port->dev, "Error registering port device, "
1104 "continuing\n");
Alan Sternc706ebd2009-06-02 11:54:11 -04001105 port->dev_state = PORT_UNREGISTERED;
1106 } else {
1107 port->dev_state = PORT_REGISTERED;
1108 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 }
1110
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001111 usb_serial_console_init(debug, minor);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112
1113exit:
1114 /* success */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001115 usb_set_intfdata(interface, serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 return 0;
1117
1118probe_error:
Alan Stern41bd34d2009-09-01 11:38:34 -04001119 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 return -EIO;
1121}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001122EXPORT_SYMBOL_GPL(usb_serial_probe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123
1124void usb_serial_disconnect(struct usb_interface *interface)
1125{
1126 int i;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001127 struct usb_serial *serial = usb_get_intfdata(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 struct device *dev = &interface->dev;
1129 struct usb_serial_port *port;
1130
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +02001131 usb_serial_console_disconnect(serial);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001132 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001134 mutex_lock(&serial->disc_mutex);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001135 usb_set_intfdata(interface, NULL);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001136 /* must set a flag, to signal subdrivers */
1137 serial->disconnected = 1;
Alan Stern2d931482009-04-14 11:31:02 -04001138 mutex_unlock(&serial->disc_mutex);
1139
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001140 for (i = 0; i < serial->num_ports; ++i) {
1141 port = serial->port[i];
1142 if (port) {
Alan Cox4a90f092008-10-13 10:39:46 +01001143 struct tty_struct *tty = tty_port_tty_get(&port->port);
1144 if (tty) {
Alan Coxd2b39182009-09-19 13:13:23 -07001145 tty_vhangup(tty);
Alan Cox4a90f092008-10-13 10:39:46 +01001146 tty_kref_put(tty);
1147 }
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001148 kill_traffic(port);
Alan Stern2d931482009-04-14 11:31:02 -04001149 cancel_work_sync(&port->work);
Alan Sternc706ebd2009-06-02 11:54:11 -04001150 if (port->dev_state == PORT_REGISTERED) {
1151
1152 /* Make sure the port is bound so that the
1153 * driver's port_remove method is called.
1154 */
1155 if (!port->dev.driver) {
1156 int rc;
1157
1158 port->dev.driver =
1159 &serial->type->driver;
1160 rc = device_bind_driver(&port->dev);
1161 }
1162 port->dev_state = PORT_UNREGISTERING;
1163 device_del(&port->dev);
1164 port->dev_state = PORT_UNREGISTERED;
1165 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167 }
Alan Sternf9c99bb2009-06-02 11:53:55 -04001168 serial->type->disconnect(serial);
Alan Stern2d931482009-04-14 11:31:02 -04001169
Alan Stern41bd34d2009-09-01 11:38:34 -04001170 /* let the last holder of this object cause it to be cleaned up */
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001171 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172 dev_info(dev, "device disconnected\n");
1173}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001174EXPORT_SYMBOL_GPL(usb_serial_disconnect);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175
Oliver Neukumec225592007-04-27 20:54:57 +02001176int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
1177{
1178 struct usb_serial *serial = usb_get_intfdata(intf);
1179 struct usb_serial_port *port;
1180 int i, r = 0;
1181
Oliver Neukumf8bece82009-02-05 16:54:25 +01001182 serial->suspending = 1;
1183
Oliver Neukume31c1882007-07-23 08:58:39 +02001184 for (i = 0; i < serial->num_ports; ++i) {
1185 port = serial->port[i];
1186 if (port)
1187 kill_traffic(port);
Oliver Neukumec225592007-04-27 20:54:57 +02001188 }
1189
1190 if (serial->type->suspend)
Oliver Neukume31c1882007-07-23 08:58:39 +02001191 r = serial->type->suspend(serial, message);
Oliver Neukumec225592007-04-27 20:54:57 +02001192
1193 return r;
1194}
1195EXPORT_SYMBOL(usb_serial_suspend);
1196
1197int usb_serial_resume(struct usb_interface *intf)
1198{
1199 struct usb_serial *serial = usb_get_intfdata(intf);
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001200 int rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001201
Oliver Neukumf8bece82009-02-05 16:54:25 +01001202 serial->suspending = 0;
Sarah Sharp8abaee22007-10-25 10:58:43 -07001203 if (serial->type->resume)
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001204 rv = serial->type->resume(serial);
1205 else
1206 rv = usb_serial_generic_resume(serial);
Oliver Neukumf8bece82009-02-05 16:54:25 +01001207
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001208 return rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001209}
1210EXPORT_SYMBOL(usb_serial_resume);
1211
Jeff Dikeb68e31d2006-10-02 02:17:18 -07001212static const struct tty_operations serial_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 .open = serial_open,
1214 .close = serial_close,
1215 .write = serial_write,
Alan Cox335f8512009-06-11 12:26:29 +01001216 .hangup = serial_hangup,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 .write_room = serial_write_room,
1218 .ioctl = serial_ioctl,
1219 .set_termios = serial_set_termios,
1220 .throttle = serial_throttle,
1221 .unthrottle = serial_unthrottle,
1222 .break_ctl = serial_break,
1223 .chars_in_buffer = serial_chars_in_buffer,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 .tiocmget = serial_tiocmget,
1225 .tiocmset = serial_tiocmset,
Alan Coxfe1ae7f2009-09-19 13:13:33 -07001226 .shutdown = serial_do_free,
1227 .install = serial_install,
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -07001228 .proc_fops = &serial_proc_fops,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229};
1230
Alan Cox335f8512009-06-11 12:26:29 +01001231
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232struct tty_driver *usb_serial_tty_driver;
1233
1234static int __init usb_serial_init(void)
1235{
1236 int i;
1237 int result;
1238
1239 usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS);
1240 if (!usb_serial_tty_driver)
1241 return -ENOMEM;
1242
1243 /* Initialize our global data */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001244 for (i = 0; i < SERIAL_TTY_MINORS; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245 serial_table[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246
1247 result = bus_register(&usb_serial_bus_type);
1248 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001249 printk(KERN_ERR "usb-serial: %s - registering bus driver "
1250 "failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 goto exit_bus;
1252 }
1253
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254 usb_serial_tty_driver->owner = THIS_MODULE;
1255 usb_serial_tty_driver->driver_name = "usbserial";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 usb_serial_tty_driver->name = "ttyUSB";
1257 usb_serial_tty_driver->major = SERIAL_TTY_MAJOR;
1258 usb_serial_tty_driver->minor_start = 0;
1259 usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
1260 usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001261 usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW |
1262 TTY_DRIVER_DYNAMIC_DEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263 usb_serial_tty_driver->init_termios = tty_std_termios;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001264 usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD
1265 | HUPCL | CLOCAL;
Alan Coxa5b6f602008-04-08 17:16:06 +01001266 usb_serial_tty_driver->init_termios.c_ispeed = 9600;
1267 usb_serial_tty_driver->init_termios.c_ospeed = 9600;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 tty_set_operations(usb_serial_tty_driver, &serial_ops);
1269 result = tty_register_driver(usb_serial_tty_driver);
1270 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001271 printk(KERN_ERR "usb-serial: %s - tty_register_driver failed\n",
1272 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 goto exit_reg_driver;
1274 }
1275
1276 /* register the USB driver */
1277 result = usb_register(&usb_serial_driver);
1278 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001279 printk(KERN_ERR "usb-serial: %s - usb_register failed\n",
1280 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281 goto exit_tty;
1282 }
1283
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001284 /* register the generic driver, if we should */
1285 result = usb_serial_generic_register(debug);
1286 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001287 printk(KERN_ERR "usb-serial: %s - registering generic "
1288 "driver failed\n", __func__);
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001289 goto exit_generic;
1290 }
1291
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001292 printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293
1294 return result;
1295
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001296exit_generic:
1297 usb_deregister(&usb_serial_driver);
1298
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299exit_tty:
1300 tty_unregister_driver(usb_serial_tty_driver);
1301
1302exit_reg_driver:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303 bus_unregister(&usb_serial_bus_type);
1304
1305exit_bus:
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001306 printk(KERN_ERR "usb-serial: %s - returning with error %d\n",
1307 __func__, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308 put_tty_driver(usb_serial_tty_driver);
1309 return result;
1310}
1311
1312
1313static void __exit usb_serial_exit(void)
1314{
1315 usb_serial_console_exit();
1316
1317 usb_serial_generic_deregister();
1318
1319 usb_deregister(&usb_serial_driver);
1320 tty_unregister_driver(usb_serial_tty_driver);
1321 put_tty_driver(usb_serial_tty_driver);
1322 bus_unregister(&usb_serial_bus_type);
1323}
1324
1325
1326module_init(usb_serial_init);
1327module_exit(usb_serial_exit);
1328
1329#define set_to_generic_if_null(type, function) \
1330 do { \
1331 if (!type->function) { \
1332 type->function = usb_serial_generic_##function; \
1333 dbg("Had to override the " #function \
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001334 " usb serial operation with the generic one.");\
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335 } \
1336 } while (0)
1337
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001338static void fixup_generic(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339{
1340 set_to_generic_if_null(device, open);
1341 set_to_generic_if_null(device, write);
1342 set_to_generic_if_null(device, close);
1343 set_to_generic_if_null(device, write_room);
1344 set_to_generic_if_null(device, chars_in_buffer);
1345 set_to_generic_if_null(device, read_bulk_callback);
1346 set_to_generic_if_null(device, write_bulk_callback);
Alan Sternf9c99bb2009-06-02 11:53:55 -04001347 set_to_generic_if_null(device, disconnect);
1348 set_to_generic_if_null(device, release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349}
1350
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001351int usb_serial_register(struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001353 /* must be called with BKL held */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 int retval;
1355
Dave Younge4abe662009-02-14 21:21:13 +08001356 if (usb_disabled())
1357 return -ENODEV;
1358
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001359 fixup_generic(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001361 if (!driver->description)
1362 driver->description = driver->driver.name;
1363
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364 /* Add this device to our list of devices */
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001365 list_add(&driver->driver_list, &usb_serial_driver_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001367 retval = usb_serial_bus_register(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368 if (retval) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001369 printk(KERN_ERR "usb-serial: problem %d when registering "
1370 "driver %s\n", retval, driver->description);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001371 list_del(&driver->driver_list);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001372 } else
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001373 printk(KERN_INFO "USB Serial support registered for %s\n",
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001374 driver->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375
1376 return retval;
1377}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001378EXPORT_SYMBOL_GPL(usb_serial_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379
1380
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001381void usb_serial_deregister(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001383 /* must be called with BKL held */
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001384 printk(KERN_INFO "USB Serial deregistering driver %s\n",
1385 device->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386 list_del(&device->driver_list);
1387 usb_serial_bus_deregister(device);
1388}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389EXPORT_SYMBOL_GPL(usb_serial_deregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390
1391/* Module information */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001392MODULE_AUTHOR(DRIVER_AUTHOR);
1393MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394MODULE_LICENSE("GPL");
1395
1396module_param(debug, bool, S_IRUGO | S_IWUSR);
1397MODULE_PARM_DESC(debug, "Debug enabled or not");