blob: f331e2bde88acbb0c2b4e36fee01eff68ffc9b5c [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>
24#include <linux/tty.h>
25#include <linux/tty_driver.h>
26#include <linux/tty_flip.h>
27#include <linux/module.h>
28#include <linux/moduleparam.h>
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -070029#include <linux/seq_file.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <linux/spinlock.h>
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -030031#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include <linux/list.h>
Alan Coxa8d6f0a2008-07-22 11:12:24 +010033#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include <linux/usb.h>
Greg Kroah-Hartmana9698882006-07-11 21:22:58 -070035#include <linux/usb/serial.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#include "pl2303.h"
37
38/*
39 * Version Information
40 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/"
42#define DRIVER_DESC "USB Serial Driver core"
43
Pete Zaitcev34f8e762006-06-21 15:00:45 -070044static void port_free(struct usb_serial_port *port);
45
Linus Torvalds1da177e2005-04-16 15:20:36 -070046/* 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
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144 /* If this is a "fake" port, we have to clean it up here, as it will
145 * not get cleaned up in port_release() as it was never registered with
146 * the driver core */
147 if (serial->num_ports < serial->num_port_pointers) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100148 for (i = serial->num_ports;
149 i < serial->num_port_pointers; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150 port = serial->port[i];
151 if (!port)
152 continue;
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700153 port_free(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154 }
155 }
156
157 usb_put_dev(serial->dev);
158
159 /* free up any memory that we allocated */
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100160 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161}
162
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200163void usb_serial_put(struct usb_serial *serial)
164{
Oliver Neukum3ddad822007-07-24 15:13:42 +0200165 mutex_lock(&table_lock);
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200166 kref_put(&serial->kref, destroy_serial);
Oliver Neukum3ddad822007-07-24 15:13:42 +0200167 mutex_unlock(&table_lock);
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200168}
169
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170/*****************************************************************************
171 * Driver tty interface functions
172 *****************************************************************************/
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100173static int serial_open (struct tty_struct *tty, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174{
175 struct usb_serial *serial;
176 struct usb_serial_port *port;
177 unsigned int portNumber;
Alan Stern2d931482009-04-14 11:31:02 -0400178 int retval = 0;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100179
Harvey Harrison441b62c2008-03-03 16:08:34 -0800180 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181
182 /* get the serial object associated with this tty pointer */
183 serial = usb_serial_get_by_index(tty->index);
184 if (!serial) {
185 tty->driver_data = NULL;
186 return -ENODEV;
187 }
188
Alan Stern2d931482009-04-14 11:31:02 -0400189 mutex_lock(&serial->disc_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190 portNumber = tty->index - serial->minor;
191 port = serial->port[portNumber];
Alan Stern2d931482009-04-14 11:31:02 -0400192 if (!port || serial->disconnected)
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300193 retval = -ENODEV;
Alan Stern2d931482009-04-14 11:31:02 -0400194 else
195 get_device(&port->dev);
196 /*
197 * Note: Our locking order requirement does not allow port->mutex
198 * to be acquired while serial->disc_mutex is held.
199 */
200 mutex_unlock(&serial->disc_mutex);
201 if (retval)
202 goto bailout_serial_put;
James Woodcock331879f2009-02-11 15:06:53 +0000203
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300204 if (mutex_lock_interruptible(&port->mutex)) {
205 retval = -ERESTARTSYS;
Alan Stern2d931482009-04-14 11:31:02 -0400206 goto bailout_port_put;
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300207 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100208
Alan Cox95da3102008-07-22 11:09:07 +0100209 ++port->port.count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210
Paul Fulghumca854852006-04-13 22:28:17 +0200211 /* set up our port structure making the tty driver
212 * remember our port object, and us it */
213 tty->driver_data = port;
Alan Cox4a90f092008-10-13 10:39:46 +0100214 tty_port_tty_set(&port->port, tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215
Alan Cox95da3102008-07-22 11:09:07 +0100216 if (port->port.count == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217
218 /* lock this module before we call it
219 * this may fail, which means we must bail out,
220 * safe because we are called with BKL held */
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700221 if (!try_module_get(serial->type->driver.owner)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222 retval = -ENODEV;
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300223 goto bailout_mutex_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 }
225
Alan Stern2d931482009-04-14 11:31:02 -0400226 mutex_lock(&serial->disc_mutex);
227 if (serial->disconnected)
228 retval = -ENODEV;
229 else
230 retval = usb_autopm_get_interface(serial->interface);
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800231 if (retval)
232 goto bailout_module_put;
Alan Stern2d931482009-04-14 11:31:02 -0400233
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100234 /* only call the device specific open if this
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 * is the first time the port is opened */
Alan Cox95da3102008-07-22 11:09:07 +0100236 retval = serial->type->open(tty, port, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 if (retval)
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800238 goto bailout_interface_put;
Alan Stern2d931482009-04-14 11:31:02 -0400239 mutex_unlock(&serial->disc_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 }
241
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300242 mutex_unlock(&port->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 return 0;
244
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800245bailout_interface_put:
246 usb_autopm_put_interface(serial->interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247bailout_module_put:
Alan Stern2d931482009-04-14 11:31:02 -0400248 mutex_unlock(&serial->disc_mutex);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700249 module_put(serial->type->driver.owner);
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300250bailout_mutex_unlock:
Alan Cox95da3102008-07-22 11:09:07 +0100251 port->port.count = 0;
Frank Gevaertsb059c812006-06-14 15:52:05 +0200252 tty->driver_data = NULL;
Alan Cox4a90f092008-10-13 10:39:46 +0100253 tty_port_tty_set(&port->port, NULL);
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300254 mutex_unlock(&port->mutex);
Alan Stern2d931482009-04-14 11:31:02 -0400255bailout_port_put:
256 put_device(&port->dev);
257bailout_serial_put:
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200258 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 return retval;
260}
261
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100262static void serial_close(struct tty_struct *tty, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200264 struct usb_serial_port *port = tty->driver_data;
Alan Stern2d931482009-04-14 11:31:02 -0400265 struct usb_serial *serial;
266 struct module *owner;
267 int count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268
269 if (!port)
270 return;
271
Harvey Harrison441b62c2008-03-03 16:08:34 -0800272 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300274 mutex_lock(&port->mutex);
Alan Stern2d931482009-04-14 11:31:02 -0400275 serial = port->serial;
276 owner = serial->type->driver.owner;
Luiz Fernando Capitulino8a4613f2005-11-28 19:16:07 -0200277
Alan Cox95da3102008-07-22 11:09:07 +0100278 if (port->port.count == 0) {
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300279 mutex_unlock(&port->mutex);
Greg Kroah-Hartman91c0bce2006-03-06 13:25:52 -0800280 return;
281 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282
Alan Cox4bd43f22009-01-02 13:44:04 +0000283 if (port->port.count == 1)
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100284 /* only call the device specific close if this
Alan Cox4bd43f22009-01-02 13:44:04 +0000285 * port is being closed by the last owner. Ensure we do
286 * this before we drop the port count. The call is protected
287 * by the port mutex
288 */
Alan Stern2d931482009-04-14 11:31:02 -0400289 serial->type->close(tty, port, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290
Alan Cox4bd43f22009-01-02 13:44:04 +0000291 if (port->port.count == (port->console ? 2 : 1)) {
Alan Cox4a90f092008-10-13 10:39:46 +0100292 struct tty_struct *tty = tty_port_tty_get(&port->port);
293 if (tty) {
Alan Cox4bd43f22009-01-02 13:44:04 +0000294 /* We must do this before we drop the port count to
295 zero. */
Alan Cox4a90f092008-10-13 10:39:46 +0100296 if (tty->driver_data)
297 tty->driver_data = NULL;
298 tty_port_tty_set(&port->port, NULL);
Alan Coxfce48772008-10-30 15:54:12 +0000299 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301 }
302
Alan Cox4bd43f22009-01-02 13:44:04 +0000303 --port->port.count;
Alan Stern2d931482009-04-14 11:31:02 -0400304 count = port->port.count;
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300305 mutex_unlock(&port->mutex);
Alan Stern2d931482009-04-14 11:31:02 -0400306 put_device(&port->dev);
307
308 /* Mustn't dereference port any more */
309 if (count == 0) {
310 mutex_lock(&serial->disc_mutex);
311 if (!serial->disconnected)
312 usb_autopm_put_interface(serial->interface);
313 mutex_unlock(&serial->disc_mutex);
314 }
315 usb_serial_put(serial);
316
317 /* Mustn't dereference serial any more */
318 if (count == 0)
319 module_put(owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320}
321
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100322static int serial_write(struct tty_struct *tty, const unsigned char *buf,
323 int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200325 struct usb_serial_port *port = tty->driver_data;
Oliver Neukum3ff4fd92007-01-13 07:32:27 +0100326 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327
Alan Coxf34d7a52008-04-30 00:54:13 -0700328 if (port->serial->dev->state == USB_STATE_NOTATTACHED)
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200329 goto exit;
330
Harvey Harrison441b62c2008-03-03 16:08:34 -0800331 dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332
Alan Cox95da3102008-07-22 11:09:07 +0100333 /* count is managed under the mutex lock for the tty so cannot
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100334 drop to zero until after the last close completes */
Alan Cox95da3102008-07-22 11:09:07 +0100335 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336
337 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100338 retval = port->serial->type->write(tty, port, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339
340exit:
341 return retval;
342}
343
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100344static int serial_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200346 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800347 dbg("%s - port %d", __func__, port->number);
Alan Cox95da3102008-07-22 11:09:07 +0100348 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100350 return port->serial->type->write_room(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351}
352
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100353static int serial_chars_in_buffer(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200355 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800356 dbg("%s = port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357
Alan Cox95da3102008-07-22 11:09:07 +0100358 WARN_ON(!port->port.count);
Alan Coxeff69372009-01-02 13:47:06 +0000359 /* if the device was unplugged then any remaining characters
360 fell out of the connector ;) */
361 if (port->serial->disconnected)
362 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100364 return port->serial->type->chars_in_buffer(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365}
366
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100367static void serial_throttle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200369 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800370 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371
Alan Cox95da3102008-07-22 11:09:07 +0100372 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 /* pass on to the driver specific version of this function */
374 if (port->serial->type->throttle)
Alan Cox95da3102008-07-22 11:09:07 +0100375 port->serial->type->throttle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376}
377
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100378static void serial_unthrottle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200380 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800381 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382
Alan Cox95da3102008-07-22 11:09:07 +0100383 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 /* pass on to the driver specific version of this function */
385 if (port->serial->type->unthrottle)
Alan Cox95da3102008-07-22 11:09:07 +0100386 port->serial->type->unthrottle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387}
388
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100389static int serial_ioctl(struct tty_struct *tty, struct file *file,
390 unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200392 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 int retval = -ENODEV;
394
Harvey Harrison441b62c2008-03-03 16:08:34 -0800395 dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396
Alan Cox95da3102008-07-22 11:09:07 +0100397 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100399 /* pass on to the driver specific version of this function
400 if it is available */
Alan Coxf34d7a52008-04-30 00:54:13 -0700401 if (port->serial->type->ioctl) {
Alan Cox95da3102008-07-22 11:09:07 +0100402 retval = port->serial->type->ioctl(tty, file, cmd, arg);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100403 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404 retval = -ENOIOCTLCMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 return retval;
406}
407
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100408static void serial_set_termios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200410 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800411 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412
Alan Cox95da3102008-07-22 11:09:07 +0100413 WARN_ON(!port->port.count);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100414 /* pass on to the driver specific version of this function
415 if it is available */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 if (port->serial->type->set_termios)
Alan Cox95da3102008-07-22 11:09:07 +0100417 port->serial->type->set_termios(tty, port, old);
Alan Cox33785092007-10-18 01:24:22 -0700418 else
419 tty_termios_copy_hw(tty->termios, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420}
421
Alan Cox9e989662008-07-22 11:18:03 +0100422static int serial_break(struct tty_struct *tty, int break_state)
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
Harvey Harrison441b62c2008-03-03 16:08:34 -0800426 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427
Alan Cox95da3102008-07-22 11:09:07 +0100428 WARN_ON(!port->port.count);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100429 /* pass on to the driver specific version of this function
430 if it is available */
Alan Cox6b447f042009-01-02 13:48:56 +0000431 if (port->serial->type->break_ctl)
Alan Cox95da3102008-07-22 11:09:07 +0100432 port->serial->type->break_ctl(tty, break_state);
Alan Cox9e989662008-07-22 11:18:03 +0100433 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434}
435
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700436static int serial_proc_show(struct seq_file *m, void *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437{
438 struct usb_serial *serial;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 char tmp[40];
441
Harvey Harrison441b62c2008-03-03 16:08:34 -0800442 dbg("%s", __func__);
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700443 seq_puts(m, "usbserinfo:1.0 driver:2.0\n");
444 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 serial = usb_serial_get_by_index(i);
446 if (serial == NULL)
447 continue;
448
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700449 seq_printf(m, "%d:", i);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700450 if (serial->type->driver.owner)
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700451 seq_printf(m, " module:%s",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100452 module_name(serial->type->driver.owner));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700453 seq_printf(m, " name:\"%s\"",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100454 serial->type->description);
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700455 seq_printf(m, " vendor:%04x product:%04x",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100456 le16_to_cpu(serial->dev->descriptor.idVendor),
457 le16_to_cpu(serial->dev->descriptor.idProduct));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700458 seq_printf(m, " num_ports:%d", serial->num_ports);
459 seq_printf(m, " port:%d", i - serial->minor + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 usb_make_path(serial->dev, tmp, sizeof(tmp));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700461 seq_printf(m, " path:%s", tmp);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100462
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700463 seq_putc(m, '\n');
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200464 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465 }
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700466 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467}
468
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700469static int serial_proc_open(struct inode *inode, struct file *file)
470{
471 return single_open(file, serial_proc_show, NULL);
472}
473
474static const struct file_operations serial_proc_fops = {
475 .owner = THIS_MODULE,
476 .open = serial_proc_open,
477 .read = seq_read,
478 .llseek = seq_lseek,
479 .release = single_release,
480};
481
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100482static int serial_tiocmget(struct tty_struct *tty, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200484 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485
Harvey Harrison441b62c2008-03-03 16:08:34 -0800486 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487
Alan Cox95da3102008-07-22 11:09:07 +0100488 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489 if (port->serial->type->tiocmget)
Alan Cox95da3102008-07-22 11:09:07 +0100490 return port->serial->type->tiocmget(tty, file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491 return -EINVAL;
492}
493
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100494static int serial_tiocmset(struct tty_struct *tty, struct file *file,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 unsigned int set, unsigned int clear)
496{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200497 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498
Harvey Harrison441b62c2008-03-03 16:08:34 -0800499 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500
Alan Cox95da3102008-07-22 11:09:07 +0100501 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 if (port->serial->type->tiocmset)
Alan Cox95da3102008-07-22 11:09:07 +0100503 return port->serial->type->tiocmset(tty, file, set, clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 return -EINVAL;
505}
506
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700507/*
508 * We would be calling tty_wakeup here, but unfortunately some line
509 * disciplines have an annoying habit of calling tty->write from
510 * the write wakeup callback (e.g. n_hdlc.c).
511 */
512void usb_serial_port_softint(struct usb_serial_port *port)
513{
514 schedule_work(&port->work);
515}
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100516EXPORT_SYMBOL_GPL(usb_serial_port_softint);
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700517
David Howellsc4028952006-11-22 14:57:56 +0000518static void usb_serial_port_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519{
David Howellsc4028952006-11-22 14:57:56 +0000520 struct usb_serial_port *port =
521 container_of(work, struct usb_serial_port, work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 struct tty_struct *tty;
523
Harvey Harrison441b62c2008-03-03 16:08:34 -0800524 dbg("%s - port %d", __func__, port->number);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100525
Alan Cox4a90f092008-10-13 10:39:46 +0100526 tty = tty_port_tty_get(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 if (!tty)
528 return;
529
530 tty_wakeup(tty);
Alan Cox4a90f092008-10-13 10:39:46 +0100531 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532}
533
534static void port_release(struct device *dev)
535{
536 struct usb_serial_port *port = to_usb_serial_port(dev);
537
Kay Sievers7071a3c2008-05-02 06:02:41 +0200538 dbg ("%s - %s", __func__, dev_name(dev));
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700539 port_free(port);
540}
541
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100542static void kill_traffic(struct usb_serial_port *port)
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700543{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 usb_kill_urb(port->write_urb);
Oliver Neukum5adceac2007-08-17 14:01:38 +0200546 /*
547 * This is tricky.
548 * Some drivers submit the read_urb in the
549 * handler for the write_urb or vice versa
550 * this order determines the order in which
551 * usb_kill_urb() must be used to reliably
552 * kill the URBs. As it is unknown here,
553 * both orders must be used in turn.
554 * The call below is not redundant.
555 */
556 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 usb_kill_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 usb_kill_urb(port->interrupt_out_urb);
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100559}
560
561static void port_free(struct usb_serial_port *port)
562{
Alan Stern2d931482009-04-14 11:31:02 -0400563 /*
564 * Stop all the traffic before cancelling the work, so that
565 * nobody will restart it by calling usb_serial_port_softint.
566 */
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100567 kill_traffic(port);
Alan Stern2d931482009-04-14 11:31:02 -0400568 cancel_work_sync(&port->work);
569
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100570 usb_free_urb(port->read_urb);
571 usb_free_urb(port->write_urb);
572 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 usb_free_urb(port->interrupt_out_urb);
574 kfree(port->bulk_in_buffer);
575 kfree(port->bulk_out_buffer);
576 kfree(port->interrupt_in_buffer);
577 kfree(port->interrupt_out_buffer);
578 kfree(port);
579}
580
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100581static struct usb_serial *create_serial(struct usb_device *dev,
582 struct usb_interface *interface,
583 struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584{
585 struct usb_serial *serial;
586
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100587 serial = kzalloc(sizeof(*serial), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 if (!serial) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800589 dev_err(&dev->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 return NULL;
591 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592 serial->dev = usb_get_dev(dev);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700593 serial->type = driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 serial->interface = interface;
595 kref_init(&serial->kref);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +0100596 mutex_init(&serial->disc_mutex);
Alan Stern0282b7f2008-07-29 12:01:04 -0400597 serial->minor = SERIAL_TTY_NO_MINOR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598
599 return serial;
600}
601
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100602static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf,
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100603 struct usb_serial_driver *drv)
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100604{
605 struct usb_dynid *dynid;
606
607 spin_lock(&drv->dynids.lock);
608 list_for_each_entry(dynid, &drv->dynids.list, node) {
609 if (usb_match_one_id(intf, &dynid->id)) {
610 spin_unlock(&drv->dynids.lock);
611 return &dynid->id;
612 }
613 }
614 spin_unlock(&drv->dynids.lock);
615 return NULL;
616}
617
618static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv,
619 struct usb_interface *intf)
620{
621 const struct usb_device_id *id;
622
623 id = usb_match_id(intf, drv->id_table);
624 if (id) {
625 dbg("static descriptor matches");
626 goto exit;
627 }
628 id = match_dynamic_id(intf, drv);
629 if (id)
630 dbg("dynamic descriptor matches");
631exit:
632 return id;
633}
634
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100635static struct usb_serial_driver *search_serial_device(
636 struct usb_interface *iface)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 const struct usb_device_id *id;
Alan Stern063a2da2007-10-10 16:24:06 -0400639 struct usb_serial_driver *drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640
Adrian Bunk93b1fae2006-01-10 00:13:33 +0100641 /* Check if the usb id matches a known device */
Alan Stern063a2da2007-10-10 16:24:06 -0400642 list_for_each_entry(drv, &usb_serial_driver_list, driver_list) {
643 id = get_iface_id(drv, iface);
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100644 if (id)
Alan Stern063a2da2007-10-10 16:24:06 -0400645 return drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 }
647
648 return NULL;
649}
650
651int usb_serial_probe(struct usb_interface *interface,
652 const struct usb_device_id *id)
653{
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100654 struct usb_device *dev = interface_to_usbdev(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655 struct usb_serial *serial = NULL;
656 struct usb_serial_port *port;
657 struct usb_host_interface *iface_desc;
658 struct usb_endpoint_descriptor *endpoint;
659 struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS];
660 struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS];
661 struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];
662 struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700663 struct usb_serial_driver *type = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 int retval;
Andre Hauptdd9ca5d2008-06-18 15:56:00 +0200665 unsigned int minor;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 int buffer_size;
667 int i;
668 int num_interrupt_in = 0;
669 int num_interrupt_out = 0;
670 int num_bulk_in = 0;
671 int num_bulk_out = 0;
672 int num_ports = 0;
673 int max_endpoints;
674
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100675 lock_kernel(); /* guard against unloading a serial driver module */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676 type = search_serial_device(interface);
677 if (!type) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100678 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679 dbg("none matched");
680 return -ENODEV;
681 }
682
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100683 serial = create_serial(dev, interface, type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 if (!serial) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100685 unlock_kernel();
Harvey Harrison441b62c2008-03-03 16:08:34 -0800686 dev_err(&interface->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 return -ENOMEM;
688 }
689
690 /* if this device type has a probe function, call it */
691 if (type->probe) {
692 const struct usb_device_id *id;
693
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700694 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100695 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100696 dev_err(&interface->dev,
697 "module get failed, exiting\n");
698 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699 return -EIO;
700 }
701
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100702 id = get_iface_id(type, interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 retval = type->probe(serial, id);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700704 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705
706 if (retval) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100707 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100708 dbg("sub driver rejected device");
709 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710 return retval;
711 }
712 }
713
714 /* descriptor matches, let's find the endpoints needed */
715 /* check out the endpoints */
716 iface_desc = interface->cur_altsetting;
717 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
718 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700719
720 if (usb_endpoint_is_bulk_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 /* we found a bulk in endpoint */
722 dbg("found bulk in on endpoint %d", i);
723 bulk_in_endpoint[num_bulk_in] = endpoint;
724 ++num_bulk_in;
725 }
726
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700727 if (usb_endpoint_is_bulk_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 /* we found a bulk out endpoint */
729 dbg("found bulk out on endpoint %d", i);
730 bulk_out_endpoint[num_bulk_out] = endpoint;
731 ++num_bulk_out;
732 }
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700733
734 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 /* we found a interrupt in endpoint */
736 dbg("found interrupt in on endpoint %d", i);
737 interrupt_in_endpoint[num_interrupt_in] = endpoint;
738 ++num_interrupt_in;
739 }
740
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700741 if (usb_endpoint_is_int_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 /* we found an interrupt out endpoint */
743 dbg("found interrupt out on endpoint %d", i);
744 interrupt_out_endpoint[num_interrupt_out] = endpoint;
745 ++num_interrupt_out;
746 }
747 }
748
749#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100750 /* BEGIN HORRIBLE HACK FOR PL2303 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 /* this is needed due to the looney way its endpoints are set up */
752 if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&
753 (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||
754 ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) &&
Johannes Steingraeber8fd80132006-09-16 16:17:34 +0200755 (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) ||
756 ((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) &&
Andreas Bombece816cf2008-09-14 01:58:55 +0200757 (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID)) ||
758 ((le16_to_cpu(dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) &&
759 (le16_to_cpu(dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_EF81))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 if (interface != dev->actconfig->interface[0]) {
761 /* check out the endpoints of the other interface*/
762 iface_desc = dev->actconfig->interface[0]->cur_altsetting;
763 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
764 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700765 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 /* we found a interrupt in endpoint */
767 dbg("found interrupt in for Prolific device on separate interface");
768 interrupt_in_endpoint[num_interrupt_in] = endpoint;
769 ++num_interrupt_in;
770 }
771 }
772 }
773
774 /* Now make sure the PL-2303 is configured correctly.
775 * If not, give up now and hope this hack will work
776 * properly during a later invocation of usb_serial_probe
777 */
778 if (num_bulk_in == 0 || num_bulk_out == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100779 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100781 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782 return -ENODEV;
783 }
784 }
785 /* END HORRIBLE HACK FOR PL2303 */
786#endif
787
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788#ifdef CONFIG_USB_SERIAL_GENERIC
789 if (type == &usb_serial_generic_device) {
790 num_ports = num_bulk_out;
791 if (num_ports == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100792 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100793 dev_err(&interface->dev,
794 "Generic device with no bulk out, not allowed.\n");
795 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796 return -EIO;
797 }
798 }
799#endif
800 if (!num_ports) {
801 /* if this device type has a calc_num_ports function, call it */
802 if (type->calc_num_ports) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700803 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100804 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100805 dev_err(&interface->dev,
806 "module get failed, exiting\n");
807 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 return -EIO;
809 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100810 num_ports = type->calc_num_ports(serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700811 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 }
813 if (!num_ports)
814 num_ports = type->num_ports;
815 }
816
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 serial->num_ports = num_ports;
818 serial->num_bulk_in = num_bulk_in;
819 serial->num_bulk_out = num_bulk_out;
820 serial->num_interrupt_in = num_interrupt_in;
821 serial->num_interrupt_out = num_interrupt_out;
822
Alan Stern063a2da2007-10-10 16:24:06 -0400823 /* found all that we need */
824 dev_info(&interface->dev, "%s converter detected\n",
825 type->description);
826
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 /* create our ports, we need as many as the max endpoints */
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100828 /* we don't use num_ports here because some devices have more
829 endpoint pairs than ports */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 max_endpoints = max(num_bulk_in, num_bulk_out);
831 max_endpoints = max(max_endpoints, num_interrupt_in);
832 max_endpoints = max(max_endpoints, num_interrupt_out);
833 max_endpoints = max(max_endpoints, (int)serial->num_ports);
834 serial->num_port_pointers = max_endpoints;
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100835 unlock_kernel();
836
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100837 dbg("%s - setting up %d port structures for this device",
838 __func__, max_endpoints);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 for (i = 0; i < max_endpoints; ++i) {
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100840 port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841 if (!port)
842 goto probe_error;
Alan Cox4a90f092008-10-13 10:39:46 +0100843 tty_port_init(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 port->serial = serial;
Greg Kroah-Hartman507ca9b2005-04-23 12:49:16 -0700845 spin_lock_init(&port->lock);
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300846 mutex_init(&port->mutex);
David Howellsc4028952006-11-22 14:57:56 +0000847 INIT_WORK(&port->work, usb_serial_port_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 serial->port[i] = port;
849 }
850
851 /* set up the endpoint information */
852 for (i = 0; i < num_bulk_in; ++i) {
853 endpoint = bulk_in_endpoint[i];
854 port = serial->port[i];
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100855 port->read_urb = usb_alloc_urb(0, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 if (!port->read_urb) {
857 dev_err(&interface->dev, "No free urbs available\n");
858 goto probe_error;
859 }
860 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
861 port->bulk_in_size = buffer_size;
862 port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100863 port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 if (!port->bulk_in_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100865 dev_err(&interface->dev,
866 "Couldn't allocate bulk_in_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867 goto probe_error;
868 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100869 usb_fill_bulk_urb(port->read_urb, dev,
870 usb_rcvbulkpipe(dev,
871 endpoint->bEndpointAddress),
872 port->bulk_in_buffer, buffer_size,
873 serial->type->read_bulk_callback, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874 }
875
876 for (i = 0; i < num_bulk_out; ++i) {
877 endpoint = bulk_out_endpoint[i];
878 port = serial->port[i];
879 port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
880 if (!port->write_urb) {
881 dev_err(&interface->dev, "No free urbs available\n");
882 goto probe_error;
883 }
884 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
885 port->bulk_out_size = buffer_size;
886 port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100887 port->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 if (!port->bulk_out_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100889 dev_err(&interface->dev,
890 "Couldn't allocate bulk_out_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 goto probe_error;
892 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100893 usb_fill_bulk_urb(port->write_urb, dev,
894 usb_sndbulkpipe(dev,
895 endpoint->bEndpointAddress),
896 port->bulk_out_buffer, buffer_size,
897 serial->type->write_bulk_callback, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 }
899
900 if (serial->type->read_int_callback) {
901 for (i = 0; i < num_interrupt_in; ++i) {
902 endpoint = interrupt_in_endpoint[i];
903 port = serial->port[i];
904 port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
905 if (!port->interrupt_in_urb) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100906 dev_err(&interface->dev,
907 "No free urbs available\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 goto probe_error;
909 }
910 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100911 port->interrupt_in_endpointAddress =
912 endpoint->bEndpointAddress;
913 port->interrupt_in_buffer = kmalloc(buffer_size,
914 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 if (!port->interrupt_in_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100916 dev_err(&interface->dev,
917 "Couldn't allocate interrupt_in_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 goto probe_error;
919 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100920 usb_fill_int_urb(port->interrupt_in_urb, dev,
921 usb_rcvintpipe(dev,
922 endpoint->bEndpointAddress),
923 port->interrupt_in_buffer, buffer_size,
924 serial->type->read_int_callback, port,
925 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 }
927 } else if (num_interrupt_in) {
928 dbg("the device claims to support interrupt in transfers, but read_int_callback is not defined");
929 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100930
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 if (serial->type->write_int_callback) {
932 for (i = 0; i < num_interrupt_out; ++i) {
933 endpoint = interrupt_out_endpoint[i];
934 port = serial->port[i];
935 port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
936 if (!port->interrupt_out_urb) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100937 dev_err(&interface->dev,
938 "No free urbs available\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939 goto probe_error;
940 }
941 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
942 port->interrupt_out_size = buffer_size;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100943 port->interrupt_out_endpointAddress =
944 endpoint->bEndpointAddress;
945 port->interrupt_out_buffer = kmalloc(buffer_size,
946 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947 if (!port->interrupt_out_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100948 dev_err(&interface->dev,
949 "Couldn't allocate interrupt_out_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 goto probe_error;
951 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100952 usb_fill_int_urb(port->interrupt_out_urb, dev,
953 usb_sndintpipe(dev,
954 endpoint->bEndpointAddress),
955 port->interrupt_out_buffer, buffer_size,
956 serial->type->write_int_callback, port,
957 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 }
959 } else if (num_interrupt_out) {
960 dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined");
961 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100962
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 /* if this device type has an attach function, call it */
964 if (type->attach) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700965 if (!try_module_get(type->driver.owner)) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100966 dev_err(&interface->dev,
967 "module get failed, exiting\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 goto probe_error;
969 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100970 retval = type->attach(serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700971 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 if (retval < 0)
973 goto probe_error;
974 if (retval > 0) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100975 /* quietly accept this device, but don't bind to a
976 serial port as it's about to disappear */
Alan Stern0a3c8542009-05-27 11:25:52 -0400977 serial->num_ports = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 goto exit;
979 }
980 }
981
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100982 if (get_free_serial(serial, num_ports, &minor) == NULL) {
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100983 dev_err(&interface->dev, "No more free serial devices\n");
984 goto probe_error;
985 }
Oliver Neukumc744f992007-02-26 15:43:00 +0100986 serial->minor = minor;
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100987
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 /* register all of the individual ports with the driver core */
989 for (i = 0; i < num_ports; ++i) {
990 port = serial->port[i];
991 port->dev.parent = &interface->dev;
992 port->dev.driver = NULL;
993 port->dev.bus = &usb_serial_bus_type;
994 port->dev.release = &port_release;
995
Kay Sievers0031a062008-05-02 06:02:41 +0200996 dev_set_name(&port->dev, "ttyUSB%d", port->number);
Kay Sievers7071a3c2008-05-02 06:02:41 +0200997 dbg ("%s - registering %s", __func__, dev_name(&port->dev));
Greg Kroah-Hartman13f4db92006-08-28 11:43:25 -0700998 retval = device_register(&port->dev);
999 if (retval)
1000 dev_err(&port->dev, "Error registering port device, "
1001 "continuing\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 }
1003
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001004 usb_serial_console_init(debug, minor);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005
1006exit:
1007 /* success */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001008 usb_set_intfdata(interface, serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 return 0;
1010
1011probe_error:
1012 for (i = 0; i < num_bulk_in; ++i) {
1013 port = serial->port[i];
1014 if (!port)
1015 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001016 usb_free_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 kfree(port->bulk_in_buffer);
1018 }
1019 for (i = 0; i < num_bulk_out; ++i) {
1020 port = serial->port[i];
1021 if (!port)
1022 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001023 usb_free_urb(port->write_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 kfree(port->bulk_out_buffer);
1025 }
1026 for (i = 0; i < num_interrupt_in; ++i) {
1027 port = serial->port[i];
1028 if (!port)
1029 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001030 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 kfree(port->interrupt_in_buffer);
1032 }
1033 for (i = 0; i < num_interrupt_out; ++i) {
1034 port = serial->port[i];
1035 if (!port)
1036 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001037 usb_free_urb(port->interrupt_out_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 kfree(port->interrupt_out_buffer);
1039 }
1040
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 /* free up any memory that we allocated */
1042 for (i = 0; i < serial->num_port_pointers; ++i)
1043 kfree(serial->port[i]);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001044 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 return -EIO;
1046}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001047EXPORT_SYMBOL_GPL(usb_serial_probe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048
1049void usb_serial_disconnect(struct usb_interface *interface)
1050{
1051 int i;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001052 struct usb_serial *serial = usb_get_intfdata(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 struct device *dev = &interface->dev;
1054 struct usb_serial_port *port;
1055
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +02001056 usb_serial_console_disconnect(serial);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001057 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001059 mutex_lock(&serial->disc_mutex);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001060 usb_set_intfdata(interface, NULL);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001061 /* must set a flag, to signal subdrivers */
1062 serial->disconnected = 1;
Alan Stern2d931482009-04-14 11:31:02 -04001063 mutex_unlock(&serial->disc_mutex);
1064
1065 /* Unfortunately, many of the sub-drivers expect the port structures
1066 * to exist when their shutdown method is called, so we have to go
1067 * through this awkward two-step unregistration procedure.
1068 */
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001069 for (i = 0; i < serial->num_ports; ++i) {
1070 port = serial->port[i];
1071 if (port) {
Alan Cox4a90f092008-10-13 10:39:46 +01001072 struct tty_struct *tty = tty_port_tty_get(&port->port);
1073 if (tty) {
1074 tty_hangup(tty);
1075 tty_kref_put(tty);
1076 }
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001077 kill_traffic(port);
Alan Stern2d931482009-04-14 11:31:02 -04001078 cancel_work_sync(&port->work);
1079 device_del(&port->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081 }
Alan Stern2d931482009-04-14 11:31:02 -04001082 serial->type->shutdown(serial);
1083 for (i = 0; i < serial->num_ports; ++i) {
1084 port = serial->port[i];
1085 if (port) {
1086 put_device(&port->dev);
1087 serial->port[i] = NULL;
1088 }
1089 }
1090
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001091 /* let the last holder of this object
1092 * cause it to be cleaned up */
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001093 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 dev_info(dev, "device disconnected\n");
1095}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001096EXPORT_SYMBOL_GPL(usb_serial_disconnect);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097
Oliver Neukumec225592007-04-27 20:54:57 +02001098int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
1099{
1100 struct usb_serial *serial = usb_get_intfdata(intf);
1101 struct usb_serial_port *port;
1102 int i, r = 0;
1103
Oliver Neukumf8bece82009-02-05 16:54:25 +01001104 serial->suspending = 1;
1105
Oliver Neukume31c1882007-07-23 08:58:39 +02001106 for (i = 0; i < serial->num_ports; ++i) {
1107 port = serial->port[i];
1108 if (port)
1109 kill_traffic(port);
Oliver Neukumec225592007-04-27 20:54:57 +02001110 }
1111
1112 if (serial->type->suspend)
Oliver Neukume31c1882007-07-23 08:58:39 +02001113 r = serial->type->suspend(serial, message);
Oliver Neukumec225592007-04-27 20:54:57 +02001114
1115 return r;
1116}
1117EXPORT_SYMBOL(usb_serial_suspend);
1118
1119int usb_serial_resume(struct usb_interface *intf)
1120{
1121 struct usb_serial *serial = usb_get_intfdata(intf);
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001122 int rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001123
Oliver Neukumf8bece82009-02-05 16:54:25 +01001124 serial->suspending = 0;
Sarah Sharp8abaee22007-10-25 10:58:43 -07001125 if (serial->type->resume)
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001126 rv = serial->type->resume(serial);
1127 else
1128 rv = usb_serial_generic_resume(serial);
Oliver Neukumf8bece82009-02-05 16:54:25 +01001129
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001130 return rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001131}
1132EXPORT_SYMBOL(usb_serial_resume);
1133
Jeff Dikeb68e31d2006-10-02 02:17:18 -07001134static const struct tty_operations serial_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 .open = serial_open,
1136 .close = serial_close,
1137 .write = serial_write,
1138 .write_room = serial_write_room,
1139 .ioctl = serial_ioctl,
1140 .set_termios = serial_set_termios,
1141 .throttle = serial_throttle,
1142 .unthrottle = serial_unthrottle,
1143 .break_ctl = serial_break,
1144 .chars_in_buffer = serial_chars_in_buffer,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145 .tiocmget = serial_tiocmget,
1146 .tiocmset = serial_tiocmset,
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -07001147 .proc_fops = &serial_proc_fops,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148};
1149
1150struct tty_driver *usb_serial_tty_driver;
1151
1152static int __init usb_serial_init(void)
1153{
1154 int i;
1155 int result;
1156
1157 usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS);
1158 if (!usb_serial_tty_driver)
1159 return -ENOMEM;
1160
1161 /* Initialize our global data */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001162 for (i = 0; i < SERIAL_TTY_MINORS; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 serial_table[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164
1165 result = bus_register(&usb_serial_bus_type);
1166 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001167 printk(KERN_ERR "usb-serial: %s - registering bus driver "
1168 "failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 goto exit_bus;
1170 }
1171
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172 usb_serial_tty_driver->owner = THIS_MODULE;
1173 usb_serial_tty_driver->driver_name = "usbserial";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 usb_serial_tty_driver->name = "ttyUSB";
1175 usb_serial_tty_driver->major = SERIAL_TTY_MAJOR;
1176 usb_serial_tty_driver->minor_start = 0;
1177 usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
1178 usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001179 usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW |
1180 TTY_DRIVER_DYNAMIC_DEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 usb_serial_tty_driver->init_termios = tty_std_termios;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001182 usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD
1183 | HUPCL | CLOCAL;
Alan Coxa5b6f602008-04-08 17:16:06 +01001184 usb_serial_tty_driver->init_termios.c_ispeed = 9600;
1185 usb_serial_tty_driver->init_termios.c_ospeed = 9600;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 tty_set_operations(usb_serial_tty_driver, &serial_ops);
1187 result = tty_register_driver(usb_serial_tty_driver);
1188 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001189 printk(KERN_ERR "usb-serial: %s - tty_register_driver failed\n",
1190 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191 goto exit_reg_driver;
1192 }
1193
1194 /* register the USB driver */
1195 result = usb_register(&usb_serial_driver);
1196 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001197 printk(KERN_ERR "usb-serial: %s - usb_register failed\n",
1198 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199 goto exit_tty;
1200 }
1201
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001202 /* register the generic driver, if we should */
1203 result = usb_serial_generic_register(debug);
1204 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001205 printk(KERN_ERR "usb-serial: %s - registering generic "
1206 "driver failed\n", __func__);
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001207 goto exit_generic;
1208 }
1209
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001210 printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211
1212 return result;
1213
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001214exit_generic:
1215 usb_deregister(&usb_serial_driver);
1216
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217exit_tty:
1218 tty_unregister_driver(usb_serial_tty_driver);
1219
1220exit_reg_driver:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 bus_unregister(&usb_serial_bus_type);
1222
1223exit_bus:
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001224 printk(KERN_ERR "usb-serial: %s - returning with error %d\n",
1225 __func__, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226 put_tty_driver(usb_serial_tty_driver);
1227 return result;
1228}
1229
1230
1231static void __exit usb_serial_exit(void)
1232{
1233 usb_serial_console_exit();
1234
1235 usb_serial_generic_deregister();
1236
1237 usb_deregister(&usb_serial_driver);
1238 tty_unregister_driver(usb_serial_tty_driver);
1239 put_tty_driver(usb_serial_tty_driver);
1240 bus_unregister(&usb_serial_bus_type);
1241}
1242
1243
1244module_init(usb_serial_init);
1245module_exit(usb_serial_exit);
1246
1247#define set_to_generic_if_null(type, function) \
1248 do { \
1249 if (!type->function) { \
1250 type->function = usb_serial_generic_##function; \
1251 dbg("Had to override the " #function \
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001252 " usb serial operation with the generic one.");\
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253 } \
1254 } while (0)
1255
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001256static void fixup_generic(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257{
1258 set_to_generic_if_null(device, open);
1259 set_to_generic_if_null(device, write);
1260 set_to_generic_if_null(device, close);
1261 set_to_generic_if_null(device, write_room);
1262 set_to_generic_if_null(device, chars_in_buffer);
1263 set_to_generic_if_null(device, read_bulk_callback);
1264 set_to_generic_if_null(device, write_bulk_callback);
1265 set_to_generic_if_null(device, shutdown);
1266}
1267
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001268int usb_serial_register(struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001270 /* must be called with BKL held */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 int retval;
1272
Dave Younge4abe662009-02-14 21:21:13 +08001273 if (usb_disabled())
1274 return -ENODEV;
1275
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001276 fixup_generic(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001278 if (!driver->description)
1279 driver->description = driver->driver.name;
1280
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281 /* Add this device to our list of devices */
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001282 list_add(&driver->driver_list, &usb_serial_driver_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001284 retval = usb_serial_bus_register(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285 if (retval) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001286 printk(KERN_ERR "usb-serial: problem %d when registering "
1287 "driver %s\n", retval, driver->description);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001288 list_del(&driver->driver_list);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001289 } else
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001290 printk(KERN_INFO "USB Serial support registered for %s\n",
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001291 driver->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292
1293 return retval;
1294}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001295EXPORT_SYMBOL_GPL(usb_serial_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296
1297
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001298void usb_serial_deregister(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001300 /* must be called with BKL held */
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001301 printk(KERN_INFO "USB Serial deregistering driver %s\n",
1302 device->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303 list_del(&device->driver_list);
1304 usb_serial_bus_deregister(device);
1305}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306EXPORT_SYMBOL_GPL(usb_serial_deregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307
1308/* Module information */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001309MODULE_AUTHOR(DRIVER_AUTHOR);
1310MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311MODULE_LICENSE("GPL");
1312
1313module_param(debug, bool, S_IRUGO | S_IWUSR);
1314MODULE_PARM_DESC(debug, "Debug enabled or not");