blob: bd7581b3a48afd3beb2f3eeef28ca604c8c08842 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * USB Serial Converter driver
3 *
Greg Kroah-Hartman502b95c2005-06-20 21:15:16 -07004 * Copyright (C) 1999 - 2005 Greg Kroah-Hartman (greg@kroah.com)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 * Copyright (C) 2000 Peter Berger (pberger@brimson.com)
6 * Copyright (C) 2000 Al Borchers (borchers@steinerpoint.com)
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version
10 * 2 as published by the Free Software Foundation.
11 *
Greg Kroah-Hartman502b95c2005-06-20 21:15:16 -070012 * This driver was originally based on the ACM driver by Armin Fuerst (which was
Linus Torvalds1da177e2005-04-16 15:20:36 -070013 * based on a driver by Brad Keryan)
14 *
Alan Coxa8d6f0a2008-07-22 11:12:24 +010015 * See Documentation/usb/usb-serial.txt for more information on using this
16 * driver
Linus Torvalds1da177e2005-04-16 15:20:36 -070017 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 */
19
Linus Torvalds1da177e2005-04-16 15:20:36 -070020#include <linux/kernel.h>
21#include <linux/errno.h>
22#include <linux/init.h>
23#include <linux/slab.h>
Alexey Dobriyan405f5572009-07-11 22:08:37 +040024#include <linux/smp_lock.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <linux/tty.h>
26#include <linux/tty_driver.h>
27#include <linux/tty_flip.h>
28#include <linux/module.h>
29#include <linux/moduleparam.h>
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -070030#include <linux/seq_file.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <linux/spinlock.h>
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -030032#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/list.h>
Alan Coxa8d6f0a2008-07-22 11:12:24 +010034#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/usb.h>
Greg Kroah-Hartmana9698882006-07-11 21:22:58 -070036#include <linux/usb/serial.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include "pl2303.h"
38
39/*
40 * Version Information
41 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/"
43#define DRIVER_DESC "USB Serial Driver core"
44
Pete Zaitcev34f8e762006-06-21 15:00:45 -070045static void port_free(struct usb_serial_port *port);
46
Linus Torvalds1da177e2005-04-16 15:20:36 -070047/* Driver structure we register with the USB core */
48static struct usb_driver usb_serial_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070049 .name = "usbserial",
50 .probe = usb_serial_probe,
51 .disconnect = usb_serial_disconnect,
Oliver Neukumec225592007-04-27 20:54:57 +020052 .suspend = usb_serial_suspend,
53 .resume = usb_serial_resume,
Greg Kroah-Hartmanba9dc652005-11-16 13:41:28 -080054 .no_dynamic_id = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -070055};
56
57/* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead
58 the MODULE_DEVICE_TABLE declarations in each serial driver
59 cause the "hotplug" program to pull in whatever module is necessary
60 via modprobe, and modprobe will load usbserial because the serial
61 drivers depend on it.
62*/
63
64static int debug;
Alan Coxa8d6f0a2008-07-22 11:12:24 +010065/* initially all NULL */
66static struct usb_serial *serial_table[SERIAL_TTY_MINORS];
Oliver Neukum3ddad822007-07-24 15:13:42 +020067static DEFINE_MUTEX(table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070068static LIST_HEAD(usb_serial_driver_list);
69
70struct usb_serial *usb_serial_get_by_index(unsigned index)
71{
Oliver Neukum34ef50e2007-01-13 07:29:26 +010072 struct usb_serial *serial;
73
Oliver Neukum3ddad822007-07-24 15:13:42 +020074 mutex_lock(&table_lock);
Oliver Neukum34ef50e2007-01-13 07:29:26 +010075 serial = serial_table[index];
Linus Torvalds1da177e2005-04-16 15:20:36 -070076
77 if (serial)
78 kref_get(&serial->kref);
Oliver Neukum3ddad822007-07-24 15:13:42 +020079 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070080 return serial;
81}
82
Alan Coxa8d6f0a2008-07-22 11:12:24 +010083static struct usb_serial *get_free_serial(struct usb_serial *serial,
84 int num_ports, unsigned int *minor)
Linus Torvalds1da177e2005-04-16 15:20:36 -070085{
86 unsigned int i, j;
87 int good_spot;
88
Harvey Harrison441b62c2008-03-03 16:08:34 -080089 dbg("%s %d", __func__, num_ports);
Linus Torvalds1da177e2005-04-16 15:20:36 -070090
91 *minor = 0;
Oliver Neukum3ddad822007-07-24 15:13:42 +020092 mutex_lock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070093 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
94 if (serial_table[i])
95 continue;
96
97 good_spot = 1;
98 for (j = 1; j <= num_ports-1; ++j)
99 if ((i+j >= SERIAL_TTY_MINORS) || (serial_table[i+j])) {
100 good_spot = 0;
101 i += j;
102 break;
103 }
104 if (good_spot == 0)
105 continue;
106
107 *minor = i;
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100108 j = 0;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800109 dbg("%s - minor base = %d", __func__, *minor);
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100110 for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111 serial_table[i] = serial;
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100112 serial->port[j++]->number = i;
113 }
Oliver Neukum3ddad822007-07-24 15:13:42 +0200114 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115 return serial;
116 }
Oliver Neukum3ddad822007-07-24 15:13:42 +0200117 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 return NULL;
119}
120
121static void return_serial(struct usb_serial *serial)
122{
123 int i;
124
Harvey Harrison441b62c2008-03-03 16:08:34 -0800125 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100127 for (i = 0; i < serial->num_ports; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128 serial_table[serial->minor + i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129}
130
131static void destroy_serial(struct kref *kref)
132{
133 struct usb_serial *serial;
134 struct usb_serial_port *port;
135 int i;
136
137 serial = to_usb_serial(kref);
138
Harvey Harrison441b62c2008-03-03 16:08:34 -0800139 dbg("%s - %s", __func__, serial->type->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140
Jim Radford521b85a2007-03-13 08:30:50 -0700141 /* 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
Alan Sternf9c99bb2009-06-02 11:53:55 -0400145 serial->type->release(serial);
146
147 for (i = 0; i < serial->num_ports; ++i) {
148 port = serial->port[i];
149 if (port)
150 put_device(&port->dev);
151 }
152
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153 /* If this is a "fake" port, we have to clean it up here, as it will
154 * not get cleaned up in port_release() as it was never registered with
155 * the driver core */
156 if (serial->num_ports < serial->num_port_pointers) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100157 for (i = serial->num_ports;
158 i < serial->num_port_pointers; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 port = serial->port[i];
Alan Sternf9c99bb2009-06-02 11:53:55 -0400160 if (port)
161 port_free(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 }
163 }
164
165 usb_put_dev(serial->dev);
166
167 /* free up any memory that we allocated */
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100168 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169}
170
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200171void usb_serial_put(struct usb_serial *serial)
172{
Oliver Neukum3ddad822007-07-24 15:13:42 +0200173 mutex_lock(&table_lock);
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200174 kref_put(&serial->kref, destroy_serial);
Oliver Neukum3ddad822007-07-24 15:13:42 +0200175 mutex_unlock(&table_lock);
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200176}
177
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178/*****************************************************************************
179 * Driver tty interface functions
180 *****************************************************************************/
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100181static int serial_open (struct tty_struct *tty, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182{
183 struct usb_serial *serial;
184 struct usb_serial_port *port;
185 unsigned int portNumber;
Alan Stern2d931482009-04-14 11:31:02 -0400186 int retval = 0;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100187
Harvey Harrison441b62c2008-03-03 16:08:34 -0800188 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189
190 /* get the serial object associated with this tty pointer */
191 serial = usb_serial_get_by_index(tty->index);
192 if (!serial) {
193 tty->driver_data = NULL;
194 return -ENODEV;
195 }
196
Alan Stern2d931482009-04-14 11:31:02 -0400197 mutex_lock(&serial->disc_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198 portNumber = tty->index - serial->minor;
199 port = serial->port[portNumber];
Alan Stern2d931482009-04-14 11:31:02 -0400200 if (!port || serial->disconnected)
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300201 retval = -ENODEV;
Alan Stern2d931482009-04-14 11:31:02 -0400202 else
203 get_device(&port->dev);
204 /*
205 * Note: Our locking order requirement does not allow port->mutex
206 * to be acquired while serial->disc_mutex is held.
207 */
208 mutex_unlock(&serial->disc_mutex);
209 if (retval)
210 goto bailout_serial_put;
James Woodcock331879f2009-02-11 15:06:53 +0000211
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300212 if (mutex_lock_interruptible(&port->mutex)) {
213 retval = -ERESTARTSYS;
Alan Stern2d931482009-04-14 11:31:02 -0400214 goto bailout_port_put;
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300215 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100216
Alan Cox95da3102008-07-22 11:09:07 +0100217 ++port->port.count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218
Paul Fulghumca854852006-04-13 22:28:17 +0200219 /* set up our port structure making the tty driver
220 * remember our port object, and us it */
221 tty->driver_data = port;
Alan Cox4a90f092008-10-13 10:39:46 +0100222 tty_port_tty_set(&port->port, tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223
Jason Wessel6e406122009-06-22 11:32:20 -0500224 /* If the console is attached, the device is already open */
225 if (port->port.count == 1 && !port->console) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226
227 /* lock this module before we call it
228 * this may fail, which means we must bail out,
229 * safe because we are called with BKL held */
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700230 if (!try_module_get(serial->type->driver.owner)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231 retval = -ENODEV;
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300232 goto bailout_mutex_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 }
234
Alan Stern2d931482009-04-14 11:31:02 -0400235 mutex_lock(&serial->disc_mutex);
236 if (serial->disconnected)
237 retval = -ENODEV;
238 else
239 retval = usb_autopm_get_interface(serial->interface);
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800240 if (retval)
241 goto bailout_module_put;
Alan Stern2d931482009-04-14 11:31:02 -0400242
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100243 /* only call the device specific open if this
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 * is the first time the port is opened */
Alan Cox95da3102008-07-22 11:09:07 +0100245 retval = serial->type->open(tty, port, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246 if (retval)
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800247 goto bailout_interface_put;
Alan Stern2d931482009-04-14 11:31:02 -0400248 mutex_unlock(&serial->disc_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249 }
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300250 mutex_unlock(&port->mutex);
Alan Cox335f8512009-06-11 12:26:29 +0100251 /* Now do the correct tty layer semantics */
252 retval = tty_port_block_til_ready(&port->port, tty, filp);
253 if (retval == 0)
254 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800256bailout_interface_put:
257 usb_autopm_put_interface(serial->interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258bailout_module_put:
Alan Stern2d931482009-04-14 11:31:02 -0400259 mutex_unlock(&serial->disc_mutex);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700260 module_put(serial->type->driver.owner);
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300261bailout_mutex_unlock:
Alan Cox95da3102008-07-22 11:09:07 +0100262 port->port.count = 0;
Frank Gevaertsb059c812006-06-14 15:52:05 +0200263 tty->driver_data = NULL;
Alan Cox4a90f092008-10-13 10:39:46 +0100264 tty_port_tty_set(&port->port, NULL);
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300265 mutex_unlock(&port->mutex);
Alan Stern2d931482009-04-14 11:31:02 -0400266bailout_port_put:
267 put_device(&port->dev);
268bailout_serial_put:
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200269 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 return retval;
271}
272
Alan Cox335f8512009-06-11 12:26:29 +0100273/**
274 * serial_do_down - shut down hardware
275 * @port: port to shut down
276 *
277 * Shut down a USB port unless it is the console. We never shut down the
278 * console hardware as it will always be in use.
279 *
280 * Don't free any resources at this point
281 */
282static void serial_do_down(struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283{
Alan Cox335f8512009-06-11 12:26:29 +0100284 struct usb_serial_driver *drv = port->serial->type;
Alan Stern2d931482009-04-14 11:31:02 -0400285 struct usb_serial *serial;
286 struct module *owner;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287
Alan Cox335f8512009-06-11 12:26:29 +0100288 /* The console is magical, do not hang up the console hardware
289 or there will be tears */
290 if (port->console)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 return;
292
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300293 mutex_lock(&port->mutex);
Alan Stern2d931482009-04-14 11:31:02 -0400294 serial = port->serial;
295 owner = serial->type->driver.owner;
Luiz Fernando Capitulino8a4613f2005-11-28 19:16:07 -0200296
Alan Cox335f8512009-06-11 12:26:29 +0100297 if (drv->close)
298 drv->close(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300300 mutex_unlock(&port->mutex);
Alan Cox335f8512009-06-11 12:26:29 +0100301}
302
303/**
304 * serial_do_free - free resources post close/hangup
305 * @port: port to free up
306 *
307 * Do the resource freeing and refcount dropping for the port. We must
308 * be careful about ordering and we must avoid freeing up the console.
309 */
310
311static void serial_do_free(struct usb_serial_port *port)
312{
313 struct usb_serial *serial;
314 struct module *owner;
315
316 /* The console is magical, do not hang up the console hardware
317 or there will be tears */
318 if (port->console)
319 return;
320
321 serial = port->serial;
322 owner = serial->type->driver.owner;
Alan Stern2d931482009-04-14 11:31:02 -0400323 put_device(&port->dev);
Alan Stern2d931482009-04-14 11:31:02 -0400324 /* Mustn't dereference port any more */
Alan Cox335f8512009-06-11 12:26:29 +0100325 mutex_lock(&serial->disc_mutex);
326 if (!serial->disconnected)
327 usb_autopm_put_interface(serial->interface);
328 mutex_unlock(&serial->disc_mutex);
Alan Stern2d931482009-04-14 11:31:02 -0400329 usb_serial_put(serial);
Alan Stern2d931482009-04-14 11:31:02 -0400330 /* Mustn't dereference serial any more */
Alan Cox335f8512009-06-11 12:26:29 +0100331 module_put(owner);
332}
333
334static void serial_close(struct tty_struct *tty, struct file *filp)
335{
336 struct usb_serial_port *port = tty->driver_data;
337
Thadeu Lima de Souza Cascardof4fa4462009-06-25 14:41:37 +0100338 if (!port)
339 return;
340
Alan Cox335f8512009-06-11 12:26:29 +0100341 dbg("%s - port %d", __func__, port->number);
342
343
344 if (tty_port_close_start(&port->port, tty, filp) == 0)
345 return;
346
347 serial_do_down(port);
348 tty_port_close_end(&port->port, tty);
349 tty_port_tty_set(&port->port, NULL);
350 serial_do_free(port);
351}
352
353static void serial_hangup(struct tty_struct *tty)
354{
355 struct usb_serial_port *port = tty->driver_data;
356 serial_do_down(port);
357 tty_port_hangup(&port->port);
358 serial_do_free(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359}
360
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100361static int serial_write(struct tty_struct *tty, const unsigned char *buf,
362 int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200364 struct usb_serial_port *port = tty->driver_data;
Oliver Neukum3ff4fd92007-01-13 07:32:27 +0100365 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366
Alan Coxf34d7a52008-04-30 00:54:13 -0700367 if (port->serial->dev->state == USB_STATE_NOTATTACHED)
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200368 goto exit;
369
Harvey Harrison441b62c2008-03-03 16:08:34 -0800370 dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371
Alan Cox95da3102008-07-22 11:09:07 +0100372 /* count is managed under the mutex lock for the tty so cannot
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100373 drop to zero until after the last close completes */
Alan Cox95da3102008-07-22 11:09:07 +0100374 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375
376 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100377 retval = port->serial->type->write(tty, port, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378
379exit:
380 return retval;
381}
382
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100383static int serial_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200385 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800386 dbg("%s - port %d", __func__, port->number);
Alan Cox95da3102008-07-22 11:09:07 +0100387 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100389 return port->serial->type->write_room(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390}
391
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100392static int serial_chars_in_buffer(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200394 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800395 dbg("%s = port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396
Alan Cox95da3102008-07-22 11:09:07 +0100397 WARN_ON(!port->port.count);
Alan Coxeff69372009-01-02 13:47:06 +0000398 /* if the device was unplugged then any remaining characters
399 fell out of the connector ;) */
400 if (port->serial->disconnected)
401 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100403 return port->serial->type->chars_in_buffer(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404}
405
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100406static void serial_throttle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200408 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800409 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410
Alan Cox95da3102008-07-22 11:09:07 +0100411 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 /* pass on to the driver specific version of this function */
413 if (port->serial->type->throttle)
Alan Cox95da3102008-07-22 11:09:07 +0100414 port->serial->type->throttle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415}
416
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100417static void serial_unthrottle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200419 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800420 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421
Alan Cox95da3102008-07-22 11:09:07 +0100422 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 /* pass on to the driver specific version of this function */
424 if (port->serial->type->unthrottle)
Alan Cox95da3102008-07-22 11:09:07 +0100425 port->serial->type->unthrottle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426}
427
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100428static int serial_ioctl(struct tty_struct *tty, struct file *file,
429 unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200431 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 int retval = -ENODEV;
433
Harvey Harrison441b62c2008-03-03 16:08:34 -0800434 dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435
Alan Cox95da3102008-07-22 11:09:07 +0100436 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100438 /* pass on to the driver specific version of this function
439 if it is available */
Alan Coxf34d7a52008-04-30 00:54:13 -0700440 if (port->serial->type->ioctl) {
Alan Cox95da3102008-07-22 11:09:07 +0100441 retval = port->serial->type->ioctl(tty, file, cmd, arg);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100442 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 retval = -ENOIOCTLCMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 return retval;
445}
446
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100447static void serial_set_termios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200449 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800450 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451
Alan Cox95da3102008-07-22 11:09:07 +0100452 WARN_ON(!port->port.count);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100453 /* pass on to the driver specific version of this function
454 if it is available */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 if (port->serial->type->set_termios)
Alan Cox95da3102008-07-22 11:09:07 +0100456 port->serial->type->set_termios(tty, port, old);
Alan Cox33785092007-10-18 01:24:22 -0700457 else
458 tty_termios_copy_hw(tty->termios, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459}
460
Alan Cox9e989662008-07-22 11:18:03 +0100461static int serial_break(struct tty_struct *tty, int break_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200463 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464
Harvey Harrison441b62c2008-03-03 16:08:34 -0800465 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466
Alan Cox95da3102008-07-22 11:09:07 +0100467 WARN_ON(!port->port.count);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100468 /* pass on to the driver specific version of this function
469 if it is available */
Alan Cox6b447f042009-01-02 13:48:56 +0000470 if (port->serial->type->break_ctl)
Alan Cox95da3102008-07-22 11:09:07 +0100471 port->serial->type->break_ctl(tty, break_state);
Alan Cox9e989662008-07-22 11:18:03 +0100472 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473}
474
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700475static int serial_proc_show(struct seq_file *m, void *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476{
477 struct usb_serial *serial;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479 char tmp[40];
480
Harvey Harrison441b62c2008-03-03 16:08:34 -0800481 dbg("%s", __func__);
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700482 seq_puts(m, "usbserinfo:1.0 driver:2.0\n");
483 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 serial = usb_serial_get_by_index(i);
485 if (serial == NULL)
486 continue;
487
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700488 seq_printf(m, "%d:", i);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700489 if (serial->type->driver.owner)
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700490 seq_printf(m, " module:%s",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100491 module_name(serial->type->driver.owner));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700492 seq_printf(m, " name:\"%s\"",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100493 serial->type->description);
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700494 seq_printf(m, " vendor:%04x product:%04x",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100495 le16_to_cpu(serial->dev->descriptor.idVendor),
496 le16_to_cpu(serial->dev->descriptor.idProduct));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700497 seq_printf(m, " num_ports:%d", serial->num_ports);
498 seq_printf(m, " port:%d", i - serial->minor + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 usb_make_path(serial->dev, tmp, sizeof(tmp));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700500 seq_printf(m, " path:%s", tmp);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100501
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700502 seq_putc(m, '\n');
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200503 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 }
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700505 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506}
507
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700508static int serial_proc_open(struct inode *inode, struct file *file)
509{
510 return single_open(file, serial_proc_show, NULL);
511}
512
513static const struct file_operations serial_proc_fops = {
514 .owner = THIS_MODULE,
515 .open = serial_proc_open,
516 .read = seq_read,
517 .llseek = seq_lseek,
518 .release = single_release,
519};
520
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100521static int serial_tiocmget(struct tty_struct *tty, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200523 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524
Harvey Harrison441b62c2008-03-03 16:08:34 -0800525 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526
Alan Cox95da3102008-07-22 11:09:07 +0100527 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 if (port->serial->type->tiocmget)
Alan Cox95da3102008-07-22 11:09:07 +0100529 return port->serial->type->tiocmget(tty, file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 return -EINVAL;
531}
532
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100533static int serial_tiocmset(struct tty_struct *tty, struct file *file,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534 unsigned int set, unsigned int clear)
535{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200536 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537
Harvey Harrison441b62c2008-03-03 16:08:34 -0800538 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539
Alan Cox95da3102008-07-22 11:09:07 +0100540 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 if (port->serial->type->tiocmset)
Alan Cox95da3102008-07-22 11:09:07 +0100542 return port->serial->type->tiocmset(tty, file, set, clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 return -EINVAL;
544}
545
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700546/*
547 * We would be calling tty_wakeup here, but unfortunately some line
548 * disciplines have an annoying habit of calling tty->write from
549 * the write wakeup callback (e.g. n_hdlc.c).
550 */
551void usb_serial_port_softint(struct usb_serial_port *port)
552{
553 schedule_work(&port->work);
554}
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100555EXPORT_SYMBOL_GPL(usb_serial_port_softint);
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700556
David Howellsc4028952006-11-22 14:57:56 +0000557static void usb_serial_port_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558{
David Howellsc4028952006-11-22 14:57:56 +0000559 struct usb_serial_port *port =
560 container_of(work, struct usb_serial_port, work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561 struct tty_struct *tty;
562
Harvey Harrison441b62c2008-03-03 16:08:34 -0800563 dbg("%s - port %d", __func__, port->number);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100564
Alan Cox4a90f092008-10-13 10:39:46 +0100565 tty = tty_port_tty_get(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 if (!tty)
567 return;
568
569 tty_wakeup(tty);
Alan Cox4a90f092008-10-13 10:39:46 +0100570 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571}
572
573static void port_release(struct device *dev)
574{
575 struct usb_serial_port *port = to_usb_serial_port(dev);
576
Kay Sievers7071a3c2008-05-02 06:02:41 +0200577 dbg ("%s - %s", __func__, dev_name(dev));
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700578 port_free(port);
579}
580
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100581static void kill_traffic(struct usb_serial_port *port)
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700582{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584 usb_kill_urb(port->write_urb);
Oliver Neukum5adceac2007-08-17 14:01:38 +0200585 /*
586 * This is tricky.
587 * Some drivers submit the read_urb in the
588 * handler for the write_urb or vice versa
589 * this order determines the order in which
590 * usb_kill_urb() must be used to reliably
591 * kill the URBs. As it is unknown here,
592 * both orders must be used in turn.
593 * The call below is not redundant.
594 */
595 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596 usb_kill_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 usb_kill_urb(port->interrupt_out_urb);
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100598}
599
600static void port_free(struct usb_serial_port *port)
601{
Alan Stern2d931482009-04-14 11:31:02 -0400602 /*
603 * Stop all the traffic before cancelling the work, so that
604 * nobody will restart it by calling usb_serial_port_softint.
605 */
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100606 kill_traffic(port);
Alan Stern2d931482009-04-14 11:31:02 -0400607 cancel_work_sync(&port->work);
608
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100609 usb_free_urb(port->read_urb);
610 usb_free_urb(port->write_urb);
611 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612 usb_free_urb(port->interrupt_out_urb);
613 kfree(port->bulk_in_buffer);
614 kfree(port->bulk_out_buffer);
615 kfree(port->interrupt_in_buffer);
616 kfree(port->interrupt_out_buffer);
617 kfree(port);
618}
619
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100620static struct usb_serial *create_serial(struct usb_device *dev,
621 struct usb_interface *interface,
622 struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623{
624 struct usb_serial *serial;
625
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100626 serial = kzalloc(sizeof(*serial), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627 if (!serial) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800628 dev_err(&dev->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629 return NULL;
630 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 serial->dev = usb_get_dev(dev);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700632 serial->type = driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 serial->interface = interface;
634 kref_init(&serial->kref);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +0100635 mutex_init(&serial->disc_mutex);
Alan Stern0282b7f2008-07-29 12:01:04 -0400636 serial->minor = SERIAL_TTY_NO_MINOR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637
638 return serial;
639}
640
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100641static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf,
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100642 struct usb_serial_driver *drv)
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100643{
644 struct usb_dynid *dynid;
645
646 spin_lock(&drv->dynids.lock);
647 list_for_each_entry(dynid, &drv->dynids.list, node) {
648 if (usb_match_one_id(intf, &dynid->id)) {
649 spin_unlock(&drv->dynids.lock);
650 return &dynid->id;
651 }
652 }
653 spin_unlock(&drv->dynids.lock);
654 return NULL;
655}
656
657static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv,
658 struct usb_interface *intf)
659{
660 const struct usb_device_id *id;
661
662 id = usb_match_id(intf, drv->id_table);
663 if (id) {
664 dbg("static descriptor matches");
665 goto exit;
666 }
667 id = match_dynamic_id(intf, drv);
668 if (id)
669 dbg("dynamic descriptor matches");
670exit:
671 return id;
672}
673
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100674static struct usb_serial_driver *search_serial_device(
675 struct usb_interface *iface)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 const struct usb_device_id *id;
Alan Stern063a2da2007-10-10 16:24:06 -0400678 struct usb_serial_driver *drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679
Adrian Bunk93b1fae2006-01-10 00:13:33 +0100680 /* Check if the usb id matches a known device */
Alan Stern063a2da2007-10-10 16:24:06 -0400681 list_for_each_entry(drv, &usb_serial_driver_list, driver_list) {
682 id = get_iface_id(drv, iface);
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100683 if (id)
Alan Stern063a2da2007-10-10 16:24:06 -0400684 return drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 }
686
687 return NULL;
688}
689
Alan Cox335f8512009-06-11 12:26:29 +0100690static int serial_carrier_raised(struct tty_port *port)
691{
692 struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
693 struct usb_serial_driver *drv = p->serial->type;
694 if (drv->carrier_raised)
695 return drv->carrier_raised(p);
696 /* No carrier control - don't block */
697 return 1;
698}
699
700static void serial_dtr_rts(struct tty_port *port, int on)
701{
702 struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
703 struct usb_serial_driver *drv = p->serial->type;
704 if (drv->dtr_rts)
705 drv->dtr_rts(p, on);
706}
707
708static const struct tty_port_operations serial_port_ops = {
709 .carrier_raised = serial_carrier_raised,
710 .dtr_rts = serial_dtr_rts,
711};
712
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713int usb_serial_probe(struct usb_interface *interface,
714 const struct usb_device_id *id)
715{
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100716 struct usb_device *dev = interface_to_usbdev(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717 struct usb_serial *serial = NULL;
718 struct usb_serial_port *port;
719 struct usb_host_interface *iface_desc;
720 struct usb_endpoint_descriptor *endpoint;
721 struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS];
722 struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS];
723 struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];
724 struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700725 struct usb_serial_driver *type = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726 int retval;
Andre Hauptdd9ca5d2008-06-18 15:56:00 +0200727 unsigned int minor;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 int buffer_size;
729 int i;
730 int num_interrupt_in = 0;
731 int num_interrupt_out = 0;
732 int num_bulk_in = 0;
733 int num_bulk_out = 0;
734 int num_ports = 0;
735 int max_endpoints;
736
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100737 lock_kernel(); /* guard against unloading a serial driver module */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738 type = search_serial_device(interface);
739 if (!type) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100740 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 dbg("none matched");
742 return -ENODEV;
743 }
744
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100745 serial = create_serial(dev, interface, type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 if (!serial) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100747 unlock_kernel();
Harvey Harrison441b62c2008-03-03 16:08:34 -0800748 dev_err(&interface->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 return -ENOMEM;
750 }
751
752 /* if this device type has a probe function, call it */
753 if (type->probe) {
754 const struct usb_device_id *id;
755
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700756 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100757 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100758 dev_err(&interface->dev,
759 "module get failed, exiting\n");
760 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 return -EIO;
762 }
763
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100764 id = get_iface_id(type, interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 retval = type->probe(serial, id);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700766 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767
768 if (retval) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100769 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100770 dbg("sub driver rejected device");
771 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 return retval;
773 }
774 }
775
776 /* descriptor matches, let's find the endpoints needed */
777 /* check out the endpoints */
778 iface_desc = interface->cur_altsetting;
779 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
780 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700781
782 if (usb_endpoint_is_bulk_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 /* we found a bulk in endpoint */
784 dbg("found bulk in on endpoint %d", i);
785 bulk_in_endpoint[num_bulk_in] = endpoint;
786 ++num_bulk_in;
787 }
788
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700789 if (usb_endpoint_is_bulk_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 /* we found a bulk out endpoint */
791 dbg("found bulk out on endpoint %d", i);
792 bulk_out_endpoint[num_bulk_out] = endpoint;
793 ++num_bulk_out;
794 }
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700795
796 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 /* we found a interrupt in endpoint */
798 dbg("found interrupt in on endpoint %d", i);
799 interrupt_in_endpoint[num_interrupt_in] = endpoint;
800 ++num_interrupt_in;
801 }
802
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700803 if (usb_endpoint_is_int_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 /* we found an interrupt out endpoint */
805 dbg("found interrupt out on endpoint %d", i);
806 interrupt_out_endpoint[num_interrupt_out] = endpoint;
807 ++num_interrupt_out;
808 }
809 }
810
811#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100812 /* BEGIN HORRIBLE HACK FOR PL2303 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813 /* this is needed due to the looney way its endpoints are set up */
814 if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&
815 (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||
816 ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) &&
Johannes Steingraeber8fd80132006-09-16 16:17:34 +0200817 (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) ||
818 ((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) &&
Andreas Bombece816cf2008-09-14 01:58:55 +0200819 (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID)) ||
820 ((le16_to_cpu(dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) &&
821 (le16_to_cpu(dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_EF81))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 if (interface != dev->actconfig->interface[0]) {
823 /* check out the endpoints of the other interface*/
824 iface_desc = dev->actconfig->interface[0]->cur_altsetting;
825 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
826 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700827 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828 /* we found a interrupt in endpoint */
829 dbg("found interrupt in for Prolific device on separate interface");
830 interrupt_in_endpoint[num_interrupt_in] = endpoint;
831 ++num_interrupt_in;
832 }
833 }
834 }
835
836 /* Now make sure the PL-2303 is configured correctly.
837 * If not, give up now and hope this hack will work
838 * properly during a later invocation of usb_serial_probe
839 */
840 if (num_bulk_in == 0 || num_bulk_out == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100841 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100843 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 return -ENODEV;
845 }
846 }
847 /* END HORRIBLE HACK FOR PL2303 */
848#endif
849
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850#ifdef CONFIG_USB_SERIAL_GENERIC
851 if (type == &usb_serial_generic_device) {
852 num_ports = num_bulk_out;
853 if (num_ports == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100854 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100855 dev_err(&interface->dev,
856 "Generic device with no bulk out, not allowed.\n");
857 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 return -EIO;
859 }
860 }
861#endif
862 if (!num_ports) {
863 /* if this device type has a calc_num_ports function, call it */
864 if (type->calc_num_ports) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700865 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100866 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100867 dev_err(&interface->dev,
868 "module get failed, exiting\n");
869 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 return -EIO;
871 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100872 num_ports = type->calc_num_ports(serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700873 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874 }
875 if (!num_ports)
876 num_ports = type->num_ports;
877 }
878
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879 serial->num_ports = num_ports;
880 serial->num_bulk_in = num_bulk_in;
881 serial->num_bulk_out = num_bulk_out;
882 serial->num_interrupt_in = num_interrupt_in;
883 serial->num_interrupt_out = num_interrupt_out;
884
Alan Stern063a2da2007-10-10 16:24:06 -0400885 /* found all that we need */
886 dev_info(&interface->dev, "%s converter detected\n",
887 type->description);
888
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 /* create our ports, we need as many as the max endpoints */
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100890 /* we don't use num_ports here because some devices have more
891 endpoint pairs than ports */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 max_endpoints = max(num_bulk_in, num_bulk_out);
893 max_endpoints = max(max_endpoints, num_interrupt_in);
894 max_endpoints = max(max_endpoints, num_interrupt_out);
895 max_endpoints = max(max_endpoints, (int)serial->num_ports);
896 serial->num_port_pointers = max_endpoints;
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100897 unlock_kernel();
898
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100899 dbg("%s - setting up %d port structures for this device",
900 __func__, max_endpoints);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 for (i = 0; i < max_endpoints; ++i) {
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100902 port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 if (!port)
904 goto probe_error;
Alan Cox4a90f092008-10-13 10:39:46 +0100905 tty_port_init(&port->port);
Alan Cox335f8512009-06-11 12:26:29 +0100906 port->port.ops = &serial_port_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 port->serial = serial;
Greg Kroah-Hartman507ca9b2005-04-23 12:49:16 -0700908 spin_lock_init(&port->lock);
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300909 mutex_init(&port->mutex);
David Howellsc4028952006-11-22 14:57:56 +0000910 INIT_WORK(&port->work, usb_serial_port_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 serial->port[i] = port;
912 }
913
914 /* set up the endpoint information */
915 for (i = 0; i < num_bulk_in; ++i) {
916 endpoint = bulk_in_endpoint[i];
917 port = serial->port[i];
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100918 port->read_urb = usb_alloc_urb(0, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 if (!port->read_urb) {
920 dev_err(&interface->dev, "No free urbs available\n");
921 goto probe_error;
922 }
923 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
924 port->bulk_in_size = buffer_size;
925 port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100926 port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 if (!port->bulk_in_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100928 dev_err(&interface->dev,
929 "Couldn't allocate bulk_in_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 goto probe_error;
931 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100932 usb_fill_bulk_urb(port->read_urb, dev,
933 usb_rcvbulkpipe(dev,
934 endpoint->bEndpointAddress),
935 port->bulk_in_buffer, buffer_size,
936 serial->type->read_bulk_callback, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937 }
938
939 for (i = 0; i < num_bulk_out; ++i) {
940 endpoint = bulk_out_endpoint[i];
941 port = serial->port[i];
942 port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
943 if (!port->write_urb) {
944 dev_err(&interface->dev, "No free urbs available\n");
945 goto probe_error;
946 }
947 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
948 port->bulk_out_size = buffer_size;
949 port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100950 port->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 if (!port->bulk_out_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100952 dev_err(&interface->dev,
953 "Couldn't allocate bulk_out_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 goto probe_error;
955 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100956 usb_fill_bulk_urb(port->write_urb, dev,
957 usb_sndbulkpipe(dev,
958 endpoint->bEndpointAddress),
959 port->bulk_out_buffer, buffer_size,
960 serial->type->write_bulk_callback, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961 }
962
963 if (serial->type->read_int_callback) {
964 for (i = 0; i < num_interrupt_in; ++i) {
965 endpoint = interrupt_in_endpoint[i];
966 port = serial->port[i];
967 port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
968 if (!port->interrupt_in_urb) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100969 dev_err(&interface->dev,
970 "No free urbs available\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971 goto probe_error;
972 }
973 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100974 port->interrupt_in_endpointAddress =
975 endpoint->bEndpointAddress;
976 port->interrupt_in_buffer = kmalloc(buffer_size,
977 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 if (!port->interrupt_in_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100979 dev_err(&interface->dev,
980 "Couldn't allocate interrupt_in_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 goto probe_error;
982 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100983 usb_fill_int_urb(port->interrupt_in_urb, dev,
984 usb_rcvintpipe(dev,
985 endpoint->bEndpointAddress),
986 port->interrupt_in_buffer, buffer_size,
987 serial->type->read_int_callback, port,
988 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 }
990 } else if (num_interrupt_in) {
991 dbg("the device claims to support interrupt in transfers, but read_int_callback is not defined");
992 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100993
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 if (serial->type->write_int_callback) {
995 for (i = 0; i < num_interrupt_out; ++i) {
996 endpoint = interrupt_out_endpoint[i];
997 port = serial->port[i];
998 port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
999 if (!port->interrupt_out_urb) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001000 dev_err(&interface->dev,
1001 "No free urbs available\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 goto probe_error;
1003 }
1004 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
1005 port->interrupt_out_size = buffer_size;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001006 port->interrupt_out_endpointAddress =
1007 endpoint->bEndpointAddress;
1008 port->interrupt_out_buffer = kmalloc(buffer_size,
1009 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010 if (!port->interrupt_out_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001011 dev_err(&interface->dev,
1012 "Couldn't allocate interrupt_out_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 goto probe_error;
1014 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001015 usb_fill_int_urb(port->interrupt_out_urb, dev,
1016 usb_sndintpipe(dev,
1017 endpoint->bEndpointAddress),
1018 port->interrupt_out_buffer, buffer_size,
1019 serial->type->write_int_callback, port,
1020 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 }
1022 } else if (num_interrupt_out) {
1023 dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined");
1024 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001025
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 /* if this device type has an attach function, call it */
1027 if (type->attach) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -07001028 if (!try_module_get(type->driver.owner)) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001029 dev_err(&interface->dev,
1030 "module get failed, exiting\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 goto probe_error;
1032 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001033 retval = type->attach(serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -07001034 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 if (retval < 0)
1036 goto probe_error;
1037 if (retval > 0) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001038 /* quietly accept this device, but don't bind to a
1039 serial port as it's about to disappear */
Alan Stern0a3c8542009-05-27 11:25:52 -04001040 serial->num_ports = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 goto exit;
1042 }
1043 }
1044
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001045 if (get_free_serial(serial, num_ports, &minor) == NULL) {
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001046 dev_err(&interface->dev, "No more free serial devices\n");
1047 goto probe_error;
1048 }
Oliver Neukumc744f992007-02-26 15:43:00 +01001049 serial->minor = minor;
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001050
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 /* register all of the individual ports with the driver core */
1052 for (i = 0; i < num_ports; ++i) {
1053 port = serial->port[i];
1054 port->dev.parent = &interface->dev;
1055 port->dev.driver = NULL;
1056 port->dev.bus = &usb_serial_bus_type;
1057 port->dev.release = &port_release;
1058
Kay Sievers0031a062008-05-02 06:02:41 +02001059 dev_set_name(&port->dev, "ttyUSB%d", port->number);
Kay Sievers7071a3c2008-05-02 06:02:41 +02001060 dbg ("%s - registering %s", __func__, dev_name(&port->dev));
Alan Sternc706ebd2009-06-02 11:54:11 -04001061 port->dev_state = PORT_REGISTERING;
Greg Kroah-Hartman13f4db92006-08-28 11:43:25 -07001062 retval = device_register(&port->dev);
Alan Sternc706ebd2009-06-02 11:54:11 -04001063 if (retval) {
Greg Kroah-Hartman13f4db92006-08-28 11:43:25 -07001064 dev_err(&port->dev, "Error registering port device, "
1065 "continuing\n");
Alan Sternc706ebd2009-06-02 11:54:11 -04001066 port->dev_state = PORT_UNREGISTERED;
1067 } else {
1068 port->dev_state = PORT_REGISTERED;
1069 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 }
1071
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001072 usb_serial_console_init(debug, minor);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073
1074exit:
1075 /* success */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001076 usb_set_intfdata(interface, serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077 return 0;
1078
1079probe_error:
1080 for (i = 0; i < num_bulk_in; ++i) {
1081 port = serial->port[i];
1082 if (!port)
1083 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001084 usb_free_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 kfree(port->bulk_in_buffer);
1086 }
1087 for (i = 0; i < num_bulk_out; ++i) {
1088 port = serial->port[i];
1089 if (!port)
1090 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001091 usb_free_urb(port->write_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 kfree(port->bulk_out_buffer);
1093 }
1094 for (i = 0; i < num_interrupt_in; ++i) {
1095 port = serial->port[i];
1096 if (!port)
1097 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001098 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099 kfree(port->interrupt_in_buffer);
1100 }
1101 for (i = 0; i < num_interrupt_out; ++i) {
1102 port = serial->port[i];
1103 if (!port)
1104 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001105 usb_free_urb(port->interrupt_out_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106 kfree(port->interrupt_out_buffer);
1107 }
1108
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 /* free up any memory that we allocated */
1110 for (i = 0; i < serial->num_port_pointers; ++i)
1111 kfree(serial->port[i]);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001112 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 return -EIO;
1114}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001115EXPORT_SYMBOL_GPL(usb_serial_probe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116
1117void usb_serial_disconnect(struct usb_interface *interface)
1118{
1119 int i;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001120 struct usb_serial *serial = usb_get_intfdata(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 struct device *dev = &interface->dev;
1122 struct usb_serial_port *port;
1123
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +02001124 usb_serial_console_disconnect(serial);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001125 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001127 mutex_lock(&serial->disc_mutex);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001128 usb_set_intfdata(interface, NULL);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001129 /* must set a flag, to signal subdrivers */
1130 serial->disconnected = 1;
Alan Stern2d931482009-04-14 11:31:02 -04001131 mutex_unlock(&serial->disc_mutex);
1132
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001133 for (i = 0; i < serial->num_ports; ++i) {
1134 port = serial->port[i];
1135 if (port) {
Alan Cox4a90f092008-10-13 10:39:46 +01001136 struct tty_struct *tty = tty_port_tty_get(&port->port);
1137 if (tty) {
Alan Cox335f8512009-06-11 12:26:29 +01001138 /* The hangup will occur asynchronously but
1139 the object refcounts will sort out all the
1140 cleanup */
Alan Cox4a90f092008-10-13 10:39:46 +01001141 tty_hangup(tty);
1142 tty_kref_put(tty);
1143 }
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001144 kill_traffic(port);
Alan Stern2d931482009-04-14 11:31:02 -04001145 cancel_work_sync(&port->work);
Alan Sternc706ebd2009-06-02 11:54:11 -04001146 if (port->dev_state == PORT_REGISTERED) {
1147
1148 /* Make sure the port is bound so that the
1149 * driver's port_remove method is called.
1150 */
1151 if (!port->dev.driver) {
1152 int rc;
1153
1154 port->dev.driver =
1155 &serial->type->driver;
1156 rc = device_bind_driver(&port->dev);
1157 }
1158 port->dev_state = PORT_UNREGISTERING;
1159 device_del(&port->dev);
1160 port->dev_state = PORT_UNREGISTERED;
1161 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 }
Alan Sternf9c99bb2009-06-02 11:53:55 -04001164 serial->type->disconnect(serial);
Alan Stern2d931482009-04-14 11:31:02 -04001165
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001166 /* let the last holder of this object
1167 * cause it to be cleaned up */
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001168 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 dev_info(dev, "device disconnected\n");
1170}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001171EXPORT_SYMBOL_GPL(usb_serial_disconnect);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172
Oliver Neukumec225592007-04-27 20:54:57 +02001173int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
1174{
1175 struct usb_serial *serial = usb_get_intfdata(intf);
1176 struct usb_serial_port *port;
1177 int i, r = 0;
1178
Oliver Neukumf8bece82009-02-05 16:54:25 +01001179 serial->suspending = 1;
1180
Oliver Neukume31c1882007-07-23 08:58:39 +02001181 for (i = 0; i < serial->num_ports; ++i) {
1182 port = serial->port[i];
1183 if (port)
1184 kill_traffic(port);
Oliver Neukumec225592007-04-27 20:54:57 +02001185 }
1186
1187 if (serial->type->suspend)
Oliver Neukume31c1882007-07-23 08:58:39 +02001188 r = serial->type->suspend(serial, message);
Oliver Neukumec225592007-04-27 20:54:57 +02001189
1190 return r;
1191}
1192EXPORT_SYMBOL(usb_serial_suspend);
1193
1194int usb_serial_resume(struct usb_interface *intf)
1195{
1196 struct usb_serial *serial = usb_get_intfdata(intf);
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001197 int rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001198
Oliver Neukumf8bece82009-02-05 16:54:25 +01001199 serial->suspending = 0;
Sarah Sharp8abaee22007-10-25 10:58:43 -07001200 if (serial->type->resume)
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001201 rv = serial->type->resume(serial);
1202 else
1203 rv = usb_serial_generic_resume(serial);
Oliver Neukumf8bece82009-02-05 16:54:25 +01001204
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001205 return rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001206}
1207EXPORT_SYMBOL(usb_serial_resume);
1208
Jeff Dikeb68e31d2006-10-02 02:17:18 -07001209static const struct tty_operations serial_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210 .open = serial_open,
1211 .close = serial_close,
1212 .write = serial_write,
Alan Cox335f8512009-06-11 12:26:29 +01001213 .hangup = serial_hangup,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 .write_room = serial_write_room,
1215 .ioctl = serial_ioctl,
1216 .set_termios = serial_set_termios,
1217 .throttle = serial_throttle,
1218 .unthrottle = serial_unthrottle,
1219 .break_ctl = serial_break,
1220 .chars_in_buffer = serial_chars_in_buffer,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 .tiocmget = serial_tiocmget,
1222 .tiocmset = serial_tiocmset,
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -07001223 .proc_fops = &serial_proc_fops,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224};
1225
Alan Cox335f8512009-06-11 12:26:29 +01001226
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227struct tty_driver *usb_serial_tty_driver;
1228
1229static int __init usb_serial_init(void)
1230{
1231 int i;
1232 int result;
1233
1234 usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS);
1235 if (!usb_serial_tty_driver)
1236 return -ENOMEM;
1237
1238 /* Initialize our global data */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001239 for (i = 0; i < SERIAL_TTY_MINORS; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240 serial_table[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241
1242 result = bus_register(&usb_serial_bus_type);
1243 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001244 printk(KERN_ERR "usb-serial: %s - registering bus driver "
1245 "failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246 goto exit_bus;
1247 }
1248
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249 usb_serial_tty_driver->owner = THIS_MODULE;
1250 usb_serial_tty_driver->driver_name = "usbserial";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 usb_serial_tty_driver->name = "ttyUSB";
1252 usb_serial_tty_driver->major = SERIAL_TTY_MAJOR;
1253 usb_serial_tty_driver->minor_start = 0;
1254 usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
1255 usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001256 usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW |
1257 TTY_DRIVER_DYNAMIC_DEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 usb_serial_tty_driver->init_termios = tty_std_termios;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001259 usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD
1260 | HUPCL | CLOCAL;
Alan Coxa5b6f602008-04-08 17:16:06 +01001261 usb_serial_tty_driver->init_termios.c_ispeed = 9600;
1262 usb_serial_tty_driver->init_termios.c_ospeed = 9600;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263 tty_set_operations(usb_serial_tty_driver, &serial_ops);
1264 result = tty_register_driver(usb_serial_tty_driver);
1265 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001266 printk(KERN_ERR "usb-serial: %s - tty_register_driver failed\n",
1267 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 goto exit_reg_driver;
1269 }
1270
1271 /* register the USB driver */
1272 result = usb_register(&usb_serial_driver);
1273 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001274 printk(KERN_ERR "usb-serial: %s - usb_register failed\n",
1275 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 goto exit_tty;
1277 }
1278
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001279 /* register the generic driver, if we should */
1280 result = usb_serial_generic_register(debug);
1281 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001282 printk(KERN_ERR "usb-serial: %s - registering generic "
1283 "driver failed\n", __func__);
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001284 goto exit_generic;
1285 }
1286
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001287 printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288
1289 return result;
1290
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001291exit_generic:
1292 usb_deregister(&usb_serial_driver);
1293
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294exit_tty:
1295 tty_unregister_driver(usb_serial_tty_driver);
1296
1297exit_reg_driver:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298 bus_unregister(&usb_serial_bus_type);
1299
1300exit_bus:
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001301 printk(KERN_ERR "usb-serial: %s - returning with error %d\n",
1302 __func__, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303 put_tty_driver(usb_serial_tty_driver);
1304 return result;
1305}
1306
1307
1308static void __exit usb_serial_exit(void)
1309{
1310 usb_serial_console_exit();
1311
1312 usb_serial_generic_deregister();
1313
1314 usb_deregister(&usb_serial_driver);
1315 tty_unregister_driver(usb_serial_tty_driver);
1316 put_tty_driver(usb_serial_tty_driver);
1317 bus_unregister(&usb_serial_bus_type);
1318}
1319
1320
1321module_init(usb_serial_init);
1322module_exit(usb_serial_exit);
1323
1324#define set_to_generic_if_null(type, function) \
1325 do { \
1326 if (!type->function) { \
1327 type->function = usb_serial_generic_##function; \
1328 dbg("Had to override the " #function \
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001329 " usb serial operation with the generic one.");\
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330 } \
1331 } while (0)
1332
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001333static void fixup_generic(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334{
1335 set_to_generic_if_null(device, open);
1336 set_to_generic_if_null(device, write);
1337 set_to_generic_if_null(device, close);
1338 set_to_generic_if_null(device, write_room);
1339 set_to_generic_if_null(device, chars_in_buffer);
1340 set_to_generic_if_null(device, read_bulk_callback);
1341 set_to_generic_if_null(device, write_bulk_callback);
Alan Sternf9c99bb2009-06-02 11:53:55 -04001342 set_to_generic_if_null(device, disconnect);
1343 set_to_generic_if_null(device, release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344}
1345
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001346int usb_serial_register(struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001348 /* must be called with BKL held */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 int retval;
1350
Dave Younge4abe662009-02-14 21:21:13 +08001351 if (usb_disabled())
1352 return -ENODEV;
1353
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001354 fixup_generic(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001356 if (!driver->description)
1357 driver->description = driver->driver.name;
1358
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 /* Add this device to our list of devices */
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001360 list_add(&driver->driver_list, &usb_serial_driver_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001362 retval = usb_serial_bus_register(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363 if (retval) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001364 printk(KERN_ERR "usb-serial: problem %d when registering "
1365 "driver %s\n", retval, driver->description);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001366 list_del(&driver->driver_list);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001367 } else
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001368 printk(KERN_INFO "USB Serial support registered for %s\n",
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001369 driver->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370
1371 return retval;
1372}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001373EXPORT_SYMBOL_GPL(usb_serial_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374
1375
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001376void usb_serial_deregister(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001378 /* must be called with BKL held */
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001379 printk(KERN_INFO "USB Serial deregistering driver %s\n",
1380 device->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 list_del(&device->driver_list);
1382 usb_serial_bus_deregister(device);
1383}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384EXPORT_SYMBOL_GPL(usb_serial_deregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385
1386/* Module information */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001387MODULE_AUTHOR(DRIVER_AUTHOR);
1388MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389MODULE_LICENSE("GPL");
1390
1391module_param(debug, bool, S_IRUGO | S_IWUSR);
1392MODULE_PARM_DESC(debug, "Debug enabled or not");