blob: 8d5189096470fe15fa9912c1aea062576fa8310f [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>
29#include <linux/spinlock.h>
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -030030#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <linux/list.h>
Alan Coxa8d6f0a2008-07-22 11:12:24 +010032#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/usb.h>
Greg Kroah-Hartmana9698882006-07-11 21:22:58 -070034#include <linux/usb/serial.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include "pl2303.h"
36
37/*
38 * Version Information
39 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070040#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/"
41#define DRIVER_DESC "USB Serial Driver core"
42
Pete Zaitcev34f8e762006-06-21 15:00:45 -070043static void port_free(struct usb_serial_port *port);
44
Linus Torvalds1da177e2005-04-16 15:20:36 -070045/* Driver structure we register with the USB core */
46static struct usb_driver usb_serial_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070047 .name = "usbserial",
48 .probe = usb_serial_probe,
49 .disconnect = usb_serial_disconnect,
Oliver Neukumec225592007-04-27 20:54:57 +020050 .suspend = usb_serial_suspend,
51 .resume = usb_serial_resume,
Greg Kroah-Hartmanba9dc652005-11-16 13:41:28 -080052 .no_dynamic_id = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -070053};
54
55/* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead
56 the MODULE_DEVICE_TABLE declarations in each serial driver
57 cause the "hotplug" program to pull in whatever module is necessary
58 via modprobe, and modprobe will load usbserial because the serial
59 drivers depend on it.
60*/
61
62static int debug;
Alan Coxa8d6f0a2008-07-22 11:12:24 +010063/* initially all NULL */
64static struct usb_serial *serial_table[SERIAL_TTY_MINORS];
Oliver Neukum3ddad822007-07-24 15:13:42 +020065static DEFINE_MUTEX(table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070066static LIST_HEAD(usb_serial_driver_list);
67
68struct usb_serial *usb_serial_get_by_index(unsigned index)
69{
Oliver Neukum34ef50e2007-01-13 07:29:26 +010070 struct usb_serial *serial;
71
Oliver Neukum3ddad822007-07-24 15:13:42 +020072 mutex_lock(&table_lock);
Oliver Neukum34ef50e2007-01-13 07:29:26 +010073 serial = serial_table[index];
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
75 if (serial)
76 kref_get(&serial->kref);
Oliver Neukum3ddad822007-07-24 15:13:42 +020077 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070078 return serial;
79}
80
Alan Coxa8d6f0a2008-07-22 11:12:24 +010081static struct usb_serial *get_free_serial(struct usb_serial *serial,
82 int num_ports, unsigned int *minor)
Linus Torvalds1da177e2005-04-16 15:20:36 -070083{
84 unsigned int i, j;
85 int good_spot;
86
Harvey Harrison441b62c2008-03-03 16:08:34 -080087 dbg("%s %d", __func__, num_ports);
Linus Torvalds1da177e2005-04-16 15:20:36 -070088
89 *minor = 0;
Oliver Neukum3ddad822007-07-24 15:13:42 +020090 mutex_lock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070091 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
92 if (serial_table[i])
93 continue;
94
95 good_spot = 1;
96 for (j = 1; j <= num_ports-1; ++j)
97 if ((i+j >= SERIAL_TTY_MINORS) || (serial_table[i+j])) {
98 good_spot = 0;
99 i += j;
100 break;
101 }
102 if (good_spot == 0)
103 continue;
104
105 *minor = i;
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100106 j = 0;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800107 dbg("%s - minor base = %d", __func__, *minor);
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100108 for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109 serial_table[i] = serial;
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100110 serial->port[j++]->number = i;
111 }
Oliver Neukum3ddad822007-07-24 15:13:42 +0200112 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113 return serial;
114 }
Oliver Neukum3ddad822007-07-24 15:13:42 +0200115 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116 return NULL;
117}
118
119static void return_serial(struct usb_serial *serial)
120{
121 int i;
122
Harvey Harrison441b62c2008-03-03 16:08:34 -0800123 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100125 for (i = 0; i < serial->num_ports; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126 serial_table[serial->minor + i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127}
128
129static void destroy_serial(struct kref *kref)
130{
131 struct usb_serial *serial;
132 struct usb_serial_port *port;
133 int i;
134
135 serial = to_usb_serial(kref);
136
Harvey Harrison441b62c2008-03-03 16:08:34 -0800137 dbg("%s - %s", __func__, serial->type->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138
Jim Radford521b85a2007-03-13 08:30:50 -0700139 serial->type->shutdown(serial);
140
141 /* return the minor range that this device had */
Alan Stern0282b7f2008-07-29 12:01:04 -0400142 if (serial->minor != SERIAL_TTY_NO_MINOR)
143 return_serial(serial);
Jim Radford521b85a2007-03-13 08:30:50 -0700144
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145 for (i = 0; i < serial->num_ports; ++i)
Alan Cox95da3102008-07-22 11:09:07 +0100146 serial->port[i]->port.count = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147
148 /* the ports are cleaned up and released in port_release() */
149 for (i = 0; i < serial->num_ports; ++i)
150 if (serial->port[i]->dev.parent != NULL) {
151 device_unregister(&serial->port[i]->dev);
152 serial->port[i] = NULL;
153 }
154
155 /* If this is a "fake" port, we have to clean it up here, as it will
156 * not get cleaned up in port_release() as it was never registered with
157 * the driver core */
158 if (serial->num_ports < serial->num_port_pointers) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100159 for (i = serial->num_ports;
160 i < serial->num_port_pointers; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161 port = serial->port[i];
162 if (!port)
163 continue;
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700164 port_free(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165 }
166 }
167
168 usb_put_dev(serial->dev);
169
170 /* free up any memory that we allocated */
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100171 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172}
173
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200174void usb_serial_put(struct usb_serial *serial)
175{
Oliver Neukum3ddad822007-07-24 15:13:42 +0200176 mutex_lock(&table_lock);
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200177 kref_put(&serial->kref, destroy_serial);
Oliver Neukum3ddad822007-07-24 15:13:42 +0200178 mutex_unlock(&table_lock);
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200179}
180
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181/*****************************************************************************
182 * Driver tty interface functions
183 *****************************************************************************/
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100184static int serial_open (struct tty_struct *tty, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185{
186 struct usb_serial *serial;
187 struct usb_serial_port *port;
188 unsigned int portNumber;
189 int retval;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100190
Harvey Harrison441b62c2008-03-03 16:08:34 -0800191 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192
193 /* get the serial object associated with this tty pointer */
194 serial = usb_serial_get_by_index(tty->index);
195 if (!serial) {
196 tty->driver_data = NULL;
197 return -ENODEV;
198 }
199
200 portNumber = tty->index - serial->minor;
201 port = serial->port[portNumber];
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300202 if (!port) {
203 retval = -ENODEV;
204 goto bailout_kref_put;
205 }
Luiz Fernando Capitulino8a4613f2005-11-28 19:16:07 -0200206
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300207 if (mutex_lock_interruptible(&port->mutex)) {
208 retval = -ERESTARTSYS;
209 goto bailout_kref_put;
210 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100211
Alan Cox95da3102008-07-22 11:09:07 +0100212 ++port->port.count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213
Paul Fulghumca854852006-04-13 22:28:17 +0200214 /* set up our port structure making the tty driver
215 * remember our port object, and us it */
216 tty->driver_data = port;
Alan Cox4a90f092008-10-13 10:39:46 +0100217 tty_port_tty_set(&port->port, tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218
Alan Cox95da3102008-07-22 11:09:07 +0100219 if (port->port.count == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220
221 /* lock this module before we call it
222 * this may fail, which means we must bail out,
223 * safe because we are called with BKL held */
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700224 if (!try_module_get(serial->type->driver.owner)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225 retval = -ENODEV;
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300226 goto bailout_mutex_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 }
228
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800229 retval = usb_autopm_get_interface(serial->interface);
230 if (retval)
231 goto bailout_module_put;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100232 /* only call the device specific open if this
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 * is the first time the port is opened */
Alan Cox95da3102008-07-22 11:09:07 +0100234 retval = serial->type->open(tty, port, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 if (retval)
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800236 goto bailout_interface_put;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 }
238
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300239 mutex_unlock(&port->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 return 0;
241
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800242bailout_interface_put:
243 usb_autopm_put_interface(serial->interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244bailout_module_put:
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700245 module_put(serial->type->driver.owner);
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300246bailout_mutex_unlock:
Alan Cox95da3102008-07-22 11:09:07 +0100247 port->port.count = 0;
Frank Gevaertsb059c812006-06-14 15:52:05 +0200248 tty->driver_data = NULL;
Alan Cox4a90f092008-10-13 10:39:46 +0100249 tty_port_tty_set(&port->port, NULL);
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300250 mutex_unlock(&port->mutex);
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300251bailout_kref_put:
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200252 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253 return retval;
254}
255
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100256static void serial_close(struct tty_struct *tty, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200258 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259
260 if (!port)
261 return;
262
Harvey Harrison441b62c2008-03-03 16:08:34 -0800263 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300265 mutex_lock(&port->mutex);
Luiz Fernando Capitulino8a4613f2005-11-28 19:16:07 -0200266
Alan Cox95da3102008-07-22 11:09:07 +0100267 if (port->port.count == 0) {
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300268 mutex_unlock(&port->mutex);
Greg Kroah-Hartman91c0bce2006-03-06 13:25:52 -0800269 return;
270 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271
Alan Cox4bd43f22009-01-02 13:44:04 +0000272 if (port->port.count == 1)
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100273 /* only call the device specific close if this
Alan Cox4bd43f22009-01-02 13:44:04 +0000274 * port is being closed by the last owner. Ensure we do
275 * this before we drop the port count. The call is protected
276 * by the port mutex
277 */
Alan Cox95da3102008-07-22 11:09:07 +0100278 port->serial->type->close(tty, port, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279
Alan Cox4bd43f22009-01-02 13:44:04 +0000280 if (port->port.count == (port->console ? 2 : 1)) {
Alan Cox4a90f092008-10-13 10:39:46 +0100281 struct tty_struct *tty = tty_port_tty_get(&port->port);
282 if (tty) {
Alan Cox4bd43f22009-01-02 13:44:04 +0000283 /* We must do this before we drop the port count to
284 zero. */
Alan Cox4a90f092008-10-13 10:39:46 +0100285 if (tty->driver_data)
286 tty->driver_data = NULL;
287 tty_port_tty_set(&port->port, NULL);
Alan Coxfce48772008-10-30 15:54:12 +0000288 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 }
291
Alan Cox4bd43f22009-01-02 13:44:04 +0000292 if (port->port.count == 1) {
Oliver Neukum62ad2962008-06-25 13:32:49 +0200293 mutex_lock(&port->serial->disc_mutex);
294 if (!port->serial->disconnected)
295 usb_autopm_put_interface(port->serial->interface);
296 mutex_unlock(&port->serial->disc_mutex);
Aristeu Rozanski9a6b1ef2007-11-12 15:15:02 -0500297 module_put(port->serial->type->driver.owner);
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800298 }
Alan Cox4bd43f22009-01-02 13:44:04 +0000299 --port->port.count;
Aristeu Rozanski9a6b1ef2007-11-12 15:15:02 -0500300
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300301 mutex_unlock(&port->mutex);
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200302 usb_serial_put(port->serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303}
304
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100305static int serial_write(struct tty_struct *tty, const unsigned char *buf,
306 int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200308 struct usb_serial_port *port = tty->driver_data;
Oliver Neukum3ff4fd92007-01-13 07:32:27 +0100309 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310
Alan Coxf34d7a52008-04-30 00:54:13 -0700311 if (port->serial->dev->state == USB_STATE_NOTATTACHED)
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200312 goto exit;
313
Harvey Harrison441b62c2008-03-03 16:08:34 -0800314 dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315
Alan Cox95da3102008-07-22 11:09:07 +0100316 /* count is managed under the mutex lock for the tty so cannot
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100317 drop to zero until after the last close completes */
Alan Cox95da3102008-07-22 11:09:07 +0100318 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319
320 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100321 retval = port->serial->type->write(tty, port, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322
323exit:
324 return retval;
325}
326
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100327static int serial_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200329 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800330 dbg("%s - port %d", __func__, port->number);
Alan Cox95da3102008-07-22 11:09:07 +0100331 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100333 return port->serial->type->write_room(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334}
335
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100336static int serial_chars_in_buffer(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200338 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800339 dbg("%s = port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340
Alan Cox95da3102008-07-22 11:09:07 +0100341 WARN_ON(!port->port.count);
Alan Coxeff69372009-01-02 13:47:06 +0000342 /* if the device was unplugged then any remaining characters
343 fell out of the connector ;) */
344 if (port->serial->disconnected)
345 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100347 return port->serial->type->chars_in_buffer(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348}
349
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100350static void serial_throttle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200352 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800353 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354
Alan Cox95da3102008-07-22 11:09:07 +0100355 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 /* pass on to the driver specific version of this function */
357 if (port->serial->type->throttle)
Alan Cox95da3102008-07-22 11:09:07 +0100358 port->serial->type->throttle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359}
360
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100361static void serial_unthrottle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200363 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800364 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365
Alan Cox95da3102008-07-22 11:09:07 +0100366 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 /* pass on to the driver specific version of this function */
368 if (port->serial->type->unthrottle)
Alan Cox95da3102008-07-22 11:09:07 +0100369 port->serial->type->unthrottle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370}
371
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100372static int serial_ioctl(struct tty_struct *tty, struct file *file,
373 unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200375 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 int retval = -ENODEV;
377
Harvey Harrison441b62c2008-03-03 16:08:34 -0800378 dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379
Alan Cox95da3102008-07-22 11:09:07 +0100380 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100382 /* pass on to the driver specific version of this function
383 if it is available */
Alan Coxf34d7a52008-04-30 00:54:13 -0700384 if (port->serial->type->ioctl) {
385 lock_kernel();
Alan Cox95da3102008-07-22 11:09:07 +0100386 retval = port->serial->type->ioctl(tty, file, cmd, arg);
Alan Coxf34d7a52008-04-30 00:54:13 -0700387 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100388 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 retval = -ENOIOCTLCMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 return retval;
391}
392
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100393static void serial_set_termios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200395 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800396 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397
Alan Cox95da3102008-07-22 11:09:07 +0100398 WARN_ON(!port->port.count);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100399 /* pass on to the driver specific version of this function
400 if it is available */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 if (port->serial->type->set_termios)
Alan Cox95da3102008-07-22 11:09:07 +0100402 port->serial->type->set_termios(tty, port, old);
Alan Cox33785092007-10-18 01:24:22 -0700403 else
404 tty_termios_copy_hw(tty->termios, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405}
406
Alan Cox9e989662008-07-22 11:18:03 +0100407static int serial_break(struct tty_struct *tty, int break_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200409 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410
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 */
Alan Coxf34d7a52008-04-30 00:54:13 -0700416 if (port->serial->type->break_ctl) {
417 lock_kernel();
Alan Cox95da3102008-07-22 11:09:07 +0100418 port->serial->type->break_ctl(tty, break_state);
Alan Coxf34d7a52008-04-30 00:54:13 -0700419 unlock_kernel();
420 }
Alan Cox9e989662008-07-22 11:18:03 +0100421 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422}
423
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100424static int serial_read_proc(char *page, char **start, off_t off, int count,
425 int *eof, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426{
427 struct usb_serial *serial;
428 int length = 0;
429 int i;
430 off_t begin = 0;
431 char tmp[40];
432
Harvey Harrison441b62c2008-03-03 16:08:34 -0800433 dbg("%s", __func__);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100434 length += sprintf(page, "usbserinfo:1.0 driver:2.0\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 for (i = 0; i < SERIAL_TTY_MINORS && length < PAGE_SIZE; ++i) {
436 serial = usb_serial_get_by_index(i);
437 if (serial == NULL)
438 continue;
439
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100440 length += sprintf(page+length, "%d:", i);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700441 if (serial->type->driver.owner)
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100442 length += sprintf(page+length, " module:%s",
443 module_name(serial->type->driver.owner));
444 length += sprintf(page+length, " name:\"%s\"",
445 serial->type->description);
446 length += sprintf(page+length, " vendor:%04x product:%04x",
447 le16_to_cpu(serial->dev->descriptor.idVendor),
448 le16_to_cpu(serial->dev->descriptor.idProduct));
449 length += sprintf(page+length, " num_ports:%d",
450 serial->num_ports);
451 length += sprintf(page+length, " port:%d",
452 i - serial->minor + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453 usb_make_path(serial->dev, tmp, sizeof(tmp));
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100454 length += sprintf(page+length, " path:%s", tmp);
455
456 length += sprintf(page+length, "\n");
Matthias Urlichs59925832006-09-11 12:35:20 +0200457 if ((length + begin) > (off + count)) {
458 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459 goto done;
Matthias Urlichs59925832006-09-11 12:35:20 +0200460 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461 if ((length + begin) < off) {
462 begin += length;
463 length = 0;
464 }
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200465 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 }
467 *eof = 1;
468done:
469 if (off >= (length + begin))
470 return 0;
471 *start = page + (off-begin);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100472 return (count < begin+length-off) ? count : begin+length-off;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473}
474
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100475static int serial_tiocmget(struct tty_struct *tty, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200477 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478
Harvey Harrison441b62c2008-03-03 16:08:34 -0800479 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480
Alan Cox95da3102008-07-22 11:09:07 +0100481 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 if (port->serial->type->tiocmget)
Alan Cox95da3102008-07-22 11:09:07 +0100483 return port->serial->type->tiocmget(tty, file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 return -EINVAL;
485}
486
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100487static int serial_tiocmset(struct tty_struct *tty, struct file *file,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 unsigned int set, unsigned int clear)
489{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200490 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491
Harvey Harrison441b62c2008-03-03 16:08:34 -0800492 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493
Alan Cox95da3102008-07-22 11:09:07 +0100494 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 if (port->serial->type->tiocmset)
Alan Cox95da3102008-07-22 11:09:07 +0100496 return port->serial->type->tiocmset(tty, file, set, clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 return -EINVAL;
498}
499
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700500/*
501 * We would be calling tty_wakeup here, but unfortunately some line
502 * disciplines have an annoying habit of calling tty->write from
503 * the write wakeup callback (e.g. n_hdlc.c).
504 */
505void usb_serial_port_softint(struct usb_serial_port *port)
506{
507 schedule_work(&port->work);
508}
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100509EXPORT_SYMBOL_GPL(usb_serial_port_softint);
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700510
David Howellsc4028952006-11-22 14:57:56 +0000511static void usb_serial_port_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512{
David Howellsc4028952006-11-22 14:57:56 +0000513 struct usb_serial_port *port =
514 container_of(work, struct usb_serial_port, work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 struct tty_struct *tty;
516
Harvey Harrison441b62c2008-03-03 16:08:34 -0800517 dbg("%s - port %d", __func__, port->number);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100518
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 if (!port)
520 return;
521
Alan Cox4a90f092008-10-13 10:39:46 +0100522 tty = tty_port_tty_get(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 if (!tty)
524 return;
525
526 tty_wakeup(tty);
Alan Cox4a90f092008-10-13 10:39:46 +0100527 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528}
529
530static void port_release(struct device *dev)
531{
532 struct usb_serial_port *port = to_usb_serial_port(dev);
533
Kay Sievers7071a3c2008-05-02 06:02:41 +0200534 dbg ("%s - %s", __func__, dev_name(dev));
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700535 port_free(port);
536}
537
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100538static void kill_traffic(struct usb_serial_port *port)
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700539{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 usb_kill_urb(port->write_urb);
Oliver Neukum5adceac2007-08-17 14:01:38 +0200542 /*
543 * This is tricky.
544 * Some drivers submit the read_urb in the
545 * handler for the write_urb or vice versa
546 * this order determines the order in which
547 * usb_kill_urb() must be used to reliably
548 * kill the URBs. As it is unknown here,
549 * both orders must be used in turn.
550 * The call below is not redundant.
551 */
552 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 usb_kill_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 usb_kill_urb(port->interrupt_out_urb);
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100555}
556
557static void port_free(struct usb_serial_port *port)
558{
559 kill_traffic(port);
560 usb_free_urb(port->read_urb);
561 usb_free_urb(port->write_urb);
562 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563 usb_free_urb(port->interrupt_out_urb);
564 kfree(port->bulk_in_buffer);
565 kfree(port->bulk_out_buffer);
566 kfree(port->interrupt_in_buffer);
567 kfree(port->interrupt_out_buffer);
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700568 flush_scheduled_work(); /* port->work */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 kfree(port);
570}
571
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100572static struct usb_serial *create_serial(struct usb_device *dev,
573 struct usb_interface *interface,
574 struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575{
576 struct usb_serial *serial;
577
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100578 serial = kzalloc(sizeof(*serial), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579 if (!serial) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800580 dev_err(&dev->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 return NULL;
582 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 serial->dev = usb_get_dev(dev);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700584 serial->type = driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585 serial->interface = interface;
586 kref_init(&serial->kref);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +0100587 mutex_init(&serial->disc_mutex);
Alan Stern0282b7f2008-07-29 12:01:04 -0400588 serial->minor = SERIAL_TTY_NO_MINOR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589
590 return serial;
591}
592
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100593static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf,
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100594 struct usb_serial_driver *drv)
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100595{
596 struct usb_dynid *dynid;
597
598 spin_lock(&drv->dynids.lock);
599 list_for_each_entry(dynid, &drv->dynids.list, node) {
600 if (usb_match_one_id(intf, &dynid->id)) {
601 spin_unlock(&drv->dynids.lock);
602 return &dynid->id;
603 }
604 }
605 spin_unlock(&drv->dynids.lock);
606 return NULL;
607}
608
609static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv,
610 struct usb_interface *intf)
611{
612 const struct usb_device_id *id;
613
614 id = usb_match_id(intf, drv->id_table);
615 if (id) {
616 dbg("static descriptor matches");
617 goto exit;
618 }
619 id = match_dynamic_id(intf, drv);
620 if (id)
621 dbg("dynamic descriptor matches");
622exit:
623 return id;
624}
625
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100626static struct usb_serial_driver *search_serial_device(
627 struct usb_interface *iface)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629 const struct usb_device_id *id;
Alan Stern063a2da2007-10-10 16:24:06 -0400630 struct usb_serial_driver *drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631
Adrian Bunk93b1fae2006-01-10 00:13:33 +0100632 /* Check if the usb id matches a known device */
Alan Stern063a2da2007-10-10 16:24:06 -0400633 list_for_each_entry(drv, &usb_serial_driver_list, driver_list) {
634 id = get_iface_id(drv, iface);
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100635 if (id)
Alan Stern063a2da2007-10-10 16:24:06 -0400636 return drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 }
638
639 return NULL;
640}
641
642int usb_serial_probe(struct usb_interface *interface,
643 const struct usb_device_id *id)
644{
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100645 struct usb_device *dev = interface_to_usbdev(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 struct usb_serial *serial = NULL;
647 struct usb_serial_port *port;
648 struct usb_host_interface *iface_desc;
649 struct usb_endpoint_descriptor *endpoint;
650 struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS];
651 struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS];
652 struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];
653 struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700654 struct usb_serial_driver *type = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655 int retval;
Andre Hauptdd9ca5d2008-06-18 15:56:00 +0200656 unsigned int minor;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 int buffer_size;
658 int i;
659 int num_interrupt_in = 0;
660 int num_interrupt_out = 0;
661 int num_bulk_in = 0;
662 int num_bulk_out = 0;
663 int num_ports = 0;
664 int max_endpoints;
665
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100666 lock_kernel(); /* guard against unloading a serial driver module */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667 type = search_serial_device(interface);
668 if (!type) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100669 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 dbg("none matched");
671 return -ENODEV;
672 }
673
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100674 serial = create_serial(dev, interface, type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675 if (!serial) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100676 unlock_kernel();
Harvey Harrison441b62c2008-03-03 16:08:34 -0800677 dev_err(&interface->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 return -ENOMEM;
679 }
680
681 /* if this device type has a probe function, call it */
682 if (type->probe) {
683 const struct usb_device_id *id;
684
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700685 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100686 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100687 dev_err(&interface->dev,
688 "module get failed, exiting\n");
689 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 return -EIO;
691 }
692
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100693 id = get_iface_id(type, interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 retval = type->probe(serial, id);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700695 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696
697 if (retval) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100698 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100699 dbg("sub driver rejected device");
700 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 return retval;
702 }
703 }
704
705 /* descriptor matches, let's find the endpoints needed */
706 /* check out the endpoints */
707 iface_desc = interface->cur_altsetting;
708 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
709 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700710
711 if (usb_endpoint_is_bulk_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712 /* we found a bulk in endpoint */
713 dbg("found bulk in on endpoint %d", i);
714 bulk_in_endpoint[num_bulk_in] = endpoint;
715 ++num_bulk_in;
716 }
717
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700718 if (usb_endpoint_is_bulk_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 /* we found a bulk out endpoint */
720 dbg("found bulk out on endpoint %d", i);
721 bulk_out_endpoint[num_bulk_out] = endpoint;
722 ++num_bulk_out;
723 }
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700724
725 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726 /* we found a interrupt in endpoint */
727 dbg("found interrupt in on endpoint %d", i);
728 interrupt_in_endpoint[num_interrupt_in] = endpoint;
729 ++num_interrupt_in;
730 }
731
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700732 if (usb_endpoint_is_int_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 /* we found an interrupt out endpoint */
734 dbg("found interrupt out on endpoint %d", i);
735 interrupt_out_endpoint[num_interrupt_out] = endpoint;
736 ++num_interrupt_out;
737 }
738 }
739
740#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100741 /* BEGIN HORRIBLE HACK FOR PL2303 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 /* this is needed due to the looney way its endpoints are set up */
743 if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&
744 (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||
745 ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) &&
Johannes Steingraeber8fd80132006-09-16 16:17:34 +0200746 (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) ||
747 ((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) &&
Andreas Bombece816cf2008-09-14 01:58:55 +0200748 (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID)) ||
749 ((le16_to_cpu(dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) &&
750 (le16_to_cpu(dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_EF81))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 if (interface != dev->actconfig->interface[0]) {
752 /* check out the endpoints of the other interface*/
753 iface_desc = dev->actconfig->interface[0]->cur_altsetting;
754 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
755 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700756 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 /* we found a interrupt in endpoint */
758 dbg("found interrupt in for Prolific device on separate interface");
759 interrupt_in_endpoint[num_interrupt_in] = endpoint;
760 ++num_interrupt_in;
761 }
762 }
763 }
764
765 /* Now make sure the PL-2303 is configured correctly.
766 * If not, give up now and hope this hack will work
767 * properly during a later invocation of usb_serial_probe
768 */
769 if (num_bulk_in == 0 || num_bulk_out == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100770 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100772 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 return -ENODEV;
774 }
775 }
776 /* END HORRIBLE HACK FOR PL2303 */
777#endif
778
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779#ifdef CONFIG_USB_SERIAL_GENERIC
780 if (type == &usb_serial_generic_device) {
781 num_ports = num_bulk_out;
782 if (num_ports == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100783 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100784 dev_err(&interface->dev,
785 "Generic device with no bulk out, not allowed.\n");
786 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 return -EIO;
788 }
789 }
790#endif
791 if (!num_ports) {
792 /* if this device type has a calc_num_ports function, call it */
793 if (type->calc_num_ports) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700794 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100795 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100796 dev_err(&interface->dev,
797 "module get failed, exiting\n");
798 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 return -EIO;
800 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100801 num_ports = type->calc_num_ports(serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700802 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 }
804 if (!num_ports)
805 num_ports = type->num_ports;
806 }
807
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 serial->num_ports = num_ports;
809 serial->num_bulk_in = num_bulk_in;
810 serial->num_bulk_out = num_bulk_out;
811 serial->num_interrupt_in = num_interrupt_in;
812 serial->num_interrupt_out = num_interrupt_out;
813
Alan Stern063a2da2007-10-10 16:24:06 -0400814 /* found all that we need */
815 dev_info(&interface->dev, "%s converter detected\n",
816 type->description);
817
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818 /* create our ports, we need as many as the max endpoints */
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100819 /* we don't use num_ports here because some devices have more
820 endpoint pairs than ports */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 max_endpoints = max(num_bulk_in, num_bulk_out);
822 max_endpoints = max(max_endpoints, num_interrupt_in);
823 max_endpoints = max(max_endpoints, num_interrupt_out);
824 max_endpoints = max(max_endpoints, (int)serial->num_ports);
825 serial->num_port_pointers = max_endpoints;
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100826 unlock_kernel();
827
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100828 dbg("%s - setting up %d port structures for this device",
829 __func__, max_endpoints);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 for (i = 0; i < max_endpoints; ++i) {
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100831 port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 if (!port)
833 goto probe_error;
Alan Cox4a90f092008-10-13 10:39:46 +0100834 tty_port_init(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 port->serial = serial;
Greg Kroah-Hartman507ca9b2005-04-23 12:49:16 -0700836 spin_lock_init(&port->lock);
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300837 mutex_init(&port->mutex);
David Howellsc4028952006-11-22 14:57:56 +0000838 INIT_WORK(&port->work, usb_serial_port_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 serial->port[i] = port;
840 }
841
842 /* set up the endpoint information */
843 for (i = 0; i < num_bulk_in; ++i) {
844 endpoint = bulk_in_endpoint[i];
845 port = serial->port[i];
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100846 port->read_urb = usb_alloc_urb(0, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 if (!port->read_urb) {
848 dev_err(&interface->dev, "No free urbs available\n");
849 goto probe_error;
850 }
851 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
852 port->bulk_in_size = buffer_size;
853 port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100854 port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 if (!port->bulk_in_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100856 dev_err(&interface->dev,
857 "Couldn't allocate bulk_in_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 goto probe_error;
859 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100860 usb_fill_bulk_urb(port->read_urb, dev,
861 usb_rcvbulkpipe(dev,
862 endpoint->bEndpointAddress),
863 port->bulk_in_buffer, buffer_size,
864 serial->type->read_bulk_callback, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865 }
866
867 for (i = 0; i < num_bulk_out; ++i) {
868 endpoint = bulk_out_endpoint[i];
869 port = serial->port[i];
870 port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
871 if (!port->write_urb) {
872 dev_err(&interface->dev, "No free urbs available\n");
873 goto probe_error;
874 }
875 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
876 port->bulk_out_size = buffer_size;
877 port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100878 port->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879 if (!port->bulk_out_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100880 dev_err(&interface->dev,
881 "Couldn't allocate bulk_out_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 goto probe_error;
883 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100884 usb_fill_bulk_urb(port->write_urb, dev,
885 usb_sndbulkpipe(dev,
886 endpoint->bEndpointAddress),
887 port->bulk_out_buffer, buffer_size,
888 serial->type->write_bulk_callback, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 }
890
891 if (serial->type->read_int_callback) {
892 for (i = 0; i < num_interrupt_in; ++i) {
893 endpoint = interrupt_in_endpoint[i];
894 port = serial->port[i];
895 port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
896 if (!port->interrupt_in_urb) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100897 dev_err(&interface->dev,
898 "No free urbs available\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 goto probe_error;
900 }
901 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100902 port->interrupt_in_endpointAddress =
903 endpoint->bEndpointAddress;
904 port->interrupt_in_buffer = kmalloc(buffer_size,
905 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 if (!port->interrupt_in_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100907 dev_err(&interface->dev,
908 "Couldn't allocate interrupt_in_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 goto probe_error;
910 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100911 usb_fill_int_urb(port->interrupt_in_urb, dev,
912 usb_rcvintpipe(dev,
913 endpoint->bEndpointAddress),
914 port->interrupt_in_buffer, buffer_size,
915 serial->type->read_int_callback, port,
916 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 }
918 } else if (num_interrupt_in) {
919 dbg("the device claims to support interrupt in transfers, but read_int_callback is not defined");
920 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100921
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 if (serial->type->write_int_callback) {
923 for (i = 0; i < num_interrupt_out; ++i) {
924 endpoint = interrupt_out_endpoint[i];
925 port = serial->port[i];
926 port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
927 if (!port->interrupt_out_urb) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100928 dev_err(&interface->dev,
929 "No free urbs available\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 goto probe_error;
931 }
932 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
933 port->interrupt_out_size = buffer_size;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100934 port->interrupt_out_endpointAddress =
935 endpoint->bEndpointAddress;
936 port->interrupt_out_buffer = kmalloc(buffer_size,
937 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 if (!port->interrupt_out_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100939 dev_err(&interface->dev,
940 "Couldn't allocate interrupt_out_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941 goto probe_error;
942 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100943 usb_fill_int_urb(port->interrupt_out_urb, dev,
944 usb_sndintpipe(dev,
945 endpoint->bEndpointAddress),
946 port->interrupt_out_buffer, buffer_size,
947 serial->type->write_int_callback, port,
948 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 }
950 } else if (num_interrupt_out) {
951 dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined");
952 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100953
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 /* if this device type has an attach function, call it */
955 if (type->attach) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700956 if (!try_module_get(type->driver.owner)) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100957 dev_err(&interface->dev,
958 "module get failed, exiting\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959 goto probe_error;
960 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100961 retval = type->attach(serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700962 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 if (retval < 0)
964 goto probe_error;
965 if (retval > 0) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100966 /* quietly accept this device, but don't bind to a
967 serial port as it's about to disappear */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 goto exit;
969 }
970 }
971
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100972 if (get_free_serial(serial, num_ports, &minor) == NULL) {
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100973 dev_err(&interface->dev, "No more free serial devices\n");
974 goto probe_error;
975 }
Oliver Neukumc744f992007-02-26 15:43:00 +0100976 serial->minor = minor;
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100977
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 /* register all of the individual ports with the driver core */
979 for (i = 0; i < num_ports; ++i) {
980 port = serial->port[i];
981 port->dev.parent = &interface->dev;
982 port->dev.driver = NULL;
983 port->dev.bus = &usb_serial_bus_type;
984 port->dev.release = &port_release;
985
Kay Sievers0031a062008-05-02 06:02:41 +0200986 dev_set_name(&port->dev, "ttyUSB%d", port->number);
Kay Sievers7071a3c2008-05-02 06:02:41 +0200987 dbg ("%s - registering %s", __func__, dev_name(&port->dev));
Greg Kroah-Hartman13f4db92006-08-28 11:43:25 -0700988 retval = device_register(&port->dev);
989 if (retval)
990 dev_err(&port->dev, "Error registering port device, "
991 "continuing\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 }
993
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100994 usb_serial_console_init(debug, minor);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995
996exit:
997 /* success */
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100998 usb_set_intfdata(interface, serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999 return 0;
1000
1001probe_error:
1002 for (i = 0; i < num_bulk_in; ++i) {
1003 port = serial->port[i];
1004 if (!port)
1005 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001006 usb_free_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 kfree(port->bulk_in_buffer);
1008 }
1009 for (i = 0; i < num_bulk_out; ++i) {
1010 port = serial->port[i];
1011 if (!port)
1012 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001013 usb_free_urb(port->write_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 kfree(port->bulk_out_buffer);
1015 }
1016 for (i = 0; i < num_interrupt_in; ++i) {
1017 port = serial->port[i];
1018 if (!port)
1019 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001020 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 kfree(port->interrupt_in_buffer);
1022 }
1023 for (i = 0; i < num_interrupt_out; ++i) {
1024 port = serial->port[i];
1025 if (!port)
1026 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001027 usb_free_urb(port->interrupt_out_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 kfree(port->interrupt_out_buffer);
1029 }
1030
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 /* free up any memory that we allocated */
1032 for (i = 0; i < serial->num_port_pointers; ++i)
1033 kfree(serial->port[i]);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001034 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 return -EIO;
1036}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001037EXPORT_SYMBOL_GPL(usb_serial_probe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038
1039void usb_serial_disconnect(struct usb_interface *interface)
1040{
1041 int i;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001042 struct usb_serial *serial = usb_get_intfdata(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 struct device *dev = &interface->dev;
1044 struct usb_serial_port *port;
1045
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +02001046 usb_serial_console_disconnect(serial);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001047 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001049 mutex_lock(&serial->disc_mutex);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001050 usb_set_intfdata(interface, NULL);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001051 /* must set a flag, to signal subdrivers */
1052 serial->disconnected = 1;
1053 for (i = 0; i < serial->num_ports; ++i) {
1054 port = serial->port[i];
1055 if (port) {
Alan Cox4a90f092008-10-13 10:39:46 +01001056 struct tty_struct *tty = tty_port_tty_get(&port->port);
1057 if (tty) {
1058 tty_hangup(tty);
1059 tty_kref_put(tty);
1060 }
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001061 kill_traffic(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063 }
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001064 /* let the last holder of this object
1065 * cause it to be cleaned up */
1066 mutex_unlock(&serial->disc_mutex);
1067 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 dev_info(dev, "device disconnected\n");
1069}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001070EXPORT_SYMBOL_GPL(usb_serial_disconnect);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071
Oliver Neukumec225592007-04-27 20:54:57 +02001072int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
1073{
1074 struct usb_serial *serial = usb_get_intfdata(intf);
1075 struct usb_serial_port *port;
1076 int i, r = 0;
1077
Oliver Neukume31c1882007-07-23 08:58:39 +02001078 for (i = 0; i < serial->num_ports; ++i) {
1079 port = serial->port[i];
1080 if (port)
1081 kill_traffic(port);
Oliver Neukumec225592007-04-27 20:54:57 +02001082 }
1083
1084 if (serial->type->suspend)
Oliver Neukume31c1882007-07-23 08:58:39 +02001085 r = serial->type->suspend(serial, message);
Oliver Neukumec225592007-04-27 20:54:57 +02001086
1087 return r;
1088}
1089EXPORT_SYMBOL(usb_serial_suspend);
1090
1091int usb_serial_resume(struct usb_interface *intf)
1092{
1093 struct usb_serial *serial = usb_get_intfdata(intf);
1094
Sarah Sharp8abaee22007-10-25 10:58:43 -07001095 if (serial->type->resume)
1096 return serial->type->resume(serial);
1097 return 0;
Oliver Neukumec225592007-04-27 20:54:57 +02001098}
1099EXPORT_SYMBOL(usb_serial_resume);
1100
Jeff Dikeb68e31d2006-10-02 02:17:18 -07001101static const struct tty_operations serial_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102 .open = serial_open,
1103 .close = serial_close,
1104 .write = serial_write,
1105 .write_room = serial_write_room,
1106 .ioctl = serial_ioctl,
1107 .set_termios = serial_set_termios,
1108 .throttle = serial_throttle,
1109 .unthrottle = serial_unthrottle,
1110 .break_ctl = serial_break,
1111 .chars_in_buffer = serial_chars_in_buffer,
1112 .read_proc = serial_read_proc,
1113 .tiocmget = serial_tiocmget,
1114 .tiocmset = serial_tiocmset,
1115};
1116
1117struct tty_driver *usb_serial_tty_driver;
1118
1119static int __init usb_serial_init(void)
1120{
1121 int i;
1122 int result;
1123
1124 usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS);
1125 if (!usb_serial_tty_driver)
1126 return -ENOMEM;
1127
1128 /* Initialize our global data */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001129 for (i = 0; i < SERIAL_TTY_MINORS; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130 serial_table[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131
1132 result = bus_register(&usb_serial_bus_type);
1133 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001134 printk(KERN_ERR "usb-serial: %s - registering bus driver "
1135 "failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136 goto exit_bus;
1137 }
1138
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139 usb_serial_tty_driver->owner = THIS_MODULE;
1140 usb_serial_tty_driver->driver_name = "usbserial";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 usb_serial_tty_driver->name = "ttyUSB";
1142 usb_serial_tty_driver->major = SERIAL_TTY_MAJOR;
1143 usb_serial_tty_driver->minor_start = 0;
1144 usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
1145 usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001146 usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW |
1147 TTY_DRIVER_DYNAMIC_DEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 usb_serial_tty_driver->init_termios = tty_std_termios;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001149 usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD
1150 | HUPCL | CLOCAL;
Alan Coxa5b6f602008-04-08 17:16:06 +01001151 usb_serial_tty_driver->init_termios.c_ispeed = 9600;
1152 usb_serial_tty_driver->init_termios.c_ospeed = 9600;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153 tty_set_operations(usb_serial_tty_driver, &serial_ops);
1154 result = tty_register_driver(usb_serial_tty_driver);
1155 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001156 printk(KERN_ERR "usb-serial: %s - tty_register_driver failed\n",
1157 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158 goto exit_reg_driver;
1159 }
1160
1161 /* register the USB driver */
1162 result = usb_register(&usb_serial_driver);
1163 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001164 printk(KERN_ERR "usb-serial: %s - usb_register failed\n",
1165 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166 goto exit_tty;
1167 }
1168
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001169 /* register the generic driver, if we should */
1170 result = usb_serial_generic_register(debug);
1171 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001172 printk(KERN_ERR "usb-serial: %s - registering generic "
1173 "driver failed\n", __func__);
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001174 goto exit_generic;
1175 }
1176
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001177 printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178
1179 return result;
1180
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001181exit_generic:
1182 usb_deregister(&usb_serial_driver);
1183
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184exit_tty:
1185 tty_unregister_driver(usb_serial_tty_driver);
1186
1187exit_reg_driver:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 bus_unregister(&usb_serial_bus_type);
1189
1190exit_bus:
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001191 printk(KERN_ERR "usb-serial: %s - returning with error %d\n",
1192 __func__, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193 put_tty_driver(usb_serial_tty_driver);
1194 return result;
1195}
1196
1197
1198static void __exit usb_serial_exit(void)
1199{
1200 usb_serial_console_exit();
1201
1202 usb_serial_generic_deregister();
1203
1204 usb_deregister(&usb_serial_driver);
1205 tty_unregister_driver(usb_serial_tty_driver);
1206 put_tty_driver(usb_serial_tty_driver);
1207 bus_unregister(&usb_serial_bus_type);
1208}
1209
1210
1211module_init(usb_serial_init);
1212module_exit(usb_serial_exit);
1213
1214#define set_to_generic_if_null(type, function) \
1215 do { \
1216 if (!type->function) { \
1217 type->function = usb_serial_generic_##function; \
1218 dbg("Had to override the " #function \
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001219 " usb serial operation with the generic one.");\
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 } \
1221 } while (0)
1222
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001223static void fixup_generic(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224{
1225 set_to_generic_if_null(device, open);
1226 set_to_generic_if_null(device, write);
1227 set_to_generic_if_null(device, close);
1228 set_to_generic_if_null(device, write_room);
1229 set_to_generic_if_null(device, chars_in_buffer);
1230 set_to_generic_if_null(device, read_bulk_callback);
1231 set_to_generic_if_null(device, write_bulk_callback);
1232 set_to_generic_if_null(device, shutdown);
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -08001233 set_to_generic_if_null(device, resume);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234}
1235
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001236int usb_serial_register(struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001238 /* must be called with BKL held */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239 int retval;
1240
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001241 fixup_generic(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001243 if (!driver->description)
1244 driver->description = driver->driver.name;
1245
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246 /* Add this device to our list of devices */
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001247 list_add(&driver->driver_list, &usb_serial_driver_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001249 retval = usb_serial_bus_register(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250 if (retval) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001251 printk(KERN_ERR "usb-serial: problem %d when registering "
1252 "driver %s\n", retval, driver->description);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001253 list_del(&driver->driver_list);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001254 } else
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001255 printk(KERN_INFO "USB Serial support registered for %s\n",
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001256 driver->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257
1258 return retval;
1259}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001260EXPORT_SYMBOL_GPL(usb_serial_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261
1262
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001263void usb_serial_deregister(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001265 /* must be called with BKL held */
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001266 printk(KERN_INFO "USB Serial deregistering driver %s\n",
1267 device->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 list_del(&device->driver_list);
1269 usb_serial_bus_deregister(device);
1270}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271EXPORT_SYMBOL_GPL(usb_serial_deregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272
1273/* Module information */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001274MODULE_AUTHOR(DRIVER_AUTHOR);
1275MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276MODULE_LICENSE("GPL");
1277
1278module_param(debug, bool, S_IRUGO | S_IWUSR);
1279MODULE_PARM_DESC(debug, "Debug enabled or not");