blob: f1a1f0fb6d1bd5e663cfe70972bf8e1fd602adfa [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
69struct usb_serial *usb_serial_get_by_index(unsigned index)
70{
Oliver Neukum34ef50e2007-01-13 07:29:26 +010071 struct usb_serial *serial;
72
Oliver Neukum3ddad822007-07-24 15:13:42 +020073 mutex_lock(&table_lock);
Oliver Neukum34ef50e2007-01-13 07:29:26 +010074 serial = serial_table[index];
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
76 if (serial)
77 kref_get(&serial->kref);
Oliver Neukum3ddad822007-07-24 15:13:42 +020078 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070079 return serial;
80}
81
Alan Coxa8d6f0a2008-07-22 11:12:24 +010082static struct usb_serial *get_free_serial(struct usb_serial *serial,
83 int num_ports, unsigned int *minor)
Linus Torvalds1da177e2005-04-16 15:20:36 -070084{
85 unsigned int i, j;
86 int good_spot;
87
Harvey Harrison441b62c2008-03-03 16:08:34 -080088 dbg("%s %d", __func__, num_ports);
Linus Torvalds1da177e2005-04-16 15:20:36 -070089
90 *minor = 0;
Oliver Neukum3ddad822007-07-24 15:13:42 +020091 mutex_lock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070092 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
93 if (serial_table[i])
94 continue;
95
96 good_spot = 1;
97 for (j = 1; j <= num_ports-1; ++j)
98 if ((i+j >= SERIAL_TTY_MINORS) || (serial_table[i+j])) {
99 good_spot = 0;
100 i += j;
101 break;
102 }
103 if (good_spot == 0)
104 continue;
105
106 *minor = i;
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100107 j = 0;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800108 dbg("%s - minor base = %d", __func__, *minor);
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100109 for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110 serial_table[i] = serial;
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100111 serial->port[j++]->number = i;
112 }
Oliver Neukum3ddad822007-07-24 15:13:42 +0200113 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114 return serial;
115 }
Oliver Neukum3ddad822007-07-24 15:13:42 +0200116 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 return NULL;
118}
119
120static void return_serial(struct usb_serial *serial)
121{
122 int i;
123
Harvey Harrison441b62c2008-03-03 16:08:34 -0800124 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100126 for (i = 0; i < serial->num_ports; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127 serial_table[serial->minor + i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128}
129
130static void destroy_serial(struct kref *kref)
131{
132 struct usb_serial *serial;
133 struct usb_serial_port *port;
134 int i;
135
136 serial = to_usb_serial(kref);
137
Harvey Harrison441b62c2008-03-03 16:08:34 -0800138 dbg("%s - %s", __func__, serial->type->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139
Jim Radford521b85a2007-03-13 08:30:50 -0700140 /* return the minor range that this device had */
Alan Stern0282b7f2008-07-29 12:01:04 -0400141 if (serial->minor != SERIAL_TTY_NO_MINOR)
142 return_serial(serial);
Jim Radford521b85a2007-03-13 08:30:50 -0700143
Alan Sternf9c99bb2009-06-02 11:53:55 -0400144 serial->type->release(serial);
145
Alan Stern41bd34d2009-09-01 11:38:34 -0400146 /* Now that nothing is using the ports, they can be freed */
147 for (i = 0; i < serial->num_port_pointers; ++i) {
Alan Sternf9c99bb2009-06-02 11:53:55 -0400148 port = serial->port[i];
Alan Stern41bd34d2009-09-01 11:38:34 -0400149 if (port) {
150 port->serial = NULL;
Alan Sternf9c99bb2009-06-02 11:53:55 -0400151 put_device(&port->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 }
153 }
154
155 usb_put_dev(serial->dev);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100156 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157}
158
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200159void usb_serial_put(struct usb_serial *serial)
160{
Oliver Neukum3ddad822007-07-24 15:13:42 +0200161 mutex_lock(&table_lock);
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200162 kref_put(&serial->kref, destroy_serial);
Oliver Neukum3ddad822007-07-24 15:13:42 +0200163 mutex_unlock(&table_lock);
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200164}
165
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166/*****************************************************************************
167 * Driver tty interface functions
168 *****************************************************************************/
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100169static int serial_open (struct tty_struct *tty, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170{
171 struct usb_serial *serial;
172 struct usb_serial_port *port;
173 unsigned int portNumber;
Alan Stern2d931482009-04-14 11:31:02 -0400174 int retval = 0;
Alan Coxc56d3002009-07-28 00:34:58 +0100175 int first = 0;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100176
Harvey Harrison441b62c2008-03-03 16:08:34 -0800177 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178
179 /* get the serial object associated with this tty pointer */
180 serial = usb_serial_get_by_index(tty->index);
181 if (!serial) {
182 tty->driver_data = NULL;
183 return -ENODEV;
184 }
185
Alan Stern2d931482009-04-14 11:31:02 -0400186 mutex_lock(&serial->disc_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187 portNumber = tty->index - serial->minor;
188 port = serial->port[portNumber];
Alan Stern2d931482009-04-14 11:31:02 -0400189 if (!port || serial->disconnected)
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300190 retval = -ENODEV;
Alan Stern2d931482009-04-14 11:31:02 -0400191 /*
192 * Note: Our locking order requirement does not allow port->mutex
193 * to be acquired while serial->disc_mutex is held.
194 */
195 mutex_unlock(&serial->disc_mutex);
196 if (retval)
197 goto bailout_serial_put;
James Woodcock331879f2009-02-11 15:06:53 +0000198
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300199 if (mutex_lock_interruptible(&port->mutex)) {
200 retval = -ERESTARTSYS;
Alan Stern41bd34d2009-09-01 11:38:34 -0400201 goto bailout_serial_put;
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300202 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100203
Alan Cox95da3102008-07-22 11:09:07 +0100204 ++port->port.count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205
Paul Fulghumca854852006-04-13 22:28:17 +0200206 /* set up our port structure making the tty driver
207 * remember our port object, and us it */
208 tty->driver_data = port;
Alan Cox4a90f092008-10-13 10:39:46 +0100209 tty_port_tty_set(&port->port, tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210
Jason Wessel6e406122009-06-22 11:32:20 -0500211 /* If the console is attached, the device is already open */
212 if (port->port.count == 1 && !port->console) {
Alan Coxc56d3002009-07-28 00:34:58 +0100213 first = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 /* lock this module before we call it
215 * this may fail, which means we must bail out,
216 * safe because we are called with BKL held */
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700217 if (!try_module_get(serial->type->driver.owner)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 retval = -ENODEV;
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300219 goto bailout_mutex_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 }
221
Alan Stern2d931482009-04-14 11:31:02 -0400222 mutex_lock(&serial->disc_mutex);
223 if (serial->disconnected)
224 retval = -ENODEV;
225 else
226 retval = usb_autopm_get_interface(serial->interface);
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800227 if (retval)
228 goto bailout_module_put;
Alan Stern2d931482009-04-14 11:31:02 -0400229
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100230 /* only call the device specific open if this
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231 * is the first time the port is opened */
Alan Coxa509a7e2009-09-19 13:13:26 -0700232 retval = serial->type->open(tty, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 if (retval)
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800234 goto bailout_interface_put;
Alan Stern2d931482009-04-14 11:31:02 -0400235 mutex_unlock(&serial->disc_mutex);
Alan Coxc56d3002009-07-28 00:34:58 +0100236 set_bit(ASYNCB_INITIALIZED, &port->port.flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 }
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300238 mutex_unlock(&port->mutex);
Alan Cox335f8512009-06-11 12:26:29 +0100239 /* Now do the correct tty layer semantics */
240 retval = tty_port_block_til_ready(&port->port, tty, filp);
Alan Coxc56d3002009-07-28 00:34:58 +0100241 if (retval == 0) {
242 if (!first)
243 usb_serial_put(serial);
Alan Cox335f8512009-06-11 12:26:29 +0100244 return 0;
Alan Coxc56d3002009-07-28 00:34:58 +0100245 }
246 mutex_lock(&port->mutex);
247 if (first == 0)
248 goto bailout_mutex_unlock;
249 /* Undo the initial port actions */
250 mutex_lock(&serial->disc_mutex);
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800251bailout_interface_put:
252 usb_autopm_put_interface(serial->interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253bailout_module_put:
Alan Stern2d931482009-04-14 11:31:02 -0400254 mutex_unlock(&serial->disc_mutex);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700255 module_put(serial->type->driver.owner);
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300256bailout_mutex_unlock:
Alan Cox95da3102008-07-22 11:09:07 +0100257 port->port.count = 0;
Frank Gevaertsb059c812006-06-14 15:52:05 +0200258 tty->driver_data = NULL;
Alan Cox4a90f092008-10-13 10:39:46 +0100259 tty_port_tty_set(&port->port, NULL);
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300260 mutex_unlock(&port->mutex);
Alan Stern2d931482009-04-14 11:31:02 -0400261bailout_serial_put:
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200262 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 return retval;
264}
265
Alan Cox335f8512009-06-11 12:26:29 +0100266/**
267 * serial_do_down - shut down hardware
268 * @port: port to shut down
269 *
270 * Shut down a USB port unless it is the console. We never shut down the
271 * console hardware as it will always be in use.
272 *
273 * Don't free any resources at this point
274 */
275static void serial_do_down(struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276{
Alan Cox335f8512009-06-11 12:26:29 +0100277 struct usb_serial_driver *drv = port->serial->type;
Alan Stern2d931482009-04-14 11:31:02 -0400278 struct usb_serial *serial;
279 struct module *owner;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280
Alan Cox335f8512009-06-11 12:26:29 +0100281 /* The console is magical, do not hang up the console hardware
282 or there will be tears */
283 if (port->console)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 return;
285
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300286 mutex_lock(&port->mutex);
Alan Stern2d931482009-04-14 11:31:02 -0400287 serial = port->serial;
288 owner = serial->type->driver.owner;
Luiz Fernando Capitulino8a4613f2005-11-28 19:16:07 -0200289
Alan Cox335f8512009-06-11 12:26:29 +0100290 if (drv->close)
291 drv->close(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300293 mutex_unlock(&port->mutex);
Alan Cox335f8512009-06-11 12:26:29 +0100294}
295
296/**
297 * serial_do_free - free resources post close/hangup
298 * @port: port to free up
299 *
300 * Do the resource freeing and refcount dropping for the port. We must
301 * be careful about ordering and we must avoid freeing up the console.
Alan Cox4455e342009-09-19 13:13:24 -0700302 *
303 * Called when the last tty kref is dropped.
Alan Cox335f8512009-06-11 12:26:29 +0100304 */
305
Alan Cox4455e342009-09-19 13:13:24 -0700306static void serial_do_free(struct tty_struct *tty)
Alan Cox335f8512009-06-11 12:26:29 +0100307{
Alan Cox4455e342009-09-19 13:13:24 -0700308 struct usb_serial_port *port = tty->driver_data;
Alan Cox335f8512009-06-11 12:26:29 +0100309 struct usb_serial *serial;
310 struct module *owner;
311
312 /* The console is magical, do not hang up the console hardware
313 or there will be tears */
Alan Cox4455e342009-09-19 13:13:24 -0700314 if (port == NULL || port->console)
Alan Cox335f8512009-06-11 12:26:29 +0100315 return;
316
317 serial = port->serial;
318 owner = serial->type->driver.owner;
Alan Stern41bd34d2009-09-01 11:38:34 -0400319
Alan Cox335f8512009-06-11 12:26:29 +0100320 mutex_lock(&serial->disc_mutex);
321 if (!serial->disconnected)
322 usb_autopm_put_interface(serial->interface);
323 mutex_unlock(&serial->disc_mutex);
Alan Stern41bd34d2009-09-01 11:38:34 -0400324
Alan Stern2d931482009-04-14 11:31:02 -0400325 usb_serial_put(serial);
Alan Cox335f8512009-06-11 12:26:29 +0100326 module_put(owner);
327}
328
329static void serial_close(struct tty_struct *tty, struct file *filp)
330{
331 struct usb_serial_port *port = tty->driver_data;
332
Thadeu Lima de Souza Cascardof4fa4462009-06-25 14:41:37 +0100333 if (!port)
334 return;
335
Alan Cox335f8512009-06-11 12:26:29 +0100336 dbg("%s - port %d", __func__, port->number);
337
Alan Cox335f8512009-06-11 12:26:29 +0100338 if (tty_port_close_start(&port->port, tty, filp) == 0)
339 return;
Alan Cox335f8512009-06-11 12:26:29 +0100340 serial_do_down(port);
341 tty_port_close_end(&port->port, tty);
342 tty_port_tty_set(&port->port, NULL);
Alan Cox4455e342009-09-19 13:13:24 -0700343
Alan Cox335f8512009-06-11 12:26:29 +0100344}
345
346static void serial_hangup(struct tty_struct *tty)
347{
348 struct usb_serial_port *port = tty->driver_data;
349 serial_do_down(port);
350 tty_port_hangup(&port->port);
Alan Coxb68f2fb2009-07-27 10:58:08 +0100351 /* We must not free port yet - the USB serial layer depends on it's
352 continued existence */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353}
354
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100355static int serial_write(struct tty_struct *tty, const unsigned char *buf,
356 int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200358 struct usb_serial_port *port = tty->driver_data;
Oliver Neukum3ff4fd92007-01-13 07:32:27 +0100359 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360
Alan Coxf34d7a52008-04-30 00:54:13 -0700361 if (port->serial->dev->state == USB_STATE_NOTATTACHED)
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200362 goto exit;
363
Harvey Harrison441b62c2008-03-03 16:08:34 -0800364 dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365
Alan Cox95da3102008-07-22 11:09:07 +0100366 /* count is managed under the mutex lock for the tty so cannot
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100367 drop to zero until after the last close completes */
Alan Cox95da3102008-07-22 11:09:07 +0100368 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369
370 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100371 retval = port->serial->type->write(tty, port, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372
373exit:
374 return retval;
375}
376
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100377static int serial_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200379 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800380 dbg("%s - port %d", __func__, port->number);
Alan Cox95da3102008-07-22 11:09:07 +0100381 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100383 return port->serial->type->write_room(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384}
385
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100386static int serial_chars_in_buffer(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200388 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800389 dbg("%s = port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390
Alan Coxeff69372009-01-02 13:47:06 +0000391 /* if the device was unplugged then any remaining characters
392 fell out of the connector ;) */
393 if (port->serial->disconnected)
394 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100396 return port->serial->type->chars_in_buffer(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397}
398
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100399static void serial_throttle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200401 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800402 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403
Alan Cox95da3102008-07-22 11:09:07 +0100404 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 /* pass on to the driver specific version of this function */
406 if (port->serial->type->throttle)
Alan Cox95da3102008-07-22 11:09:07 +0100407 port->serial->type->throttle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408}
409
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100410static void serial_unthrottle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200412 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800413 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414
Alan Cox95da3102008-07-22 11:09:07 +0100415 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 /* pass on to the driver specific version of this function */
417 if (port->serial->type->unthrottle)
Alan Cox95da3102008-07-22 11:09:07 +0100418 port->serial->type->unthrottle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419}
420
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100421static int serial_ioctl(struct tty_struct *tty, struct file *file,
422 unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200424 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425 int retval = -ENODEV;
426
Harvey Harrison441b62c2008-03-03 16:08:34 -0800427 dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428
Alan Cox95da3102008-07-22 11:09:07 +0100429 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100431 /* pass on to the driver specific version of this function
432 if it is available */
Alan Coxf34d7a52008-04-30 00:54:13 -0700433 if (port->serial->type->ioctl) {
Alan Cox95da3102008-07-22 11:09:07 +0100434 retval = port->serial->type->ioctl(tty, file, cmd, arg);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100435 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 retval = -ENOIOCTLCMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 return retval;
438}
439
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100440static void serial_set_termios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200442 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800443 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444
Alan Cox95da3102008-07-22 11:09:07 +0100445 WARN_ON(!port->port.count);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100446 /* pass on to the driver specific version of this function
447 if it is available */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 if (port->serial->type->set_termios)
Alan Cox95da3102008-07-22 11:09:07 +0100449 port->serial->type->set_termios(tty, port, old);
Alan Cox33785092007-10-18 01:24:22 -0700450 else
451 tty_termios_copy_hw(tty->termios, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452}
453
Alan Cox9e989662008-07-22 11:18:03 +0100454static int serial_break(struct tty_struct *tty, int break_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200456 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457
Harvey Harrison441b62c2008-03-03 16:08:34 -0800458 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459
Alan Cox95da3102008-07-22 11:09:07 +0100460 WARN_ON(!port->port.count);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100461 /* pass on to the driver specific version of this function
462 if it is available */
Alan Cox6b447f042009-01-02 13:48:56 +0000463 if (port->serial->type->break_ctl)
Alan Cox95da3102008-07-22 11:09:07 +0100464 port->serial->type->break_ctl(tty, break_state);
Alan Cox9e989662008-07-22 11:18:03 +0100465 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466}
467
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700468static int serial_proc_show(struct seq_file *m, void *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469{
470 struct usb_serial *serial;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 char tmp[40];
473
Harvey Harrison441b62c2008-03-03 16:08:34 -0800474 dbg("%s", __func__);
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700475 seq_puts(m, "usbserinfo:1.0 driver:2.0\n");
476 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 serial = usb_serial_get_by_index(i);
478 if (serial == NULL)
479 continue;
480
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700481 seq_printf(m, "%d:", i);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700482 if (serial->type->driver.owner)
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700483 seq_printf(m, " module:%s",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100484 module_name(serial->type->driver.owner));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700485 seq_printf(m, " name:\"%s\"",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100486 serial->type->description);
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700487 seq_printf(m, " vendor:%04x product:%04x",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100488 le16_to_cpu(serial->dev->descriptor.idVendor),
489 le16_to_cpu(serial->dev->descriptor.idProduct));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700490 seq_printf(m, " num_ports:%d", serial->num_ports);
491 seq_printf(m, " port:%d", i - serial->minor + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 usb_make_path(serial->dev, tmp, sizeof(tmp));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700493 seq_printf(m, " path:%s", tmp);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100494
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700495 seq_putc(m, '\n');
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200496 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 }
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700498 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499}
500
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700501static int serial_proc_open(struct inode *inode, struct file *file)
502{
503 return single_open(file, serial_proc_show, NULL);
504}
505
506static const struct file_operations serial_proc_fops = {
507 .owner = THIS_MODULE,
508 .open = serial_proc_open,
509 .read = seq_read,
510 .llseek = seq_lseek,
511 .release = single_release,
512};
513
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100514static int serial_tiocmget(struct tty_struct *tty, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200516 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517
Harvey Harrison441b62c2008-03-03 16:08:34 -0800518 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519
Alan Cox95da3102008-07-22 11:09:07 +0100520 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 if (port->serial->type->tiocmget)
Alan Cox95da3102008-07-22 11:09:07 +0100522 return port->serial->type->tiocmget(tty, file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 return -EINVAL;
524}
525
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100526static int serial_tiocmset(struct tty_struct *tty, struct file *file,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 unsigned int set, unsigned int clear)
528{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200529 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530
Harvey Harrison441b62c2008-03-03 16:08:34 -0800531 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532
Alan Cox95da3102008-07-22 11:09:07 +0100533 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534 if (port->serial->type->tiocmset)
Alan Cox95da3102008-07-22 11:09:07 +0100535 return port->serial->type->tiocmset(tty, file, set, clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536 return -EINVAL;
537}
538
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700539/*
540 * We would be calling tty_wakeup here, but unfortunately some line
541 * disciplines have an annoying habit of calling tty->write from
542 * the write wakeup callback (e.g. n_hdlc.c).
543 */
544void usb_serial_port_softint(struct usb_serial_port *port)
545{
546 schedule_work(&port->work);
547}
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100548EXPORT_SYMBOL_GPL(usb_serial_port_softint);
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700549
David Howellsc4028952006-11-22 14:57:56 +0000550static void usb_serial_port_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551{
David Howellsc4028952006-11-22 14:57:56 +0000552 struct usb_serial_port *port =
553 container_of(work, struct usb_serial_port, work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 struct tty_struct *tty;
555
Harvey Harrison441b62c2008-03-03 16:08:34 -0800556 dbg("%s - port %d", __func__, port->number);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100557
Alan Cox4a90f092008-10-13 10:39:46 +0100558 tty = tty_port_tty_get(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 if (!tty)
560 return;
561
562 tty_wakeup(tty);
Alan Cox4a90f092008-10-13 10:39:46 +0100563 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564}
565
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100566static void kill_traffic(struct usb_serial_port *port)
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700567{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 usb_kill_urb(port->write_urb);
Oliver Neukum5adceac2007-08-17 14:01:38 +0200570 /*
571 * This is tricky.
572 * Some drivers submit the read_urb in the
573 * handler for the write_urb or vice versa
574 * this order determines the order in which
575 * usb_kill_urb() must be used to reliably
576 * kill the URBs. As it is unknown here,
577 * both orders must be used in turn.
578 * The call below is not redundant.
579 */
580 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 usb_kill_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582 usb_kill_urb(port->interrupt_out_urb);
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100583}
584
Alan Stern41bd34d2009-09-01 11:38:34 -0400585static void port_release(struct device *dev)
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100586{
Alan Stern41bd34d2009-09-01 11:38:34 -0400587 struct usb_serial_port *port = to_usb_serial_port(dev);
588
589 dbg ("%s - %s", __func__, dev_name(dev));
590
Alan Stern2d931482009-04-14 11:31:02 -0400591 /*
592 * Stop all the traffic before cancelling the work, so that
593 * nobody will restart it by calling usb_serial_port_softint.
594 */
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100595 kill_traffic(port);
Alan Stern2d931482009-04-14 11:31:02 -0400596 cancel_work_sync(&port->work);
597
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100598 usb_free_urb(port->read_urb);
599 usb_free_urb(port->write_urb);
600 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601 usb_free_urb(port->interrupt_out_urb);
602 kfree(port->bulk_in_buffer);
603 kfree(port->bulk_out_buffer);
604 kfree(port->interrupt_in_buffer);
605 kfree(port->interrupt_out_buffer);
606 kfree(port);
607}
608
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100609static struct usb_serial *create_serial(struct usb_device *dev,
610 struct usb_interface *interface,
611 struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612{
613 struct usb_serial *serial;
614
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100615 serial = kzalloc(sizeof(*serial), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 if (!serial) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800617 dev_err(&dev->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618 return NULL;
619 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 serial->dev = usb_get_dev(dev);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700621 serial->type = driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622 serial->interface = interface;
623 kref_init(&serial->kref);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +0100624 mutex_init(&serial->disc_mutex);
Alan Stern0282b7f2008-07-29 12:01:04 -0400625 serial->minor = SERIAL_TTY_NO_MINOR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626
627 return serial;
628}
629
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100630static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf,
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100631 struct usb_serial_driver *drv)
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100632{
633 struct usb_dynid *dynid;
634
635 spin_lock(&drv->dynids.lock);
636 list_for_each_entry(dynid, &drv->dynids.list, node) {
637 if (usb_match_one_id(intf, &dynid->id)) {
638 spin_unlock(&drv->dynids.lock);
639 return &dynid->id;
640 }
641 }
642 spin_unlock(&drv->dynids.lock);
643 return NULL;
644}
645
646static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv,
647 struct usb_interface *intf)
648{
649 const struct usb_device_id *id;
650
651 id = usb_match_id(intf, drv->id_table);
652 if (id) {
653 dbg("static descriptor matches");
654 goto exit;
655 }
656 id = match_dynamic_id(intf, drv);
657 if (id)
658 dbg("dynamic descriptor matches");
659exit:
660 return id;
661}
662
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100663static struct usb_serial_driver *search_serial_device(
664 struct usb_interface *iface)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 const struct usb_device_id *id;
Alan Stern063a2da2007-10-10 16:24:06 -0400667 struct usb_serial_driver *drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668
Adrian Bunk93b1fae2006-01-10 00:13:33 +0100669 /* Check if the usb id matches a known device */
Alan Stern063a2da2007-10-10 16:24:06 -0400670 list_for_each_entry(drv, &usb_serial_driver_list, driver_list) {
671 id = get_iface_id(drv, iface);
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100672 if (id)
Alan Stern063a2da2007-10-10 16:24:06 -0400673 return drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 }
675
676 return NULL;
677}
678
Alan Cox335f8512009-06-11 12:26:29 +0100679static int serial_carrier_raised(struct tty_port *port)
680{
681 struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
682 struct usb_serial_driver *drv = p->serial->type;
683 if (drv->carrier_raised)
684 return drv->carrier_raised(p);
685 /* No carrier control - don't block */
686 return 1;
687}
688
689static void serial_dtr_rts(struct tty_port *port, int on)
690{
691 struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
692 struct usb_serial_driver *drv = p->serial->type;
693 if (drv->dtr_rts)
694 drv->dtr_rts(p, on);
695}
696
697static const struct tty_port_operations serial_port_ops = {
698 .carrier_raised = serial_carrier_raised,
699 .dtr_rts = serial_dtr_rts,
700};
701
Alan Coxfe1ae7f2009-09-19 13:13:33 -0700702/**
703 * serial_install - install tty
704 * @driver: the driver (USB in our case)
705 * @tty: the tty being created
706 *
707 * Create the termios objects for this tty. We use the default USB
708 * serial ones but permit them to be overriddenby serial->type->termios.
709 * This lets us remove all the ugly hackery
710 */
711
712static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
713{
714 int idx = tty->index;
715 struct usb_serial *serial;
716 int retval;
717
718 /* If the termios setup has yet to be done */
719 if (tty->driver->termios[idx] == NULL) {
720 /* perform the standard setup */
721 retval = tty_init_termios(tty);
722 if (retval)
723 return retval;
724 /* allow the driver to update it */
725 serial = usb_serial_get_by_index(tty->index);
726 if (serial->type->init_termios)
727 serial->type->init_termios(tty);
728 usb_serial_put(serial);
729 }
730 /* Final install (we use the default method) */
731 tty_driver_kref_get(driver);
732 tty->count++;
733 driver->ttys[idx] = tty;
734 return 0;
735}
736
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737int usb_serial_probe(struct usb_interface *interface,
738 const struct usb_device_id *id)
739{
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100740 struct usb_device *dev = interface_to_usbdev(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 struct usb_serial *serial = NULL;
742 struct usb_serial_port *port;
743 struct usb_host_interface *iface_desc;
744 struct usb_endpoint_descriptor *endpoint;
745 struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS];
746 struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS];
747 struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];
748 struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700749 struct usb_serial_driver *type = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 int retval;
Andre Hauptdd9ca5d2008-06-18 15:56:00 +0200751 unsigned int minor;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 int buffer_size;
753 int i;
754 int num_interrupt_in = 0;
755 int num_interrupt_out = 0;
756 int num_bulk_in = 0;
757 int num_bulk_out = 0;
758 int num_ports = 0;
759 int max_endpoints;
760
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100761 lock_kernel(); /* guard against unloading a serial driver module */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 type = search_serial_device(interface);
763 if (!type) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100764 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 dbg("none matched");
766 return -ENODEV;
767 }
768
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100769 serial = create_serial(dev, interface, type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 if (!serial) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100771 unlock_kernel();
Harvey Harrison441b62c2008-03-03 16:08:34 -0800772 dev_err(&interface->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 return -ENOMEM;
774 }
775
776 /* if this device type has a probe function, call it */
777 if (type->probe) {
778 const struct usb_device_id *id;
779
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700780 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100781 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100782 dev_err(&interface->dev,
783 "module get failed, exiting\n");
784 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785 return -EIO;
786 }
787
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100788 id = get_iface_id(type, interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 retval = type->probe(serial, id);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700790 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791
792 if (retval) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100793 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100794 dbg("sub driver rejected device");
795 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796 return retval;
797 }
798 }
799
800 /* descriptor matches, let's find the endpoints needed */
801 /* check out the endpoints */
802 iface_desc = interface->cur_altsetting;
803 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
804 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700805
806 if (usb_endpoint_is_bulk_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 /* we found a bulk in endpoint */
808 dbg("found bulk in on endpoint %d", i);
809 bulk_in_endpoint[num_bulk_in] = endpoint;
810 ++num_bulk_in;
811 }
812
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700813 if (usb_endpoint_is_bulk_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814 /* we found a bulk out endpoint */
815 dbg("found bulk out on endpoint %d", i);
816 bulk_out_endpoint[num_bulk_out] = endpoint;
817 ++num_bulk_out;
818 }
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700819
820 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 /* we found a interrupt in endpoint */
822 dbg("found interrupt in on endpoint %d", i);
823 interrupt_in_endpoint[num_interrupt_in] = endpoint;
824 ++num_interrupt_in;
825 }
826
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700827 if (usb_endpoint_is_int_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828 /* we found an interrupt out endpoint */
829 dbg("found interrupt out on endpoint %d", i);
830 interrupt_out_endpoint[num_interrupt_out] = endpoint;
831 ++num_interrupt_out;
832 }
833 }
834
835#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100836 /* BEGIN HORRIBLE HACK FOR PL2303 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 /* this is needed due to the looney way its endpoints are set up */
838 if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&
839 (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||
840 ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) &&
Johannes Steingraeber8fd80132006-09-16 16:17:34 +0200841 (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) ||
842 ((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) &&
Andreas Bombece816cf2008-09-14 01:58:55 +0200843 (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID)) ||
844 ((le16_to_cpu(dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) &&
845 (le16_to_cpu(dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_EF81))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 if (interface != dev->actconfig->interface[0]) {
847 /* check out the endpoints of the other interface*/
848 iface_desc = dev->actconfig->interface[0]->cur_altsetting;
849 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
850 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700851 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 /* we found a interrupt in endpoint */
853 dbg("found interrupt in for Prolific device on separate interface");
854 interrupt_in_endpoint[num_interrupt_in] = endpoint;
855 ++num_interrupt_in;
856 }
857 }
858 }
859
860 /* Now make sure the PL-2303 is configured correctly.
861 * If not, give up now and hope this hack will work
862 * properly during a later invocation of usb_serial_probe
863 */
864 if (num_bulk_in == 0 || num_bulk_out == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100865 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100867 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 return -ENODEV;
869 }
870 }
871 /* END HORRIBLE HACK FOR PL2303 */
872#endif
873
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874#ifdef CONFIG_USB_SERIAL_GENERIC
875 if (type == &usb_serial_generic_device) {
876 num_ports = num_bulk_out;
877 if (num_ports == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100878 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100879 dev_err(&interface->dev,
880 "Generic device with no bulk out, not allowed.\n");
881 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 return -EIO;
883 }
884 }
885#endif
886 if (!num_ports) {
887 /* if this device type has a calc_num_ports function, call it */
888 if (type->calc_num_ports) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700889 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100890 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100891 dev_err(&interface->dev,
892 "module get failed, exiting\n");
893 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 return -EIO;
895 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100896 num_ports = type->calc_num_ports(serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700897 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 }
899 if (!num_ports)
900 num_ports = type->num_ports;
901 }
902
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 serial->num_ports = num_ports;
904 serial->num_bulk_in = num_bulk_in;
905 serial->num_bulk_out = num_bulk_out;
906 serial->num_interrupt_in = num_interrupt_in;
907 serial->num_interrupt_out = num_interrupt_out;
908
Alan Stern063a2da2007-10-10 16:24:06 -0400909 /* found all that we need */
910 dev_info(&interface->dev, "%s converter detected\n",
911 type->description);
912
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 /* create our ports, we need as many as the max endpoints */
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100914 /* we don't use num_ports here because some devices have more
915 endpoint pairs than ports */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 max_endpoints = max(num_bulk_in, num_bulk_out);
917 max_endpoints = max(max_endpoints, num_interrupt_in);
918 max_endpoints = max(max_endpoints, num_interrupt_out);
919 max_endpoints = max(max_endpoints, (int)serial->num_ports);
920 serial->num_port_pointers = max_endpoints;
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100921 unlock_kernel();
922
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100923 dbg("%s - setting up %d port structures for this device",
924 __func__, max_endpoints);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 for (i = 0; i < max_endpoints; ++i) {
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100926 port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 if (!port)
928 goto probe_error;
Alan Cox4a90f092008-10-13 10:39:46 +0100929 tty_port_init(&port->port);
Alan Cox335f8512009-06-11 12:26:29 +0100930 port->port.ops = &serial_port_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 port->serial = serial;
Greg Kroah-Hartman507ca9b2005-04-23 12:49:16 -0700932 spin_lock_init(&port->lock);
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300933 mutex_init(&port->mutex);
David Howellsc4028952006-11-22 14:57:56 +0000934 INIT_WORK(&port->work, usb_serial_port_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 serial->port[i] = port;
Alan Stern41bd34d2009-09-01 11:38:34 -0400936 port->dev.parent = &interface->dev;
937 port->dev.driver = NULL;
938 port->dev.bus = &usb_serial_bus_type;
939 port->dev.release = &port_release;
940 device_initialize(&port->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941 }
942
943 /* set up the endpoint information */
944 for (i = 0; i < num_bulk_in; ++i) {
945 endpoint = bulk_in_endpoint[i];
946 port = serial->port[i];
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100947 port->read_urb = usb_alloc_urb(0, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948 if (!port->read_urb) {
949 dev_err(&interface->dev, "No free urbs available\n");
950 goto probe_error;
951 }
952 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
953 port->bulk_in_size = buffer_size;
954 port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100955 port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 if (!port->bulk_in_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100957 dev_err(&interface->dev,
958 "Couldn't allocate bulk_in_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959 goto probe_error;
960 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100961 usb_fill_bulk_urb(port->read_urb, dev,
962 usb_rcvbulkpipe(dev,
963 endpoint->bEndpointAddress),
964 port->bulk_in_buffer, buffer_size,
965 serial->type->read_bulk_callback, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966 }
967
968 for (i = 0; i < num_bulk_out; ++i) {
969 endpoint = bulk_out_endpoint[i];
970 port = serial->port[i];
971 port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
972 if (!port->write_urb) {
973 dev_err(&interface->dev, "No free urbs available\n");
974 goto probe_error;
975 }
976 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
977 port->bulk_out_size = buffer_size;
978 port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100979 port->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 if (!port->bulk_out_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100981 dev_err(&interface->dev,
982 "Couldn't allocate bulk_out_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 goto probe_error;
984 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100985 usb_fill_bulk_urb(port->write_urb, dev,
986 usb_sndbulkpipe(dev,
987 endpoint->bEndpointAddress),
988 port->bulk_out_buffer, buffer_size,
989 serial->type->write_bulk_callback, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 }
991
992 if (serial->type->read_int_callback) {
993 for (i = 0; i < num_interrupt_in; ++i) {
994 endpoint = interrupt_in_endpoint[i];
995 port = serial->port[i];
996 port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
997 if (!port->interrupt_in_urb) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100998 dev_err(&interface->dev,
999 "No free urbs available\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 goto probe_error;
1001 }
1002 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001003 port->interrupt_in_endpointAddress =
1004 endpoint->bEndpointAddress;
1005 port->interrupt_in_buffer = kmalloc(buffer_size,
1006 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 if (!port->interrupt_in_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001008 dev_err(&interface->dev,
1009 "Couldn't allocate interrupt_in_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010 goto probe_error;
1011 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001012 usb_fill_int_urb(port->interrupt_in_urb, dev,
1013 usb_rcvintpipe(dev,
1014 endpoint->bEndpointAddress),
1015 port->interrupt_in_buffer, buffer_size,
1016 serial->type->read_int_callback, port,
1017 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018 }
1019 } else if (num_interrupt_in) {
1020 dbg("the device claims to support interrupt in transfers, but read_int_callback is not defined");
1021 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001022
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 if (serial->type->write_int_callback) {
1024 for (i = 0; i < num_interrupt_out; ++i) {
1025 endpoint = interrupt_out_endpoint[i];
1026 port = serial->port[i];
1027 port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
1028 if (!port->interrupt_out_urb) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001029 dev_err(&interface->dev,
1030 "No free urbs available\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 goto probe_error;
1032 }
1033 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
1034 port->interrupt_out_size = buffer_size;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001035 port->interrupt_out_endpointAddress =
1036 endpoint->bEndpointAddress;
1037 port->interrupt_out_buffer = kmalloc(buffer_size,
1038 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 if (!port->interrupt_out_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001040 dev_err(&interface->dev,
1041 "Couldn't allocate interrupt_out_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 goto probe_error;
1043 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001044 usb_fill_int_urb(port->interrupt_out_urb, dev,
1045 usb_sndintpipe(dev,
1046 endpoint->bEndpointAddress),
1047 port->interrupt_out_buffer, buffer_size,
1048 serial->type->write_int_callback, port,
1049 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 }
1051 } else if (num_interrupt_out) {
1052 dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined");
1053 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001054
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 /* if this device type has an attach function, call it */
1056 if (type->attach) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -07001057 if (!try_module_get(type->driver.owner)) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001058 dev_err(&interface->dev,
1059 "module get failed, exiting\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060 goto probe_error;
1061 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001062 retval = type->attach(serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -07001063 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 if (retval < 0)
1065 goto probe_error;
1066 if (retval > 0) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001067 /* quietly accept this device, but don't bind to a
1068 serial port as it's about to disappear */
Alan Stern0a3c8542009-05-27 11:25:52 -04001069 serial->num_ports = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 goto exit;
1071 }
1072 }
1073
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001074 if (get_free_serial(serial, num_ports, &minor) == NULL) {
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001075 dev_err(&interface->dev, "No more free serial devices\n");
1076 goto probe_error;
1077 }
Oliver Neukumc744f992007-02-26 15:43:00 +01001078 serial->minor = minor;
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001079
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 /* register all of the individual ports with the driver core */
1081 for (i = 0; i < num_ports; ++i) {
1082 port = serial->port[i];
Kay Sievers0031a062008-05-02 06:02:41 +02001083 dev_set_name(&port->dev, "ttyUSB%d", port->number);
Kay Sievers7071a3c2008-05-02 06:02:41 +02001084 dbg ("%s - registering %s", __func__, dev_name(&port->dev));
Alan Sternc706ebd2009-06-02 11:54:11 -04001085 port->dev_state = PORT_REGISTERING;
Alan Stern41bd34d2009-09-01 11:38:34 -04001086 retval = device_add(&port->dev);
Alan Sternc706ebd2009-06-02 11:54:11 -04001087 if (retval) {
Greg Kroah-Hartman13f4db92006-08-28 11:43:25 -07001088 dev_err(&port->dev, "Error registering port device, "
1089 "continuing\n");
Alan Sternc706ebd2009-06-02 11:54:11 -04001090 port->dev_state = PORT_UNREGISTERED;
1091 } else {
1092 port->dev_state = PORT_REGISTERED;
1093 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 }
1095
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001096 usb_serial_console_init(debug, minor);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097
1098exit:
1099 /* success */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001100 usb_set_intfdata(interface, serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101 return 0;
1102
1103probe_error:
Alan Stern41bd34d2009-09-01 11:38:34 -04001104 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105 return -EIO;
1106}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001107EXPORT_SYMBOL_GPL(usb_serial_probe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108
1109void usb_serial_disconnect(struct usb_interface *interface)
1110{
1111 int i;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001112 struct usb_serial *serial = usb_get_intfdata(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 struct device *dev = &interface->dev;
1114 struct usb_serial_port *port;
1115
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +02001116 usb_serial_console_disconnect(serial);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001117 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001119 mutex_lock(&serial->disc_mutex);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001120 usb_set_intfdata(interface, NULL);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001121 /* must set a flag, to signal subdrivers */
1122 serial->disconnected = 1;
Alan Stern2d931482009-04-14 11:31:02 -04001123 mutex_unlock(&serial->disc_mutex);
1124
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001125 for (i = 0; i < serial->num_ports; ++i) {
1126 port = serial->port[i];
1127 if (port) {
Alan Cox4a90f092008-10-13 10:39:46 +01001128 struct tty_struct *tty = tty_port_tty_get(&port->port);
1129 if (tty) {
Alan Coxd2b39182009-09-19 13:13:23 -07001130 tty_vhangup(tty);
Alan Cox4a90f092008-10-13 10:39:46 +01001131 tty_kref_put(tty);
1132 }
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001133 kill_traffic(port);
Alan Stern2d931482009-04-14 11:31:02 -04001134 cancel_work_sync(&port->work);
Alan Sternc706ebd2009-06-02 11:54:11 -04001135 if (port->dev_state == PORT_REGISTERED) {
1136
1137 /* Make sure the port is bound so that the
1138 * driver's port_remove method is called.
1139 */
1140 if (!port->dev.driver) {
1141 int rc;
1142
1143 port->dev.driver =
1144 &serial->type->driver;
1145 rc = device_bind_driver(&port->dev);
1146 }
1147 port->dev_state = PORT_UNREGISTERING;
1148 device_del(&port->dev);
1149 port->dev_state = PORT_UNREGISTERED;
1150 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152 }
Alan Sternf9c99bb2009-06-02 11:53:55 -04001153 serial->type->disconnect(serial);
Alan Stern2d931482009-04-14 11:31:02 -04001154
Alan Stern41bd34d2009-09-01 11:38:34 -04001155 /* let the last holder of this object cause it to be cleaned up */
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001156 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 dev_info(dev, "device disconnected\n");
1158}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001159EXPORT_SYMBOL_GPL(usb_serial_disconnect);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160
Oliver Neukumec225592007-04-27 20:54:57 +02001161int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
1162{
1163 struct usb_serial *serial = usb_get_intfdata(intf);
1164 struct usb_serial_port *port;
1165 int i, r = 0;
1166
Oliver Neukumf8bece82009-02-05 16:54:25 +01001167 serial->suspending = 1;
1168
Oliver Neukume31c1882007-07-23 08:58:39 +02001169 for (i = 0; i < serial->num_ports; ++i) {
1170 port = serial->port[i];
1171 if (port)
1172 kill_traffic(port);
Oliver Neukumec225592007-04-27 20:54:57 +02001173 }
1174
1175 if (serial->type->suspend)
Oliver Neukume31c1882007-07-23 08:58:39 +02001176 r = serial->type->suspend(serial, message);
Oliver Neukumec225592007-04-27 20:54:57 +02001177
1178 return r;
1179}
1180EXPORT_SYMBOL(usb_serial_suspend);
1181
1182int usb_serial_resume(struct usb_interface *intf)
1183{
1184 struct usb_serial *serial = usb_get_intfdata(intf);
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001185 int rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001186
Oliver Neukumf8bece82009-02-05 16:54:25 +01001187 serial->suspending = 0;
Sarah Sharp8abaee22007-10-25 10:58:43 -07001188 if (serial->type->resume)
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001189 rv = serial->type->resume(serial);
1190 else
1191 rv = usb_serial_generic_resume(serial);
Oliver Neukumf8bece82009-02-05 16:54:25 +01001192
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001193 return rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001194}
1195EXPORT_SYMBOL(usb_serial_resume);
1196
Jeff Dikeb68e31d2006-10-02 02:17:18 -07001197static const struct tty_operations serial_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 .open = serial_open,
1199 .close = serial_close,
1200 .write = serial_write,
Alan Cox335f8512009-06-11 12:26:29 +01001201 .hangup = serial_hangup,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202 .write_room = serial_write_room,
1203 .ioctl = serial_ioctl,
1204 .set_termios = serial_set_termios,
1205 .throttle = serial_throttle,
1206 .unthrottle = serial_unthrottle,
1207 .break_ctl = serial_break,
1208 .chars_in_buffer = serial_chars_in_buffer,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 .tiocmget = serial_tiocmget,
1210 .tiocmset = serial_tiocmset,
Alan Coxfe1ae7f2009-09-19 13:13:33 -07001211 .shutdown = serial_do_free,
1212 .install = serial_install,
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -07001213 .proc_fops = &serial_proc_fops,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214};
1215
Alan Cox335f8512009-06-11 12:26:29 +01001216
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217struct tty_driver *usb_serial_tty_driver;
1218
1219static int __init usb_serial_init(void)
1220{
1221 int i;
1222 int result;
1223
1224 usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS);
1225 if (!usb_serial_tty_driver)
1226 return -ENOMEM;
1227
1228 /* Initialize our global data */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001229 for (i = 0; i < SERIAL_TTY_MINORS; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230 serial_table[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231
1232 result = bus_register(&usb_serial_bus_type);
1233 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001234 printk(KERN_ERR "usb-serial: %s - registering bus driver "
1235 "failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236 goto exit_bus;
1237 }
1238
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239 usb_serial_tty_driver->owner = THIS_MODULE;
1240 usb_serial_tty_driver->driver_name = "usbserial";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241 usb_serial_tty_driver->name = "ttyUSB";
1242 usb_serial_tty_driver->major = SERIAL_TTY_MAJOR;
1243 usb_serial_tty_driver->minor_start = 0;
1244 usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
1245 usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001246 usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW |
1247 TTY_DRIVER_DYNAMIC_DEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248 usb_serial_tty_driver->init_termios = tty_std_termios;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001249 usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD
1250 | HUPCL | CLOCAL;
Alan Coxa5b6f602008-04-08 17:16:06 +01001251 usb_serial_tty_driver->init_termios.c_ispeed = 9600;
1252 usb_serial_tty_driver->init_termios.c_ospeed = 9600;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253 tty_set_operations(usb_serial_tty_driver, &serial_ops);
1254 result = tty_register_driver(usb_serial_tty_driver);
1255 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001256 printk(KERN_ERR "usb-serial: %s - tty_register_driver failed\n",
1257 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 goto exit_reg_driver;
1259 }
1260
1261 /* register the USB driver */
1262 result = usb_register(&usb_serial_driver);
1263 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001264 printk(KERN_ERR "usb-serial: %s - usb_register failed\n",
1265 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 goto exit_tty;
1267 }
1268
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001269 /* register the generic driver, if we should */
1270 result = usb_serial_generic_register(debug);
1271 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001272 printk(KERN_ERR "usb-serial: %s - registering generic "
1273 "driver failed\n", __func__);
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001274 goto exit_generic;
1275 }
1276
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001277 printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278
1279 return result;
1280
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001281exit_generic:
1282 usb_deregister(&usb_serial_driver);
1283
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284exit_tty:
1285 tty_unregister_driver(usb_serial_tty_driver);
1286
1287exit_reg_driver:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288 bus_unregister(&usb_serial_bus_type);
1289
1290exit_bus:
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001291 printk(KERN_ERR "usb-serial: %s - returning with error %d\n",
1292 __func__, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293 put_tty_driver(usb_serial_tty_driver);
1294 return result;
1295}
1296
1297
1298static void __exit usb_serial_exit(void)
1299{
1300 usb_serial_console_exit();
1301
1302 usb_serial_generic_deregister();
1303
1304 usb_deregister(&usb_serial_driver);
1305 tty_unregister_driver(usb_serial_tty_driver);
1306 put_tty_driver(usb_serial_tty_driver);
1307 bus_unregister(&usb_serial_bus_type);
1308}
1309
1310
1311module_init(usb_serial_init);
1312module_exit(usb_serial_exit);
1313
1314#define set_to_generic_if_null(type, function) \
1315 do { \
1316 if (!type->function) { \
1317 type->function = usb_serial_generic_##function; \
1318 dbg("Had to override the " #function \
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001319 " usb serial operation with the generic one.");\
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 } \
1321 } while (0)
1322
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001323static void fixup_generic(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324{
1325 set_to_generic_if_null(device, open);
1326 set_to_generic_if_null(device, write);
1327 set_to_generic_if_null(device, close);
1328 set_to_generic_if_null(device, write_room);
1329 set_to_generic_if_null(device, chars_in_buffer);
1330 set_to_generic_if_null(device, read_bulk_callback);
1331 set_to_generic_if_null(device, write_bulk_callback);
Alan Sternf9c99bb2009-06-02 11:53:55 -04001332 set_to_generic_if_null(device, disconnect);
1333 set_to_generic_if_null(device, release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334}
1335
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001336int usb_serial_register(struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001338 /* must be called with BKL held */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339 int retval;
1340
Dave Younge4abe662009-02-14 21:21:13 +08001341 if (usb_disabled())
1342 return -ENODEV;
1343
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001344 fixup_generic(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001346 if (!driver->description)
1347 driver->description = driver->driver.name;
1348
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 /* Add this device to our list of devices */
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001350 list_add(&driver->driver_list, &usb_serial_driver_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001352 retval = usb_serial_bus_register(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353 if (retval) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001354 printk(KERN_ERR "usb-serial: problem %d when registering "
1355 "driver %s\n", retval, driver->description);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001356 list_del(&driver->driver_list);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001357 } else
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001358 printk(KERN_INFO "USB Serial support registered for %s\n",
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001359 driver->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360
1361 return retval;
1362}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001363EXPORT_SYMBOL_GPL(usb_serial_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364
1365
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001366void usb_serial_deregister(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001368 /* must be called with BKL held */
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001369 printk(KERN_INFO "USB Serial deregistering driver %s\n",
1370 device->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 list_del(&device->driver_list);
1372 usb_serial_bus_deregister(device);
1373}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374EXPORT_SYMBOL_GPL(usb_serial_deregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375
1376/* Module information */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001377MODULE_AUTHOR(DRIVER_AUTHOR);
1378MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379MODULE_LICENSE("GPL");
1380
1381module_param(debug, bool, S_IRUGO | S_IWUSR);
1382MODULE_PARM_DESC(debug, "Debug enabled or not");