blob: a84216464ca01fa60a687974f0324b86bffdc137 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * USB Serial Converter driver
3 *
Greg Kroah-Hartman502b95c2005-06-20 21:15:16 -07004 * Copyright (C) 1999 - 2005 Greg Kroah-Hartman (greg@kroah.com)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 * Copyright (C) 2000 Peter Berger (pberger@brimson.com)
6 * Copyright (C) 2000 Al Borchers (borchers@steinerpoint.com)
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version
10 * 2 as published by the Free Software Foundation.
11 *
Greg Kroah-Hartman502b95c2005-06-20 21:15:16 -070012 * This driver was originally based on the ACM driver by Armin Fuerst (which was
Linus Torvalds1da177e2005-04-16 15:20:36 -070013 * based on a driver by Brad Keryan)
14 *
Alan Coxa8d6f0a2008-07-22 11:12:24 +010015 * See Documentation/usb/usb-serial.txt for more information on using this
16 * driver
Linus Torvalds1da177e2005-04-16 15:20:36 -070017 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 */
19
Linus Torvalds1da177e2005-04-16 15:20:36 -070020#include <linux/kernel.h>
21#include <linux/errno.h>
22#include <linux/init.h>
23#include <linux/slab.h>
24#include <linux/tty.h>
25#include <linux/tty_driver.h>
26#include <linux/tty_flip.h>
27#include <linux/module.h>
28#include <linux/moduleparam.h>
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -070029#include <linux/seq_file.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <linux/spinlock.h>
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -030031#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include <linux/list.h>
Alan Coxa8d6f0a2008-07-22 11:12:24 +010033#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include <linux/usb.h>
Greg Kroah-Hartmana9698882006-07-11 21:22:58 -070035#include <linux/usb/serial.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#include "pl2303.h"
37
38/*
39 * Version Information
40 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/"
42#define DRIVER_DESC "USB Serial Driver core"
43
Pete Zaitcev34f8e762006-06-21 15:00:45 -070044static void port_free(struct usb_serial_port *port);
45
Linus Torvalds1da177e2005-04-16 15:20:36 -070046/* Driver structure we register with the USB core */
47static struct usb_driver usb_serial_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070048 .name = "usbserial",
49 .probe = usb_serial_probe,
50 .disconnect = usb_serial_disconnect,
Oliver Neukumec225592007-04-27 20:54:57 +020051 .suspend = usb_serial_suspend,
52 .resume = usb_serial_resume,
Greg Kroah-Hartmanba9dc652005-11-16 13:41:28 -080053 .no_dynamic_id = 1,
Linus Torvalds1da177e2005-04-16 15:20:36 -070054};
55
56/* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead
57 the MODULE_DEVICE_TABLE declarations in each serial driver
58 cause the "hotplug" program to pull in whatever module is necessary
59 via modprobe, and modprobe will load usbserial because the serial
60 drivers depend on it.
61*/
62
63static int debug;
Alan Coxa8d6f0a2008-07-22 11:12:24 +010064/* initially all NULL */
65static struct usb_serial *serial_table[SERIAL_TTY_MINORS];
Oliver Neukum3ddad822007-07-24 15:13:42 +020066static DEFINE_MUTEX(table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070067static LIST_HEAD(usb_serial_driver_list);
68
69struct usb_serial *usb_serial_get_by_index(unsigned index)
70{
Oliver Neukum34ef50e2007-01-13 07:29:26 +010071 struct usb_serial *serial;
72
Oliver Neukum3ddad822007-07-24 15:13:42 +020073 mutex_lock(&table_lock);
Oliver Neukum34ef50e2007-01-13 07:29:26 +010074 serial = serial_table[index];
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
76 if (serial)
77 kref_get(&serial->kref);
Oliver Neukum3ddad822007-07-24 15:13:42 +020078 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070079 return serial;
80}
81
Alan Coxa8d6f0a2008-07-22 11:12:24 +010082static struct usb_serial *get_free_serial(struct usb_serial *serial,
83 int num_ports, unsigned int *minor)
Linus Torvalds1da177e2005-04-16 15:20:36 -070084{
85 unsigned int i, j;
86 int good_spot;
87
Harvey Harrison441b62c2008-03-03 16:08:34 -080088 dbg("%s %d", __func__, num_ports);
Linus Torvalds1da177e2005-04-16 15:20:36 -070089
90 *minor = 0;
Oliver Neukum3ddad822007-07-24 15:13:42 +020091 mutex_lock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070092 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
93 if (serial_table[i])
94 continue;
95
96 good_spot = 1;
97 for (j = 1; j <= num_ports-1; ++j)
98 if ((i+j >= SERIAL_TTY_MINORS) || (serial_table[i+j])) {
99 good_spot = 0;
100 i += j;
101 break;
102 }
103 if (good_spot == 0)
104 continue;
105
106 *minor = i;
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100107 j = 0;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800108 dbg("%s - minor base = %d", __func__, *minor);
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100109 for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110 serial_table[i] = serial;
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100111 serial->port[j++]->number = i;
112 }
Oliver Neukum3ddad822007-07-24 15:13:42 +0200113 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114 return serial;
115 }
Oliver Neukum3ddad822007-07-24 15:13:42 +0200116 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 return NULL;
118}
119
120static void return_serial(struct usb_serial *serial)
121{
122 int i;
123
Harvey Harrison441b62c2008-03-03 16:08:34 -0800124 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100126 for (i = 0; i < serial->num_ports; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127 serial_table[serial->minor + i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128}
129
130static void destroy_serial(struct kref *kref)
131{
132 struct usb_serial *serial;
133 struct usb_serial_port *port;
134 int i;
135
136 serial = to_usb_serial(kref);
137
Harvey Harrison441b62c2008-03-03 16:08:34 -0800138 dbg("%s - %s", __func__, serial->type->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139
Jim Radford521b85a2007-03-13 08:30:50 -0700140 /* return the minor range that this device had */
Alan Stern0282b7f2008-07-29 12:01:04 -0400141 if (serial->minor != SERIAL_TTY_NO_MINOR)
142 return_serial(serial);
Jim Radford521b85a2007-03-13 08:30:50 -0700143
Alan Sternf9c99bb2009-06-02 11:53:55 -0400144 serial->type->release(serial);
145
146 for (i = 0; i < serial->num_ports; ++i) {
147 port = serial->port[i];
148 if (port)
149 put_device(&port->dev);
150 }
151
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 /* If this is a "fake" port, we have to clean it up here, as it will
153 * not get cleaned up in port_release() as it was never registered with
154 * the driver core */
155 if (serial->num_ports < serial->num_port_pointers) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100156 for (i = serial->num_ports;
157 i < serial->num_port_pointers; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158 port = serial->port[i];
Alan Sternf9c99bb2009-06-02 11:53:55 -0400159 if (port)
160 port_free(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161 }
162 }
163
164 usb_put_dev(serial->dev);
165
166 /* free up any memory that we allocated */
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100167 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168}
169
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200170void usb_serial_put(struct usb_serial *serial)
171{
Oliver Neukum3ddad822007-07-24 15:13:42 +0200172 mutex_lock(&table_lock);
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200173 kref_put(&serial->kref, destroy_serial);
Oliver Neukum3ddad822007-07-24 15:13:42 +0200174 mutex_unlock(&table_lock);
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200175}
176
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177/*****************************************************************************
178 * Driver tty interface functions
179 *****************************************************************************/
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100180static int serial_open (struct tty_struct *tty, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181{
182 struct usb_serial *serial;
183 struct usb_serial_port *port;
184 unsigned int portNumber;
Alan Stern2d931482009-04-14 11:31:02 -0400185 int retval = 0;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100186
Harvey Harrison441b62c2008-03-03 16:08:34 -0800187 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188
189 /* get the serial object associated with this tty pointer */
190 serial = usb_serial_get_by_index(tty->index);
191 if (!serial) {
192 tty->driver_data = NULL;
193 return -ENODEV;
194 }
195
Alan Stern2d931482009-04-14 11:31:02 -0400196 mutex_lock(&serial->disc_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 portNumber = tty->index - serial->minor;
198 port = serial->port[portNumber];
Alan Stern2d931482009-04-14 11:31:02 -0400199 if (!port || serial->disconnected)
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300200 retval = -ENODEV;
Alan Stern2d931482009-04-14 11:31:02 -0400201 else
202 get_device(&port->dev);
203 /*
204 * Note: Our locking order requirement does not allow port->mutex
205 * to be acquired while serial->disc_mutex is held.
206 */
207 mutex_unlock(&serial->disc_mutex);
208 if (retval)
209 goto bailout_serial_put;
James Woodcock331879f2009-02-11 15:06:53 +0000210
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300211 if (mutex_lock_interruptible(&port->mutex)) {
212 retval = -ERESTARTSYS;
Alan Stern2d931482009-04-14 11:31:02 -0400213 goto bailout_port_put;
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300214 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100215
Alan Cox95da3102008-07-22 11:09:07 +0100216 ++port->port.count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217
Paul Fulghumca854852006-04-13 22:28:17 +0200218 /* set up our port structure making the tty driver
219 * remember our port object, and us it */
220 tty->driver_data = port;
Alan Cox4a90f092008-10-13 10:39:46 +0100221 tty_port_tty_set(&port->port, tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222
Alan Cox95da3102008-07-22 11:09:07 +0100223 if (port->port.count == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224
225 /* lock this module before we call it
226 * this may fail, which means we must bail out,
227 * safe because we are called with BKL held */
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700228 if (!try_module_get(serial->type->driver.owner)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229 retval = -ENODEV;
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300230 goto bailout_mutex_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231 }
232
Alan Stern2d931482009-04-14 11:31:02 -0400233 mutex_lock(&serial->disc_mutex);
234 if (serial->disconnected)
235 retval = -ENODEV;
236 else
237 retval = usb_autopm_get_interface(serial->interface);
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800238 if (retval)
239 goto bailout_module_put;
Alan Stern2d931482009-04-14 11:31:02 -0400240
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100241 /* only call the device specific open if this
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242 * is the first time the port is opened */
Alan Cox95da3102008-07-22 11:09:07 +0100243 retval = serial->type->open(tty, port, filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 if (retval)
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800245 goto bailout_interface_put;
Alan Stern2d931482009-04-14 11:31:02 -0400246 mutex_unlock(&serial->disc_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 }
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300248 mutex_unlock(&port->mutex);
Alan Cox335f8512009-06-11 12:26:29 +0100249 /* Now do the correct tty layer semantics */
250 retval = tty_port_block_til_ready(&port->port, tty, filp);
251 if (retval == 0)
252 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253
Sarah Sharpf0fbd5b2007-11-13 17:10:09 -0800254bailout_interface_put:
255 usb_autopm_put_interface(serial->interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256bailout_module_put:
Alan Stern2d931482009-04-14 11:31:02 -0400257 mutex_unlock(&serial->disc_mutex);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700258 module_put(serial->type->driver.owner);
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300259bailout_mutex_unlock:
Alan Cox95da3102008-07-22 11:09:07 +0100260 port->port.count = 0;
Frank Gevaertsb059c812006-06-14 15:52:05 +0200261 tty->driver_data = NULL;
Alan Cox4a90f092008-10-13 10:39:46 +0100262 tty_port_tty_set(&port->port, NULL);
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300263 mutex_unlock(&port->mutex);
Alan Stern2d931482009-04-14 11:31:02 -0400264bailout_port_put:
265 put_device(&port->dev);
266bailout_serial_put:
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200267 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 return retval;
269}
270
Alan Cox335f8512009-06-11 12:26:29 +0100271/**
272 * serial_do_down - shut down hardware
273 * @port: port to shut down
274 *
275 * Shut down a USB port unless it is the console. We never shut down the
276 * console hardware as it will always be in use.
277 *
278 * Don't free any resources at this point
279 */
280static void serial_do_down(struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281{
Alan Cox335f8512009-06-11 12:26:29 +0100282 struct usb_serial_driver *drv = port->serial->type;
Alan Stern2d931482009-04-14 11:31:02 -0400283 struct usb_serial *serial;
284 struct module *owner;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285
Alan Cox335f8512009-06-11 12:26:29 +0100286 /* The console is magical, do not hang up the console hardware
287 or there will be tears */
288 if (port->console)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289 return;
290
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300291 mutex_lock(&port->mutex);
Alan Stern2d931482009-04-14 11:31:02 -0400292 serial = port->serial;
293 owner = serial->type->driver.owner;
Luiz Fernando Capitulino8a4613f2005-11-28 19:16:07 -0200294
Alan Cox335f8512009-06-11 12:26:29 +0100295 if (drv->close)
296 drv->close(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300298 mutex_unlock(&port->mutex);
Alan Cox335f8512009-06-11 12:26:29 +0100299}
300
301/**
302 * serial_do_free - free resources post close/hangup
303 * @port: port to free up
304 *
305 * Do the resource freeing and refcount dropping for the port. We must
306 * be careful about ordering and we must avoid freeing up the console.
307 */
308
309static void serial_do_free(struct usb_serial_port *port)
310{
311 struct usb_serial *serial;
312 struct module *owner;
313
314 /* The console is magical, do not hang up the console hardware
315 or there will be tears */
316 if (port->console)
317 return;
318
319 serial = port->serial;
320 owner = serial->type->driver.owner;
Alan Stern2d931482009-04-14 11:31:02 -0400321 put_device(&port->dev);
Alan Stern2d931482009-04-14 11:31:02 -0400322 /* Mustn't dereference port any more */
Alan Cox335f8512009-06-11 12:26:29 +0100323 mutex_lock(&serial->disc_mutex);
324 if (!serial->disconnected)
325 usb_autopm_put_interface(serial->interface);
326 mutex_unlock(&serial->disc_mutex);
Alan Stern2d931482009-04-14 11:31:02 -0400327 usb_serial_put(serial);
Alan Stern2d931482009-04-14 11:31:02 -0400328 /* Mustn't dereference serial any more */
Alan Cox335f8512009-06-11 12:26:29 +0100329 module_put(owner);
330}
331
332static void serial_close(struct tty_struct *tty, struct file *filp)
333{
334 struct usb_serial_port *port = tty->driver_data;
335
Thadeu Lima de Souza Cascardof4fa4462009-06-25 14:41:37 +0100336 if (!port)
337 return;
338
Alan Cox335f8512009-06-11 12:26:29 +0100339 dbg("%s - port %d", __func__, port->number);
340
341
342 if (tty_port_close_start(&port->port, tty, filp) == 0)
343 return;
344
345 serial_do_down(port);
346 tty_port_close_end(&port->port, tty);
347 tty_port_tty_set(&port->port, NULL);
348 serial_do_free(port);
349}
350
351static void serial_hangup(struct tty_struct *tty)
352{
353 struct usb_serial_port *port = tty->driver_data;
354 serial_do_down(port);
355 tty_port_hangup(&port->port);
356 serial_do_free(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357}
358
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100359static int serial_write(struct tty_struct *tty, const unsigned char *buf,
360 int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200362 struct usb_serial_port *port = tty->driver_data;
Oliver Neukum3ff4fd92007-01-13 07:32:27 +0100363 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364
Alan Coxf34d7a52008-04-30 00:54:13 -0700365 if (port->serial->dev->state == USB_STATE_NOTATTACHED)
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200366 goto exit;
367
Harvey Harrison441b62c2008-03-03 16:08:34 -0800368 dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369
Alan Cox95da3102008-07-22 11:09:07 +0100370 /* count is managed under the mutex lock for the tty so cannot
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100371 drop to zero until after the last close completes */
Alan Cox95da3102008-07-22 11:09:07 +0100372 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373
374 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100375 retval = port->serial->type->write(tty, port, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376
377exit:
378 return retval;
379}
380
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100381static int serial_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200383 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800384 dbg("%s - port %d", __func__, port->number);
Alan Cox95da3102008-07-22 11:09:07 +0100385 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100387 return port->serial->type->write_room(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388}
389
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100390static int serial_chars_in_buffer(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200392 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800393 dbg("%s = port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394
Alan Cox95da3102008-07-22 11:09:07 +0100395 WARN_ON(!port->port.count);
Alan Coxeff69372009-01-02 13:47:06 +0000396 /* if the device was unplugged then any remaining characters
397 fell out of the connector ;) */
398 if (port->serial->disconnected)
399 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100401 return port->serial->type->chars_in_buffer(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402}
403
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100404static void serial_throttle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200406 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800407 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408
Alan Cox95da3102008-07-22 11:09:07 +0100409 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 /* pass on to the driver specific version of this function */
411 if (port->serial->type->throttle)
Alan Cox95da3102008-07-22 11:09:07 +0100412 port->serial->type->throttle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413}
414
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100415static void serial_unthrottle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200417 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800418 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419
Alan Cox95da3102008-07-22 11:09:07 +0100420 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421 /* pass on to the driver specific version of this function */
422 if (port->serial->type->unthrottle)
Alan Cox95da3102008-07-22 11:09:07 +0100423 port->serial->type->unthrottle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424}
425
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100426static int serial_ioctl(struct tty_struct *tty, struct file *file,
427 unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200429 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 int retval = -ENODEV;
431
Harvey Harrison441b62c2008-03-03 16:08:34 -0800432 dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433
Alan Cox95da3102008-07-22 11:09:07 +0100434 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100436 /* pass on to the driver specific version of this function
437 if it is available */
Alan Coxf34d7a52008-04-30 00:54:13 -0700438 if (port->serial->type->ioctl) {
Alan Cox95da3102008-07-22 11:09:07 +0100439 retval = port->serial->type->ioctl(tty, file, cmd, arg);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100440 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 retval = -ENOIOCTLCMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 return retval;
443}
444
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100445static void serial_set_termios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200447 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800448 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449
Alan Cox95da3102008-07-22 11:09:07 +0100450 WARN_ON(!port->port.count);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100451 /* pass on to the driver specific version of this function
452 if it is available */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453 if (port->serial->type->set_termios)
Alan Cox95da3102008-07-22 11:09:07 +0100454 port->serial->type->set_termios(tty, port, old);
Alan Cox33785092007-10-18 01:24:22 -0700455 else
456 tty_termios_copy_hw(tty->termios, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457}
458
Alan Cox9e989662008-07-22 11:18:03 +0100459static int serial_break(struct tty_struct *tty, int break_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200461 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462
Harvey Harrison441b62c2008-03-03 16:08:34 -0800463 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464
Alan Cox95da3102008-07-22 11:09:07 +0100465 WARN_ON(!port->port.count);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100466 /* pass on to the driver specific version of this function
467 if it is available */
Alan Cox6b447f042009-01-02 13:48:56 +0000468 if (port->serial->type->break_ctl)
Alan Cox95da3102008-07-22 11:09:07 +0100469 port->serial->type->break_ctl(tty, break_state);
Alan Cox9e989662008-07-22 11:18:03 +0100470 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471}
472
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700473static int serial_proc_show(struct seq_file *m, void *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474{
475 struct usb_serial *serial;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 char tmp[40];
478
Harvey Harrison441b62c2008-03-03 16:08:34 -0800479 dbg("%s", __func__);
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700480 seq_puts(m, "usbserinfo:1.0 driver:2.0\n");
481 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 serial = usb_serial_get_by_index(i);
483 if (serial == NULL)
484 continue;
485
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700486 seq_printf(m, "%d:", i);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700487 if (serial->type->driver.owner)
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700488 seq_printf(m, " module:%s",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100489 module_name(serial->type->driver.owner));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700490 seq_printf(m, " name:\"%s\"",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100491 serial->type->description);
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700492 seq_printf(m, " vendor:%04x product:%04x",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100493 le16_to_cpu(serial->dev->descriptor.idVendor),
494 le16_to_cpu(serial->dev->descriptor.idProduct));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700495 seq_printf(m, " num_ports:%d", serial->num_ports);
496 seq_printf(m, " port:%d", i - serial->minor + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 usb_make_path(serial->dev, tmp, sizeof(tmp));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700498 seq_printf(m, " path:%s", tmp);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100499
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700500 seq_putc(m, '\n');
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200501 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 }
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700503 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504}
505
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700506static int serial_proc_open(struct inode *inode, struct file *file)
507{
508 return single_open(file, serial_proc_show, NULL);
509}
510
511static const struct file_operations serial_proc_fops = {
512 .owner = THIS_MODULE,
513 .open = serial_proc_open,
514 .read = seq_read,
515 .llseek = seq_lseek,
516 .release = single_release,
517};
518
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100519static int serial_tiocmget(struct tty_struct *tty, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200521 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522
Harvey Harrison441b62c2008-03-03 16:08:34 -0800523 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524
Alan Cox95da3102008-07-22 11:09:07 +0100525 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 if (port->serial->type->tiocmget)
Alan Cox95da3102008-07-22 11:09:07 +0100527 return port->serial->type->tiocmget(tty, file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 return -EINVAL;
529}
530
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100531static int serial_tiocmset(struct tty_struct *tty, struct file *file,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 unsigned int set, unsigned int clear)
533{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200534 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535
Harvey Harrison441b62c2008-03-03 16:08:34 -0800536 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537
Alan Cox95da3102008-07-22 11:09:07 +0100538 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 if (port->serial->type->tiocmset)
Alan Cox95da3102008-07-22 11:09:07 +0100540 return port->serial->type->tiocmset(tty, file, set, clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 return -EINVAL;
542}
543
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700544/*
545 * We would be calling tty_wakeup here, but unfortunately some line
546 * disciplines have an annoying habit of calling tty->write from
547 * the write wakeup callback (e.g. n_hdlc.c).
548 */
549void usb_serial_port_softint(struct usb_serial_port *port)
550{
551 schedule_work(&port->work);
552}
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100553EXPORT_SYMBOL_GPL(usb_serial_port_softint);
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700554
David Howellsc4028952006-11-22 14:57:56 +0000555static void usb_serial_port_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556{
David Howellsc4028952006-11-22 14:57:56 +0000557 struct usb_serial_port *port =
558 container_of(work, struct usb_serial_port, work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 struct tty_struct *tty;
560
Harvey Harrison441b62c2008-03-03 16:08:34 -0800561 dbg("%s - port %d", __func__, port->number);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100562
Alan Cox4a90f092008-10-13 10:39:46 +0100563 tty = tty_port_tty_get(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 if (!tty)
565 return;
566
567 tty_wakeup(tty);
Alan Cox4a90f092008-10-13 10:39:46 +0100568 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569}
570
571static void port_release(struct device *dev)
572{
573 struct usb_serial_port *port = to_usb_serial_port(dev);
574
Kay Sievers7071a3c2008-05-02 06:02:41 +0200575 dbg ("%s - %s", __func__, dev_name(dev));
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700576 port_free(port);
577}
578
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100579static void kill_traffic(struct usb_serial_port *port)
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700580{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582 usb_kill_urb(port->write_urb);
Oliver Neukum5adceac2007-08-17 14:01:38 +0200583 /*
584 * This is tricky.
585 * Some drivers submit the read_urb in the
586 * handler for the write_urb or vice versa
587 * this order determines the order in which
588 * usb_kill_urb() must be used to reliably
589 * kill the URBs. As it is unknown here,
590 * both orders must be used in turn.
591 * The call below is not redundant.
592 */
593 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 usb_kill_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 usb_kill_urb(port->interrupt_out_urb);
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100596}
597
598static void port_free(struct usb_serial_port *port)
599{
Alan Stern2d931482009-04-14 11:31:02 -0400600 /*
601 * Stop all the traffic before cancelling the work, so that
602 * nobody will restart it by calling usb_serial_port_softint.
603 */
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100604 kill_traffic(port);
Alan Stern2d931482009-04-14 11:31:02 -0400605 cancel_work_sync(&port->work);
606
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100607 usb_free_urb(port->read_urb);
608 usb_free_urb(port->write_urb);
609 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610 usb_free_urb(port->interrupt_out_urb);
611 kfree(port->bulk_in_buffer);
612 kfree(port->bulk_out_buffer);
613 kfree(port->interrupt_in_buffer);
614 kfree(port->interrupt_out_buffer);
615 kfree(port);
616}
617
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100618static struct usb_serial *create_serial(struct usb_device *dev,
619 struct usb_interface *interface,
620 struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621{
622 struct usb_serial *serial;
623
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100624 serial = kzalloc(sizeof(*serial), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 if (!serial) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800626 dev_err(&dev->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627 return NULL;
628 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629 serial->dev = usb_get_dev(dev);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700630 serial->type = driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 serial->interface = interface;
632 kref_init(&serial->kref);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +0100633 mutex_init(&serial->disc_mutex);
Alan Stern0282b7f2008-07-29 12:01:04 -0400634 serial->minor = SERIAL_TTY_NO_MINOR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635
636 return serial;
637}
638
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100639static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf,
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100640 struct usb_serial_driver *drv)
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100641{
642 struct usb_dynid *dynid;
643
644 spin_lock(&drv->dynids.lock);
645 list_for_each_entry(dynid, &drv->dynids.list, node) {
646 if (usb_match_one_id(intf, &dynid->id)) {
647 spin_unlock(&drv->dynids.lock);
648 return &dynid->id;
649 }
650 }
651 spin_unlock(&drv->dynids.lock);
652 return NULL;
653}
654
655static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv,
656 struct usb_interface *intf)
657{
658 const struct usb_device_id *id;
659
660 id = usb_match_id(intf, drv->id_table);
661 if (id) {
662 dbg("static descriptor matches");
663 goto exit;
664 }
665 id = match_dynamic_id(intf, drv);
666 if (id)
667 dbg("dynamic descriptor matches");
668exit:
669 return id;
670}
671
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100672static struct usb_serial_driver *search_serial_device(
673 struct usb_interface *iface)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675 const struct usb_device_id *id;
Alan Stern063a2da2007-10-10 16:24:06 -0400676 struct usb_serial_driver *drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677
Adrian Bunk93b1fae2006-01-10 00:13:33 +0100678 /* Check if the usb id matches a known device */
Alan Stern063a2da2007-10-10 16:24:06 -0400679 list_for_each_entry(drv, &usb_serial_driver_list, driver_list) {
680 id = get_iface_id(drv, iface);
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100681 if (id)
Alan Stern063a2da2007-10-10 16:24:06 -0400682 return drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683 }
684
685 return NULL;
686}
687
Alan Cox335f8512009-06-11 12:26:29 +0100688static int serial_carrier_raised(struct tty_port *port)
689{
690 struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
691 struct usb_serial_driver *drv = p->serial->type;
692 if (drv->carrier_raised)
693 return drv->carrier_raised(p);
694 /* No carrier control - don't block */
695 return 1;
696}
697
698static void serial_dtr_rts(struct tty_port *port, int on)
699{
700 struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
701 struct usb_serial_driver *drv = p->serial->type;
702 if (drv->dtr_rts)
703 drv->dtr_rts(p, on);
704}
705
706static const struct tty_port_operations serial_port_ops = {
707 .carrier_raised = serial_carrier_raised,
708 .dtr_rts = serial_dtr_rts,
709};
710
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711int usb_serial_probe(struct usb_interface *interface,
712 const struct usb_device_id *id)
713{
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100714 struct usb_device *dev = interface_to_usbdev(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715 struct usb_serial *serial = NULL;
716 struct usb_serial_port *port;
717 struct usb_host_interface *iface_desc;
718 struct usb_endpoint_descriptor *endpoint;
719 struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS];
720 struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS];
721 struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];
722 struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700723 struct usb_serial_driver *type = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 int retval;
Andre Hauptdd9ca5d2008-06-18 15:56:00 +0200725 unsigned int minor;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726 int buffer_size;
727 int i;
728 int num_interrupt_in = 0;
729 int num_interrupt_out = 0;
730 int num_bulk_in = 0;
731 int num_bulk_out = 0;
732 int num_ports = 0;
733 int max_endpoints;
734
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100735 lock_kernel(); /* guard against unloading a serial driver module */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 type = search_serial_device(interface);
737 if (!type) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100738 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 dbg("none matched");
740 return -ENODEV;
741 }
742
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100743 serial = create_serial(dev, interface, type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 if (!serial) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100745 unlock_kernel();
Harvey Harrison441b62c2008-03-03 16:08:34 -0800746 dev_err(&interface->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747 return -ENOMEM;
748 }
749
750 /* if this device type has a probe function, call it */
751 if (type->probe) {
752 const struct usb_device_id *id;
753
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700754 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100755 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100756 dev_err(&interface->dev,
757 "module get failed, exiting\n");
758 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 return -EIO;
760 }
761
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100762 id = get_iface_id(type, interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 retval = type->probe(serial, id);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700764 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765
766 if (retval) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100767 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100768 dbg("sub driver rejected device");
769 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 return retval;
771 }
772 }
773
774 /* descriptor matches, let's find the endpoints needed */
775 /* check out the endpoints */
776 iface_desc = interface->cur_altsetting;
777 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
778 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700779
780 if (usb_endpoint_is_bulk_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 /* we found a bulk in endpoint */
782 dbg("found bulk in on endpoint %d", i);
783 bulk_in_endpoint[num_bulk_in] = endpoint;
784 ++num_bulk_in;
785 }
786
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700787 if (usb_endpoint_is_bulk_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 /* we found a bulk out endpoint */
789 dbg("found bulk out on endpoint %d", i);
790 bulk_out_endpoint[num_bulk_out] = endpoint;
791 ++num_bulk_out;
792 }
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700793
794 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 /* we found a interrupt in endpoint */
796 dbg("found interrupt in on endpoint %d", i);
797 interrupt_in_endpoint[num_interrupt_in] = endpoint;
798 ++num_interrupt_in;
799 }
800
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700801 if (usb_endpoint_is_int_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802 /* we found an interrupt out endpoint */
803 dbg("found interrupt out on endpoint %d", i);
804 interrupt_out_endpoint[num_interrupt_out] = endpoint;
805 ++num_interrupt_out;
806 }
807 }
808
809#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100810 /* BEGIN HORRIBLE HACK FOR PL2303 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 /* this is needed due to the looney way its endpoints are set up */
812 if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&
813 (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||
814 ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) &&
Johannes Steingraeber8fd80132006-09-16 16:17:34 +0200815 (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) ||
816 ((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) &&
Andreas Bombece816cf2008-09-14 01:58:55 +0200817 (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID)) ||
818 ((le16_to_cpu(dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) &&
819 (le16_to_cpu(dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_EF81))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820 if (interface != dev->actconfig->interface[0]) {
821 /* check out the endpoints of the other interface*/
822 iface_desc = dev->actconfig->interface[0]->cur_altsetting;
823 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
824 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700825 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826 /* we found a interrupt in endpoint */
827 dbg("found interrupt in for Prolific device on separate interface");
828 interrupt_in_endpoint[num_interrupt_in] = endpoint;
829 ++num_interrupt_in;
830 }
831 }
832 }
833
834 /* Now make sure the PL-2303 is configured correctly.
835 * If not, give up now and hope this hack will work
836 * properly during a later invocation of usb_serial_probe
837 */
838 if (num_bulk_in == 0 || num_bulk_out == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100839 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100841 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 return -ENODEV;
843 }
844 }
845 /* END HORRIBLE HACK FOR PL2303 */
846#endif
847
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848#ifdef CONFIG_USB_SERIAL_GENERIC
849 if (type == &usb_serial_generic_device) {
850 num_ports = num_bulk_out;
851 if (num_ports == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100852 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100853 dev_err(&interface->dev,
854 "Generic device with no bulk out, not allowed.\n");
855 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 return -EIO;
857 }
858 }
859#endif
860 if (!num_ports) {
861 /* if this device type has a calc_num_ports function, call it */
862 if (type->calc_num_ports) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700863 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100864 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100865 dev_err(&interface->dev,
866 "module get failed, exiting\n");
867 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 return -EIO;
869 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100870 num_ports = type->calc_num_ports(serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700871 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 }
873 if (!num_ports)
874 num_ports = type->num_ports;
875 }
876
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 serial->num_ports = num_ports;
878 serial->num_bulk_in = num_bulk_in;
879 serial->num_bulk_out = num_bulk_out;
880 serial->num_interrupt_in = num_interrupt_in;
881 serial->num_interrupt_out = num_interrupt_out;
882
Alan Stern063a2da2007-10-10 16:24:06 -0400883 /* found all that we need */
884 dev_info(&interface->dev, "%s converter detected\n",
885 type->description);
886
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887 /* create our ports, we need as many as the max endpoints */
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100888 /* we don't use num_ports here because some devices have more
889 endpoint pairs than ports */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 max_endpoints = max(num_bulk_in, num_bulk_out);
891 max_endpoints = max(max_endpoints, num_interrupt_in);
892 max_endpoints = max(max_endpoints, num_interrupt_out);
893 max_endpoints = max(max_endpoints, (int)serial->num_ports);
894 serial->num_port_pointers = max_endpoints;
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100895 unlock_kernel();
896
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100897 dbg("%s - setting up %d port structures for this device",
898 __func__, max_endpoints);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 for (i = 0; i < max_endpoints; ++i) {
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100900 port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 if (!port)
902 goto probe_error;
Alan Cox4a90f092008-10-13 10:39:46 +0100903 tty_port_init(&port->port);
Alan Cox335f8512009-06-11 12:26:29 +0100904 port->port.ops = &serial_port_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 port->serial = serial;
Greg Kroah-Hartman507ca9b2005-04-23 12:49:16 -0700906 spin_lock_init(&port->lock);
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300907 mutex_init(&port->mutex);
David Howellsc4028952006-11-22 14:57:56 +0000908 INIT_WORK(&port->work, usb_serial_port_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 serial->port[i] = port;
910 }
911
912 /* set up the endpoint information */
913 for (i = 0; i < num_bulk_in; ++i) {
914 endpoint = bulk_in_endpoint[i];
915 port = serial->port[i];
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100916 port->read_urb = usb_alloc_urb(0, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 if (!port->read_urb) {
918 dev_err(&interface->dev, "No free urbs available\n");
919 goto probe_error;
920 }
921 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
922 port->bulk_in_size = buffer_size;
923 port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100924 port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 if (!port->bulk_in_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100926 dev_err(&interface->dev,
927 "Couldn't allocate bulk_in_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 goto probe_error;
929 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100930 usb_fill_bulk_urb(port->read_urb, dev,
931 usb_rcvbulkpipe(dev,
932 endpoint->bEndpointAddress),
933 port->bulk_in_buffer, buffer_size,
934 serial->type->read_bulk_callback, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 }
936
937 for (i = 0; i < num_bulk_out; ++i) {
938 endpoint = bulk_out_endpoint[i];
939 port = serial->port[i];
940 port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
941 if (!port->write_urb) {
942 dev_err(&interface->dev, "No free urbs available\n");
943 goto probe_error;
944 }
945 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
946 port->bulk_out_size = buffer_size;
947 port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100948 port->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 if (!port->bulk_out_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100950 dev_err(&interface->dev,
951 "Couldn't allocate bulk_out_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952 goto probe_error;
953 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100954 usb_fill_bulk_urb(port->write_urb, dev,
955 usb_sndbulkpipe(dev,
956 endpoint->bEndpointAddress),
957 port->bulk_out_buffer, buffer_size,
958 serial->type->write_bulk_callback, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959 }
960
961 if (serial->type->read_int_callback) {
962 for (i = 0; i < num_interrupt_in; ++i) {
963 endpoint = interrupt_in_endpoint[i];
964 port = serial->port[i];
965 port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
966 if (!port->interrupt_in_urb) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100967 dev_err(&interface->dev,
968 "No free urbs available\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969 goto probe_error;
970 }
971 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100972 port->interrupt_in_endpointAddress =
973 endpoint->bEndpointAddress;
974 port->interrupt_in_buffer = kmalloc(buffer_size,
975 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976 if (!port->interrupt_in_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100977 dev_err(&interface->dev,
978 "Couldn't allocate interrupt_in_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979 goto probe_error;
980 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100981 usb_fill_int_urb(port->interrupt_in_urb, dev,
982 usb_rcvintpipe(dev,
983 endpoint->bEndpointAddress),
984 port->interrupt_in_buffer, buffer_size,
985 serial->type->read_int_callback, port,
986 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 }
988 } else if (num_interrupt_in) {
989 dbg("the device claims to support interrupt in transfers, but read_int_callback is not defined");
990 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100991
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 if (serial->type->write_int_callback) {
993 for (i = 0; i < num_interrupt_out; ++i) {
994 endpoint = interrupt_out_endpoint[i];
995 port = serial->port[i];
996 port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
997 if (!port->interrupt_out_urb) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100998 dev_err(&interface->dev,
999 "No free urbs available\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 goto probe_error;
1001 }
1002 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
1003 port->interrupt_out_size = buffer_size;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001004 port->interrupt_out_endpointAddress =
1005 endpoint->bEndpointAddress;
1006 port->interrupt_out_buffer = kmalloc(buffer_size,
1007 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 if (!port->interrupt_out_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001009 dev_err(&interface->dev,
1010 "Couldn't allocate interrupt_out_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 goto probe_error;
1012 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001013 usb_fill_int_urb(port->interrupt_out_urb, dev,
1014 usb_sndintpipe(dev,
1015 endpoint->bEndpointAddress),
1016 port->interrupt_out_buffer, buffer_size,
1017 serial->type->write_int_callback, port,
1018 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 }
1020 } else if (num_interrupt_out) {
1021 dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined");
1022 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001023
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 /* if this device type has an attach function, call it */
1025 if (type->attach) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -07001026 if (!try_module_get(type->driver.owner)) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001027 dev_err(&interface->dev,
1028 "module get failed, exiting\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 goto probe_error;
1030 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001031 retval = type->attach(serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -07001032 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 if (retval < 0)
1034 goto probe_error;
1035 if (retval > 0) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001036 /* quietly accept this device, but don't bind to a
1037 serial port as it's about to disappear */
Alan Stern0a3c8542009-05-27 11:25:52 -04001038 serial->num_ports = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 goto exit;
1040 }
1041 }
1042
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001043 if (get_free_serial(serial, num_ports, &minor) == NULL) {
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001044 dev_err(&interface->dev, "No more free serial devices\n");
1045 goto probe_error;
1046 }
Oliver Neukumc744f992007-02-26 15:43:00 +01001047 serial->minor = minor;
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001048
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 /* register all of the individual ports with the driver core */
1050 for (i = 0; i < num_ports; ++i) {
1051 port = serial->port[i];
1052 port->dev.parent = &interface->dev;
1053 port->dev.driver = NULL;
1054 port->dev.bus = &usb_serial_bus_type;
1055 port->dev.release = &port_release;
1056
Kay Sievers0031a062008-05-02 06:02:41 +02001057 dev_set_name(&port->dev, "ttyUSB%d", port->number);
Kay Sievers7071a3c2008-05-02 06:02:41 +02001058 dbg ("%s - registering %s", __func__, dev_name(&port->dev));
Alan Sternc706ebd2009-06-02 11:54:11 -04001059 port->dev_state = PORT_REGISTERING;
Greg Kroah-Hartman13f4db92006-08-28 11:43:25 -07001060 retval = device_register(&port->dev);
Alan Sternc706ebd2009-06-02 11:54:11 -04001061 if (retval) {
Greg Kroah-Hartman13f4db92006-08-28 11:43:25 -07001062 dev_err(&port->dev, "Error registering port device, "
1063 "continuing\n");
Alan Sternc706ebd2009-06-02 11:54:11 -04001064 port->dev_state = PORT_UNREGISTERED;
1065 } else {
1066 port->dev_state = PORT_REGISTERED;
1067 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 }
1069
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001070 usb_serial_console_init(debug, minor);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071
1072exit:
1073 /* success */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001074 usb_set_intfdata(interface, serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075 return 0;
1076
1077probe_error:
1078 for (i = 0; i < num_bulk_in; ++i) {
1079 port = serial->port[i];
1080 if (!port)
1081 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001082 usb_free_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 kfree(port->bulk_in_buffer);
1084 }
1085 for (i = 0; i < num_bulk_out; ++i) {
1086 port = serial->port[i];
1087 if (!port)
1088 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001089 usb_free_urb(port->write_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 kfree(port->bulk_out_buffer);
1091 }
1092 for (i = 0; i < num_interrupt_in; ++i) {
1093 port = serial->port[i];
1094 if (!port)
1095 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001096 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 kfree(port->interrupt_in_buffer);
1098 }
1099 for (i = 0; i < num_interrupt_out; ++i) {
1100 port = serial->port[i];
1101 if (!port)
1102 continue;
Mariusz Kozlowski95d43162006-11-08 15:36:51 +01001103 usb_free_urb(port->interrupt_out_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 kfree(port->interrupt_out_buffer);
1105 }
1106
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 /* free up any memory that we allocated */
1108 for (i = 0; i < serial->num_port_pointers; ++i)
1109 kfree(serial->port[i]);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001110 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 return -EIO;
1112}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001113EXPORT_SYMBOL_GPL(usb_serial_probe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114
1115void usb_serial_disconnect(struct usb_interface *interface)
1116{
1117 int i;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001118 struct usb_serial *serial = usb_get_intfdata(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 struct device *dev = &interface->dev;
1120 struct usb_serial_port *port;
1121
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +02001122 usb_serial_console_disconnect(serial);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001123 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001125 mutex_lock(&serial->disc_mutex);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001126 usb_set_intfdata(interface, NULL);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001127 /* must set a flag, to signal subdrivers */
1128 serial->disconnected = 1;
Alan Stern2d931482009-04-14 11:31:02 -04001129 mutex_unlock(&serial->disc_mutex);
1130
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001131 for (i = 0; i < serial->num_ports; ++i) {
1132 port = serial->port[i];
1133 if (port) {
Alan Cox4a90f092008-10-13 10:39:46 +01001134 struct tty_struct *tty = tty_port_tty_get(&port->port);
1135 if (tty) {
Alan Cox335f8512009-06-11 12:26:29 +01001136 /* The hangup will occur asynchronously but
1137 the object refcounts will sort out all the
1138 cleanup */
Alan Cox4a90f092008-10-13 10:39:46 +01001139 tty_hangup(tty);
1140 tty_kref_put(tty);
1141 }
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001142 kill_traffic(port);
Alan Stern2d931482009-04-14 11:31:02 -04001143 cancel_work_sync(&port->work);
Alan Sternc706ebd2009-06-02 11:54:11 -04001144 if (port->dev_state == PORT_REGISTERED) {
1145
1146 /* Make sure the port is bound so that the
1147 * driver's port_remove method is called.
1148 */
1149 if (!port->dev.driver) {
1150 int rc;
1151
1152 port->dev.driver =
1153 &serial->type->driver;
1154 rc = device_bind_driver(&port->dev);
1155 }
1156 port->dev_state = PORT_UNREGISTERING;
1157 device_del(&port->dev);
1158 port->dev_state = PORT_UNREGISTERED;
1159 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 }
Alan Sternf9c99bb2009-06-02 11:53:55 -04001162 serial->type->disconnect(serial);
Alan Stern2d931482009-04-14 11:31:02 -04001163
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001164 /* let the last holder of this object
1165 * cause it to be cleaned up */
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001166 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167 dev_info(dev, "device disconnected\n");
1168}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001169EXPORT_SYMBOL_GPL(usb_serial_disconnect);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170
Oliver Neukumec225592007-04-27 20:54:57 +02001171int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
1172{
1173 struct usb_serial *serial = usb_get_intfdata(intf);
1174 struct usb_serial_port *port;
1175 int i, r = 0;
1176
Oliver Neukumf8bece82009-02-05 16:54:25 +01001177 serial->suspending = 1;
1178
Oliver Neukume31c1882007-07-23 08:58:39 +02001179 for (i = 0; i < serial->num_ports; ++i) {
1180 port = serial->port[i];
1181 if (port)
1182 kill_traffic(port);
Oliver Neukumec225592007-04-27 20:54:57 +02001183 }
1184
1185 if (serial->type->suspend)
Oliver Neukume31c1882007-07-23 08:58:39 +02001186 r = serial->type->suspend(serial, message);
Oliver Neukumec225592007-04-27 20:54:57 +02001187
1188 return r;
1189}
1190EXPORT_SYMBOL(usb_serial_suspend);
1191
1192int usb_serial_resume(struct usb_interface *intf)
1193{
1194 struct usb_serial *serial = usb_get_intfdata(intf);
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001195 int rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001196
Oliver Neukumf8bece82009-02-05 16:54:25 +01001197 serial->suspending = 0;
Sarah Sharp8abaee22007-10-25 10:58:43 -07001198 if (serial->type->resume)
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001199 rv = serial->type->resume(serial);
1200 else
1201 rv = usb_serial_generic_resume(serial);
Oliver Neukumf8bece82009-02-05 16:54:25 +01001202
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001203 return rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001204}
1205EXPORT_SYMBOL(usb_serial_resume);
1206
Jeff Dikeb68e31d2006-10-02 02:17:18 -07001207static const struct tty_operations serial_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 .open = serial_open,
1209 .close = serial_close,
1210 .write = serial_write,
Alan Cox335f8512009-06-11 12:26:29 +01001211 .hangup = serial_hangup,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 .write_room = serial_write_room,
1213 .ioctl = serial_ioctl,
1214 .set_termios = serial_set_termios,
1215 .throttle = serial_throttle,
1216 .unthrottle = serial_unthrottle,
1217 .break_ctl = serial_break,
1218 .chars_in_buffer = serial_chars_in_buffer,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 .tiocmget = serial_tiocmget,
1220 .tiocmset = serial_tiocmset,
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -07001221 .proc_fops = &serial_proc_fops,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222};
1223
Alan Cox335f8512009-06-11 12:26:29 +01001224
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225struct tty_driver *usb_serial_tty_driver;
1226
1227static int __init usb_serial_init(void)
1228{
1229 int i;
1230 int result;
1231
1232 usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS);
1233 if (!usb_serial_tty_driver)
1234 return -ENOMEM;
1235
1236 /* Initialize our global data */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001237 for (i = 0; i < SERIAL_TTY_MINORS; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 serial_table[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239
1240 result = bus_register(&usb_serial_bus_type);
1241 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001242 printk(KERN_ERR "usb-serial: %s - registering bus driver "
1243 "failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 goto exit_bus;
1245 }
1246
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247 usb_serial_tty_driver->owner = THIS_MODULE;
1248 usb_serial_tty_driver->driver_name = "usbserial";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249 usb_serial_tty_driver->name = "ttyUSB";
1250 usb_serial_tty_driver->major = SERIAL_TTY_MAJOR;
1251 usb_serial_tty_driver->minor_start = 0;
1252 usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
1253 usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001254 usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW |
1255 TTY_DRIVER_DYNAMIC_DEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 usb_serial_tty_driver->init_termios = tty_std_termios;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001257 usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD
1258 | HUPCL | CLOCAL;
Alan Coxa5b6f602008-04-08 17:16:06 +01001259 usb_serial_tty_driver->init_termios.c_ispeed = 9600;
1260 usb_serial_tty_driver->init_termios.c_ospeed = 9600;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261 tty_set_operations(usb_serial_tty_driver, &serial_ops);
1262 result = tty_register_driver(usb_serial_tty_driver);
1263 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001264 printk(KERN_ERR "usb-serial: %s - tty_register_driver failed\n",
1265 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 goto exit_reg_driver;
1267 }
1268
1269 /* register the USB driver */
1270 result = usb_register(&usb_serial_driver);
1271 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001272 printk(KERN_ERR "usb-serial: %s - usb_register failed\n",
1273 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274 goto exit_tty;
1275 }
1276
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001277 /* register the generic driver, if we should */
1278 result = usb_serial_generic_register(debug);
1279 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001280 printk(KERN_ERR "usb-serial: %s - registering generic "
1281 "driver failed\n", __func__);
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001282 goto exit_generic;
1283 }
1284
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001285 printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286
1287 return result;
1288
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001289exit_generic:
1290 usb_deregister(&usb_serial_driver);
1291
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292exit_tty:
1293 tty_unregister_driver(usb_serial_tty_driver);
1294
1295exit_reg_driver:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 bus_unregister(&usb_serial_bus_type);
1297
1298exit_bus:
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001299 printk(KERN_ERR "usb-serial: %s - returning with error %d\n",
1300 __func__, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 put_tty_driver(usb_serial_tty_driver);
1302 return result;
1303}
1304
1305
1306static void __exit usb_serial_exit(void)
1307{
1308 usb_serial_console_exit();
1309
1310 usb_serial_generic_deregister();
1311
1312 usb_deregister(&usb_serial_driver);
1313 tty_unregister_driver(usb_serial_tty_driver);
1314 put_tty_driver(usb_serial_tty_driver);
1315 bus_unregister(&usb_serial_bus_type);
1316}
1317
1318
1319module_init(usb_serial_init);
1320module_exit(usb_serial_exit);
1321
1322#define set_to_generic_if_null(type, function) \
1323 do { \
1324 if (!type->function) { \
1325 type->function = usb_serial_generic_##function; \
1326 dbg("Had to override the " #function \
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001327 " usb serial operation with the generic one.");\
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328 } \
1329 } while (0)
1330
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001331static void fixup_generic(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332{
1333 set_to_generic_if_null(device, open);
1334 set_to_generic_if_null(device, write);
1335 set_to_generic_if_null(device, close);
1336 set_to_generic_if_null(device, write_room);
1337 set_to_generic_if_null(device, chars_in_buffer);
1338 set_to_generic_if_null(device, read_bulk_callback);
1339 set_to_generic_if_null(device, write_bulk_callback);
Alan Sternf9c99bb2009-06-02 11:53:55 -04001340 set_to_generic_if_null(device, disconnect);
1341 set_to_generic_if_null(device, release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342}
1343
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001344int usb_serial_register(struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001346 /* must be called with BKL held */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 int retval;
1348
Dave Younge4abe662009-02-14 21:21:13 +08001349 if (usb_disabled())
1350 return -ENODEV;
1351
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001352 fixup_generic(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001354 if (!driver->description)
1355 driver->description = driver->driver.name;
1356
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357 /* Add this device to our list of devices */
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001358 list_add(&driver->driver_list, &usb_serial_driver_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001360 retval = usb_serial_bus_register(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 if (retval) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001362 printk(KERN_ERR "usb-serial: problem %d when registering "
1363 "driver %s\n", retval, driver->description);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001364 list_del(&driver->driver_list);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001365 } else
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001366 printk(KERN_INFO "USB Serial support registered for %s\n",
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001367 driver->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368
1369 return retval;
1370}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001371EXPORT_SYMBOL_GPL(usb_serial_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372
1373
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001374void usb_serial_deregister(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001376 /* must be called with BKL held */
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001377 printk(KERN_INFO "USB Serial deregistering driver %s\n",
1378 device->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379 list_del(&device->driver_list);
1380 usb_serial_bus_deregister(device);
1381}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382EXPORT_SYMBOL_GPL(usb_serial_deregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383
1384/* Module information */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001385MODULE_AUTHOR(DRIVER_AUTHOR);
1386MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387MODULE_LICENSE("GPL");
1388
1389module_param(debug, bool, S_IRUGO | S_IWUSR);
1390MODULE_PARM_DESC(debug, "Debug enabled or not");