blob: 0a566eea49c02e193fcdca270488ab029742c264 [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 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 goto exit;
978 }
979 }
980
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100981 if (get_free_serial(serial, num_ports, &minor) == NULL) {
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100982 dev_err(&interface->dev, "No more free serial devices\n");
983 goto probe_error;
984 }
Oliver Neukumc744f992007-02-26 15:43:00 +0100985 serial->minor = minor;
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100986
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 /* register all of the individual ports with the driver core */
988 for (i = 0; i < num_ports; ++i) {
989 port = serial->port[i];
990 port->dev.parent = &interface->dev;
991 port->dev.driver = NULL;
992 port->dev.bus = &usb_serial_bus_type;
993 port->dev.release = &port_release;
994
Kay Sievers0031a062008-05-02 06:02:41 +0200995 dev_set_name(&port->dev, "ttyUSB%d", port->number);
Kay Sievers7071a3c2008-05-02 06:02:41 +0200996 dbg ("%s - registering %s", __func__, dev_name(&port->dev));
Greg Kroah-Hartman13f4db92006-08-28 11:43:25 -0700997 retval = device_register(&port->dev);
998 if (retval)
999 dev_err(&port->dev, "Error registering port device, "
1000 "continuing\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 }
1002
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001003 usb_serial_console_init(debug, minor);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004
1005exit:
1006 /* success */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001007 usb_set_intfdata(interface, serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 return 0;
1009
1010probe_error:
1011 for (i = 0; i < num_bulk_in; ++i) {
1012 port = serial->port[i];
1013 if (!port)
1014 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001015 usb_free_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 kfree(port->bulk_in_buffer);
1017 }
1018 for (i = 0; i < num_bulk_out; ++i) {
1019 port = serial->port[i];
1020 if (!port)
1021 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001022 usb_free_urb(port->write_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 kfree(port->bulk_out_buffer);
1024 }
1025 for (i = 0; i < num_interrupt_in; ++i) {
1026 port = serial->port[i];
1027 if (!port)
1028 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001029 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 kfree(port->interrupt_in_buffer);
1031 }
1032 for (i = 0; i < num_interrupt_out; ++i) {
1033 port = serial->port[i];
1034 if (!port)
1035 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001036 usb_free_urb(port->interrupt_out_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 kfree(port->interrupt_out_buffer);
1038 }
1039
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 /* free up any memory that we allocated */
1041 for (i = 0; i < serial->num_port_pointers; ++i)
1042 kfree(serial->port[i]);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001043 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 return -EIO;
1045}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001046EXPORT_SYMBOL_GPL(usb_serial_probe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047
1048void usb_serial_disconnect(struct usb_interface *interface)
1049{
1050 int i;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001051 struct usb_serial *serial = usb_get_intfdata(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 struct device *dev = &interface->dev;
1053 struct usb_serial_port *port;
1054
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +02001055 usb_serial_console_disconnect(serial);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001056 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001058 mutex_lock(&serial->disc_mutex);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001059 usb_set_intfdata(interface, NULL);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001060 /* must set a flag, to signal subdrivers */
1061 serial->disconnected = 1;
Alan Stern2d931482009-04-14 11:31:02 -04001062 mutex_unlock(&serial->disc_mutex);
1063
1064 /* Unfortunately, many of the sub-drivers expect the port structures
1065 * to exist when their shutdown method is called, so we have to go
1066 * through this awkward two-step unregistration procedure.
1067 */
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001068 for (i = 0; i < serial->num_ports; ++i) {
1069 port = serial->port[i];
1070 if (port) {
Alan Cox4a90f092008-10-13 10:39:46 +01001071 struct tty_struct *tty = tty_port_tty_get(&port->port);
1072 if (tty) {
1073 tty_hangup(tty);
1074 tty_kref_put(tty);
1075 }
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001076 kill_traffic(port);
Alan Stern2d931482009-04-14 11:31:02 -04001077 cancel_work_sync(&port->work);
1078 device_del(&port->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 }
Alan Stern2d931482009-04-14 11:31:02 -04001081 serial->type->shutdown(serial);
1082 for (i = 0; i < serial->num_ports; ++i) {
1083 port = serial->port[i];
1084 if (port) {
1085 put_device(&port->dev);
1086 serial->port[i] = NULL;
1087 }
1088 }
1089
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001090 /* let the last holder of this object
1091 * cause it to be cleaned up */
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001092 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 dev_info(dev, "device disconnected\n");
1094}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001095EXPORT_SYMBOL_GPL(usb_serial_disconnect);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096
Oliver Neukumec225592007-04-27 20:54:57 +02001097int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
1098{
1099 struct usb_serial *serial = usb_get_intfdata(intf);
1100 struct usb_serial_port *port;
1101 int i, r = 0;
1102
Oliver Neukumf8bece82009-02-05 16:54:25 +01001103 serial->suspending = 1;
1104
Oliver Neukume31c1882007-07-23 08:58:39 +02001105 for (i = 0; i < serial->num_ports; ++i) {
1106 port = serial->port[i];
1107 if (port)
1108 kill_traffic(port);
Oliver Neukumec225592007-04-27 20:54:57 +02001109 }
1110
1111 if (serial->type->suspend)
Oliver Neukume31c1882007-07-23 08:58:39 +02001112 r = serial->type->suspend(serial, message);
Oliver Neukumec225592007-04-27 20:54:57 +02001113
1114 return r;
1115}
1116EXPORT_SYMBOL(usb_serial_suspend);
1117
1118int usb_serial_resume(struct usb_interface *intf)
1119{
1120 struct usb_serial *serial = usb_get_intfdata(intf);
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001121 int rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001122
Oliver Neukumf8bece82009-02-05 16:54:25 +01001123 serial->suspending = 0;
Sarah Sharp8abaee22007-10-25 10:58:43 -07001124 if (serial->type->resume)
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001125 rv = serial->type->resume(serial);
1126 else
1127 rv = usb_serial_generic_resume(serial);
Oliver Neukumf8bece82009-02-05 16:54:25 +01001128
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001129 return rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001130}
1131EXPORT_SYMBOL(usb_serial_resume);
1132
Jeff Dikeb68e31d2006-10-02 02:17:18 -07001133static const struct tty_operations serial_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 .open = serial_open,
1135 .close = serial_close,
1136 .write = serial_write,
1137 .write_room = serial_write_room,
1138 .ioctl = serial_ioctl,
1139 .set_termios = serial_set_termios,
1140 .throttle = serial_throttle,
1141 .unthrottle = serial_unthrottle,
1142 .break_ctl = serial_break,
1143 .chars_in_buffer = serial_chars_in_buffer,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 .tiocmget = serial_tiocmget,
1145 .tiocmset = serial_tiocmset,
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -07001146 .proc_fops = &serial_proc_fops,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147};
1148
1149struct tty_driver *usb_serial_tty_driver;
1150
1151static int __init usb_serial_init(void)
1152{
1153 int i;
1154 int result;
1155
1156 usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS);
1157 if (!usb_serial_tty_driver)
1158 return -ENOMEM;
1159
1160 /* Initialize our global data */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001161 for (i = 0; i < SERIAL_TTY_MINORS; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 serial_table[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163
1164 result = bus_register(&usb_serial_bus_type);
1165 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001166 printk(KERN_ERR "usb-serial: %s - registering bus driver "
1167 "failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 goto exit_bus;
1169 }
1170
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 usb_serial_tty_driver->owner = THIS_MODULE;
1172 usb_serial_tty_driver->driver_name = "usbserial";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173 usb_serial_tty_driver->name = "ttyUSB";
1174 usb_serial_tty_driver->major = SERIAL_TTY_MAJOR;
1175 usb_serial_tty_driver->minor_start = 0;
1176 usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
1177 usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001178 usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW |
1179 TTY_DRIVER_DYNAMIC_DEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180 usb_serial_tty_driver->init_termios = tty_std_termios;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001181 usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD
1182 | HUPCL | CLOCAL;
Alan Coxa5b6f602008-04-08 17:16:06 +01001183 usb_serial_tty_driver->init_termios.c_ispeed = 9600;
1184 usb_serial_tty_driver->init_termios.c_ospeed = 9600;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185 tty_set_operations(usb_serial_tty_driver, &serial_ops);
1186 result = tty_register_driver(usb_serial_tty_driver);
1187 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001188 printk(KERN_ERR "usb-serial: %s - tty_register_driver failed\n",
1189 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190 goto exit_reg_driver;
1191 }
1192
1193 /* register the USB driver */
1194 result = usb_register(&usb_serial_driver);
1195 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001196 printk(KERN_ERR "usb-serial: %s - usb_register failed\n",
1197 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 goto exit_tty;
1199 }
1200
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001201 /* register the generic driver, if we should */
1202 result = usb_serial_generic_register(debug);
1203 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001204 printk(KERN_ERR "usb-serial: %s - registering generic "
1205 "driver failed\n", __func__);
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001206 goto exit_generic;
1207 }
1208
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001209 printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210
1211 return result;
1212
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001213exit_generic:
1214 usb_deregister(&usb_serial_driver);
1215
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216exit_tty:
1217 tty_unregister_driver(usb_serial_tty_driver);
1218
1219exit_reg_driver:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 bus_unregister(&usb_serial_bus_type);
1221
1222exit_bus:
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001223 printk(KERN_ERR "usb-serial: %s - returning with error %d\n",
1224 __func__, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225 put_tty_driver(usb_serial_tty_driver);
1226 return result;
1227}
1228
1229
1230static void __exit usb_serial_exit(void)
1231{
1232 usb_serial_console_exit();
1233
1234 usb_serial_generic_deregister();
1235
1236 usb_deregister(&usb_serial_driver);
1237 tty_unregister_driver(usb_serial_tty_driver);
1238 put_tty_driver(usb_serial_tty_driver);
1239 bus_unregister(&usb_serial_bus_type);
1240}
1241
1242
1243module_init(usb_serial_init);
1244module_exit(usb_serial_exit);
1245
1246#define set_to_generic_if_null(type, function) \
1247 do { \
1248 if (!type->function) { \
1249 type->function = usb_serial_generic_##function; \
1250 dbg("Had to override the " #function \
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001251 " usb serial operation with the generic one.");\
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252 } \
1253 } while (0)
1254
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001255static void fixup_generic(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256{
1257 set_to_generic_if_null(device, open);
1258 set_to_generic_if_null(device, write);
1259 set_to_generic_if_null(device, close);
1260 set_to_generic_if_null(device, write_room);
1261 set_to_generic_if_null(device, chars_in_buffer);
1262 set_to_generic_if_null(device, read_bulk_callback);
1263 set_to_generic_if_null(device, write_bulk_callback);
1264 set_to_generic_if_null(device, shutdown);
1265}
1266
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001267int usb_serial_register(struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001269 /* must be called with BKL held */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270 int retval;
1271
Dave Younge4abe662009-02-14 21:21:13 +08001272 if (usb_disabled())
1273 return -ENODEV;
1274
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001275 fixup_generic(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001277 if (!driver->description)
1278 driver->description = driver->driver.name;
1279
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 /* Add this device to our list of devices */
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001281 list_add(&driver->driver_list, &usb_serial_driver_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001283 retval = usb_serial_bus_register(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284 if (retval) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001285 printk(KERN_ERR "usb-serial: problem %d when registering "
1286 "driver %s\n", retval, driver->description);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001287 list_del(&driver->driver_list);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001288 } else
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001289 printk(KERN_INFO "USB Serial support registered for %s\n",
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001290 driver->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291
1292 return retval;
1293}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001294EXPORT_SYMBOL_GPL(usb_serial_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295
1296
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001297void usb_serial_deregister(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001299 /* must be called with BKL held */
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001300 printk(KERN_INFO "USB Serial deregistering driver %s\n",
1301 device->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302 list_del(&device->driver_list);
1303 usb_serial_bus_deregister(device);
1304}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305EXPORT_SYMBOL_GPL(usb_serial_deregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306
1307/* Module information */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001308MODULE_AUTHOR(DRIVER_AUTHOR);
1309MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310MODULE_LICENSE("GPL");
1311
1312module_param(debug, bool, S_IRUGO | S_IWUSR);
1313MODULE_PARM_DESC(debug, "Debug enabled or not");