blob: 28125de7d9022422c4f919159ff463382a415ee7 [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>
Alan Coxc56d3002009-07-28 00:34:58 +010035#include <linux/serial.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#include <linux/usb.h>
Greg Kroah-Hartmana9698882006-07-11 21:22:58 -070037#include <linux/usb/serial.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070038#include "pl2303.h"
39
40/*
41 * Version Information
42 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/"
44#define DRIVER_DESC "USB Serial Driver core"
45
46/* 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
Alan Stern8bc2c1b2009-09-01 11:38:59 -040069/*
70 * Look up the serial structure. If it is found and it hasn't been
71 * disconnected, return with its disc_mutex held and its refcount
72 * incremented. Otherwise return NULL.
73 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070074struct usb_serial *usb_serial_get_by_index(unsigned index)
75{
Oliver Neukum34ef50e2007-01-13 07:29:26 +010076 struct usb_serial *serial;
77
Oliver Neukum3ddad822007-07-24 15:13:42 +020078 mutex_lock(&table_lock);
Oliver Neukum34ef50e2007-01-13 07:29:26 +010079 serial = serial_table[index];
Linus Torvalds1da177e2005-04-16 15:20:36 -070080
Alan Stern8bc2c1b2009-09-01 11:38:59 -040081 if (serial) {
82 mutex_lock(&serial->disc_mutex);
83 if (serial->disconnected) {
84 mutex_unlock(&serial->disc_mutex);
85 serial = NULL;
86 } else {
87 kref_get(&serial->kref);
88 }
89 }
Oliver Neukum3ddad822007-07-24 15:13:42 +020090 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070091 return serial;
92}
93
Alan Coxa8d6f0a2008-07-22 11:12:24 +010094static struct usb_serial *get_free_serial(struct usb_serial *serial,
95 int num_ports, unsigned int *minor)
Linus Torvalds1da177e2005-04-16 15:20:36 -070096{
97 unsigned int i, j;
98 int good_spot;
99
Harvey Harrison441b62c2008-03-03 16:08:34 -0800100 dbg("%s %d", __func__, num_ports);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101
102 *minor = 0;
Oliver Neukum3ddad822007-07-24 15:13:42 +0200103 mutex_lock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
105 if (serial_table[i])
106 continue;
107
108 good_spot = 1;
109 for (j = 1; j <= num_ports-1; ++j)
110 if ((i+j >= SERIAL_TTY_MINORS) || (serial_table[i+j])) {
111 good_spot = 0;
112 i += j;
113 break;
114 }
115 if (good_spot == 0)
116 continue;
117
118 *minor = i;
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100119 j = 0;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800120 dbg("%s - minor base = %d", __func__, *minor);
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100121 for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122 serial_table[i] = serial;
Oliver Neukuma1f721c2007-03-05 15:23:51 +0100123 serial->port[j++]->number = i;
124 }
Oliver Neukum3ddad822007-07-24 15:13:42 +0200125 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126 return serial;
127 }
Oliver Neukum3ddad822007-07-24 15:13:42 +0200128 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129 return NULL;
130}
131
132static void return_serial(struct usb_serial *serial)
133{
134 int i;
135
Harvey Harrison441b62c2008-03-03 16:08:34 -0800136 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137
Alan Stern8bc2c1b2009-09-01 11:38:59 -0400138 mutex_lock(&table_lock);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100139 for (i = 0; i < serial->num_ports; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140 serial_table[serial->minor + i] = NULL;
Alan Stern8bc2c1b2009-09-01 11:38:59 -0400141 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142}
143
144static void destroy_serial(struct kref *kref)
145{
146 struct usb_serial *serial;
147 struct usb_serial_port *port;
148 int i;
149
150 serial = to_usb_serial(kref);
151
Harvey Harrison441b62c2008-03-03 16:08:34 -0800152 dbg("%s - %s", __func__, serial->type->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153
Jim Radford521b85a2007-03-13 08:30:50 -0700154 /* return the minor range that this device had */
Alan Stern0282b7f2008-07-29 12:01:04 -0400155 if (serial->minor != SERIAL_TTY_NO_MINOR)
156 return_serial(serial);
Jim Radford521b85a2007-03-13 08:30:50 -0700157
Alan Sternf9c99bb2009-06-02 11:53:55 -0400158 serial->type->release(serial);
159
Alan Stern41bd34d2009-09-01 11:38:34 -0400160 /* Now that nothing is using the ports, they can be freed */
161 for (i = 0; i < serial->num_port_pointers; ++i) {
Alan Sternf9c99bb2009-06-02 11:53:55 -0400162 port = serial->port[i];
Alan Stern41bd34d2009-09-01 11:38:34 -0400163 if (port) {
164 port->serial = NULL;
Alan Sternf9c99bb2009-06-02 11:53:55 -0400165 put_device(&port->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 }
167 }
168
169 usb_put_dev(serial->dev);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100170 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171}
172
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200173void usb_serial_put(struct usb_serial *serial)
174{
175 kref_put(&serial->kref, destroy_serial);
176}
177
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178/*****************************************************************************
179 * Driver tty interface functions
180 *****************************************************************************/
Alan Sternf5b09532009-09-01 11:38:44 -0400181
182/**
183 * serial_install - install tty
184 * @driver: the driver (USB in our case)
185 * @tty: the tty being created
186 *
187 * Create the termios objects for this tty. We use the default
188 * USB serial settings but permit them to be overridden by
189 * serial->type->init_termios.
Alan Sterncc56cd02009-09-01 11:39:13 -0400190 *
191 * This is the first place a new tty gets used. Hence this is where we
192 * acquire references to the usb_serial structure and the driver module,
193 * where we store a pointer to the port, and where we do an autoresume.
Alan Stern74556122009-09-01 11:39:40 -0400194 * All these actions are reversed in serial_release().
Alan Sternf5b09532009-09-01 11:38:44 -0400195 */
196static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
197{
198 int idx = tty->index;
199 struct usb_serial *serial;
Alan Sterncc56cd02009-09-01 11:39:13 -0400200 struct usb_serial_port *port;
201 int retval = -ENODEV;
202
203 serial = usb_serial_get_by_index(idx);
204 if (!serial)
205 return retval;
206
207 port = serial->port[idx - serial->minor];
208 if (!port)
209 goto error_no_port;
210 if (!try_module_get(serial->type->driver.owner))
211 goto error_module_get;
212
Alan Stern7e29bb42009-09-01 11:39:22 -0400213 /* perform the standard setup */
214 retval = tty_init_termios(tty);
215 if (retval)
216 goto error_init_termios;
217
Alan Sterncc56cd02009-09-01 11:39:13 -0400218 retval = usb_autopm_get_interface(serial->interface);
219 if (retval)
220 goto error_get_interface;
Alan Sternf5b09532009-09-01 11:38:44 -0400221
Alan Sterncc56cd02009-09-01 11:39:13 -0400222 mutex_unlock(&serial->disc_mutex);
223
Alan Stern7e29bb42009-09-01 11:39:22 -0400224 /* allow the driver to update the settings */
225 if (serial->type->init_termios)
226 serial->type->init_termios(tty);
227
Alan Sterncc56cd02009-09-01 11:39:13 -0400228 tty->driver_data = port;
229
Alan Sternf5b09532009-09-01 11:38:44 -0400230 /* Final install (we use the default method) */
231 tty_driver_kref_get(driver);
232 tty->count++;
233 driver->ttys[idx] = tty;
Alan Sterncc56cd02009-09-01 11:39:13 -0400234 return retval;
235
Alan Sterncc56cd02009-09-01 11:39:13 -0400236 error_get_interface:
Alan Stern7e29bb42009-09-01 11:39:22 -0400237 error_init_termios:
Alan Sterncc56cd02009-09-01 11:39:13 -0400238 module_put(serial->type->driver.owner);
239 error_module_get:
240 error_no_port:
241 usb_serial_put(serial);
242 mutex_unlock(&serial->disc_mutex);
243 return retval;
Alan Sternf5b09532009-09-01 11:38:44 -0400244}
245
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100246static int serial_open (struct tty_struct *tty, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247{
248 struct usb_serial *serial;
249 struct usb_serial_port *port;
Alan Stern2d931482009-04-14 11:31:02 -0400250 int retval = 0;
Alan Coxc56d3002009-07-28 00:34:58 +0100251 int first = 0;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100252
Harvey Harrison441b62c2008-03-03 16:08:34 -0800253 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254
Alan Sterncc56cd02009-09-01 11:39:13 -0400255 port = tty->driver_data;
256 serial = port->serial;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257
Alan Sterncc56cd02009-09-01 11:39:13 -0400258 if (mutex_lock_interruptible(&port->mutex))
259 return -ERESTARTSYS;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100260
Alan Cox95da3102008-07-22 11:09:07 +0100261 ++port->port.count;
Alan Cox4a90f092008-10-13 10:39:46 +0100262 tty_port_tty_set(&port->port, tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263
Jason Wessel6e406122009-06-22 11:32:20 -0500264 /* If the console is attached, the device is already open */
265 if (port->port.count == 1 && !port->console) {
Alan Coxc56d3002009-07-28 00:34:58 +0100266 first = 1;
Alan Stern2d931482009-04-14 11:31:02 -0400267 mutex_lock(&serial->disc_mutex);
Alan Stern2d931482009-04-14 11:31:02 -0400268
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100269 /* only call the device specific open if this
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 * is the first time the port is opened */
Alan Coxa509a7e2009-09-19 13:13:26 -0700271 retval = serial->type->open(tty, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 if (retval)
Alan Sterncc56cd02009-09-01 11:39:13 -0400273 goto bailout_module_put;
Alan Stern2d931482009-04-14 11:31:02 -0400274 mutex_unlock(&serial->disc_mutex);
Alan Coxc56d3002009-07-28 00:34:58 +0100275 set_bit(ASYNCB_INITIALIZED, &port->port.flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276 }
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300277 mutex_unlock(&port->mutex);
Alan Cox335f8512009-06-11 12:26:29 +0100278 /* Now do the correct tty layer semantics */
279 retval = tty_port_block_til_ready(&port->port, tty, filp);
Alan Coxc56d3002009-07-28 00:34:58 +0100280 if (retval == 0) {
281 if (!first)
282 usb_serial_put(serial);
Alan Cox335f8512009-06-11 12:26:29 +0100283 return 0;
Alan Coxc56d3002009-07-28 00:34:58 +0100284 }
285 mutex_lock(&port->mutex);
286 if (first == 0)
287 goto bailout_mutex_unlock;
288 /* Undo the initial port actions */
289 mutex_lock(&serial->disc_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290bailout_module_put:
Alan Stern2d931482009-04-14 11:31:02 -0400291 mutex_unlock(&serial->disc_mutex);
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300292bailout_mutex_unlock:
Alan Cox95da3102008-07-22 11:09:07 +0100293 port->port.count = 0;
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300294 mutex_unlock(&port->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 return retval;
296}
297
Alan Cox335f8512009-06-11 12:26:29 +0100298/**
Alan Stern74556122009-09-01 11:39:40 -0400299 * serial_down - shut down hardware
Alan Sternf5b09532009-09-01 11:38:44 -0400300 * @port: port to shut down
Alan Cox335f8512009-06-11 12:26:29 +0100301 *
Alan Sternf5b09532009-09-01 11:38:44 -0400302 * Shut down a USB serial port unless it is the console. We never
303 * shut down the console hardware as it will always be in use.
Alan Cox335f8512009-06-11 12:26:29 +0100304 */
Alan Stern74556122009-09-01 11:39:40 -0400305static void serial_down(struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306{
Alan Cox335f8512009-06-11 12:26:29 +0100307 struct usb_serial_driver *drv = port->serial->type;
Alan Stern2d931482009-04-14 11:31:02 -0400308 struct usb_serial *serial;
309 struct module *owner;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310
Alan Sternf5b09532009-09-01 11:38:44 -0400311 /*
312 * The console is magical. Do not hang up the console hardware
313 * or there will be tears.
314 */
Alan Cox335f8512009-06-11 12:26:29 +0100315 if (port->console)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316 return;
317
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300318 mutex_lock(&port->mutex);
Alan Stern2d931482009-04-14 11:31:02 -0400319 serial = port->serial;
320 owner = serial->type->driver.owner;
Luiz Fernando Capitulino8a4613f2005-11-28 19:16:07 -0200321
Alan Cox335f8512009-06-11 12:26:29 +0100322 if (drv->close)
323 drv->close(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300325 mutex_unlock(&port->mutex);
Alan Cox335f8512009-06-11 12:26:29 +0100326}
327
Alan Sternf5b09532009-09-01 11:38:44 -0400328static void serial_hangup(struct tty_struct *tty)
Alan Cox335f8512009-06-11 12:26:29 +0100329{
Alan Cox4455e342009-09-19 13:13:24 -0700330 struct usb_serial_port *port = tty->driver_data;
Alan Stern74556122009-09-01 11:39:40 -0400331 serial_down(port);
Alan Sternf5b09532009-09-01 11:38:44 -0400332 tty_port_hangup(&port->port);
333 /* We must not free port yet - the USB serial layer depends on it's
334 continued existence */
Alan Cox335f8512009-06-11 12:26:29 +0100335}
336
337static void serial_close(struct tty_struct *tty, struct file *filp)
338{
339 struct usb_serial_port *port = tty->driver_data;
340
341 dbg("%s - port %d", __func__, port->number);
342
Alan Cox335f8512009-06-11 12:26:29 +0100343 if (tty_port_close_start(&port->port, tty, filp) == 0)
344 return;
Alan Stern74556122009-09-01 11:39:40 -0400345 serial_down(port);
Alan Cox335f8512009-06-11 12:26:29 +0100346 tty_port_close_end(&port->port, tty);
347 tty_port_tty_set(&port->port, NULL);
Alan Cox335f8512009-06-11 12:26:29 +0100348}
349
Alan Sternf5b09532009-09-01 11:38:44 -0400350/**
Alan Stern74556122009-09-01 11:39:40 -0400351 * serial_release - free resources post close/hangup
Alan Sternf5b09532009-09-01 11:38:44 -0400352 * @port: port to free up
353 *
354 * Do the resource freeing and refcount dropping for the port.
355 * Avoid freeing the console.
356 *
357 * Called when the last tty kref is dropped.
358 */
Alan Stern74556122009-09-01 11:39:40 -0400359static void serial_release(struct tty_struct *tty)
Alan Cox335f8512009-06-11 12:26:29 +0100360{
361 struct usb_serial_port *port = tty->driver_data;
Alan Sternf5b09532009-09-01 11:38:44 -0400362 struct usb_serial *serial;
363 struct module *owner;
364
365 /* The console is magical. Do not hang up the console hardware
366 * or there will be tears.
367 */
Alan Sterncc56cd02009-09-01 11:39:13 -0400368 if (port->console)
Alan Sternf5b09532009-09-01 11:38:44 -0400369 return;
370
Alan Stern74556122009-09-01 11:39:40 -0400371 /* Standard shutdown processing */
372 tty_shutdown(tty);
373
Alan Sterncc56cd02009-09-01 11:39:13 -0400374 tty->driver_data = NULL;
375
Alan Sternf5b09532009-09-01 11:38:44 -0400376 serial = port->serial;
377 owner = serial->type->driver.owner;
378
379 mutex_lock(&serial->disc_mutex);
380 if (!serial->disconnected)
381 usb_autopm_put_interface(serial->interface);
382 mutex_unlock(&serial->disc_mutex);
383
384 usb_serial_put(serial);
385 module_put(owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386}
387
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100388static int serial_write(struct tty_struct *tty, const unsigned char *buf,
389 int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200391 struct usb_serial_port *port = tty->driver_data;
Oliver Neukum3ff4fd92007-01-13 07:32:27 +0100392 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393
Alan Coxf34d7a52008-04-30 00:54:13 -0700394 if (port->serial->dev->state == USB_STATE_NOTATTACHED)
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200395 goto exit;
396
Harvey Harrison441b62c2008-03-03 16:08:34 -0800397 dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398
Alan Cox95da3102008-07-22 11:09:07 +0100399 /* count is managed under the mutex lock for the tty so cannot
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100400 drop to zero until after the last close completes */
Alan Cox95da3102008-07-22 11:09:07 +0100401 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402
403 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100404 retval = port->serial->type->write(tty, port, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405
406exit:
407 return retval;
408}
409
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100410static int serial_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200412 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800413 dbg("%s - port %d", __func__, port->number);
Alan Cox95da3102008-07-22 11:09:07 +0100414 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100416 return port->serial->type->write_room(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417}
418
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100419static int serial_chars_in_buffer(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200421 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800422 dbg("%s = port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423
Alan Coxeff69372009-01-02 13:47:06 +0000424 /* if the device was unplugged then any remaining characters
425 fell out of the connector ;) */
426 if (port->serial->disconnected)
427 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100429 return port->serial->type->chars_in_buffer(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430}
431
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100432static void serial_throttle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200434 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800435 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436
Alan Cox95da3102008-07-22 11:09:07 +0100437 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438 /* pass on to the driver specific version of this function */
439 if (port->serial->type->throttle)
Alan Cox95da3102008-07-22 11:09:07 +0100440 port->serial->type->throttle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441}
442
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100443static void serial_unthrottle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200445 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800446 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447
Alan Cox95da3102008-07-22 11:09:07 +0100448 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 /* pass on to the driver specific version of this function */
450 if (port->serial->type->unthrottle)
Alan Cox95da3102008-07-22 11:09:07 +0100451 port->serial->type->unthrottle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452}
453
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100454static int serial_ioctl(struct tty_struct *tty, struct file *file,
455 unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200457 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458 int retval = -ENODEV;
459
Harvey Harrison441b62c2008-03-03 16:08:34 -0800460 dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461
Alan Cox95da3102008-07-22 11:09:07 +0100462 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100464 /* pass on to the driver specific version of this function
465 if it is available */
Alan Coxf34d7a52008-04-30 00:54:13 -0700466 if (port->serial->type->ioctl) {
Alan Cox95da3102008-07-22 11:09:07 +0100467 retval = port->serial->type->ioctl(tty, file, cmd, arg);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100468 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 retval = -ENOIOCTLCMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 return retval;
471}
472
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100473static void serial_set_termios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200475 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800476 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477
Alan Cox95da3102008-07-22 11:09:07 +0100478 WARN_ON(!port->port.count);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100479 /* pass on to the driver specific version of this function
480 if it is available */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 if (port->serial->type->set_termios)
Alan Cox95da3102008-07-22 11:09:07 +0100482 port->serial->type->set_termios(tty, port, old);
Alan Cox33785092007-10-18 01:24:22 -0700483 else
484 tty_termios_copy_hw(tty->termios, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485}
486
Alan Cox9e989662008-07-22 11:18:03 +0100487static int serial_break(struct tty_struct *tty, int break_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200489 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490
Harvey Harrison441b62c2008-03-03 16:08:34 -0800491 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492
Alan Cox95da3102008-07-22 11:09:07 +0100493 WARN_ON(!port->port.count);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100494 /* pass on to the driver specific version of this function
495 if it is available */
Alan Cox6b447f042009-01-02 13:48:56 +0000496 if (port->serial->type->break_ctl)
Alan Cox95da3102008-07-22 11:09:07 +0100497 port->serial->type->break_ctl(tty, break_state);
Alan Cox9e989662008-07-22 11:18:03 +0100498 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499}
500
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700501static int serial_proc_show(struct seq_file *m, void *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502{
503 struct usb_serial *serial;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 char tmp[40];
506
Harvey Harrison441b62c2008-03-03 16:08:34 -0800507 dbg("%s", __func__);
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700508 seq_puts(m, "usbserinfo:1.0 driver:2.0\n");
509 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 serial = usb_serial_get_by_index(i);
511 if (serial == NULL)
512 continue;
513
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700514 seq_printf(m, "%d:", i);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700515 if (serial->type->driver.owner)
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700516 seq_printf(m, " module:%s",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100517 module_name(serial->type->driver.owner));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700518 seq_printf(m, " name:\"%s\"",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100519 serial->type->description);
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700520 seq_printf(m, " vendor:%04x product:%04x",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100521 le16_to_cpu(serial->dev->descriptor.idVendor),
522 le16_to_cpu(serial->dev->descriptor.idProduct));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700523 seq_printf(m, " num_ports:%d", serial->num_ports);
524 seq_printf(m, " port:%d", i - serial->minor + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 usb_make_path(serial->dev, tmp, sizeof(tmp));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700526 seq_printf(m, " path:%s", tmp);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100527
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700528 seq_putc(m, '\n');
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200529 usb_serial_put(serial);
Alan Stern8bc2c1b2009-09-01 11:38:59 -0400530 mutex_unlock(&serial->disc_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 }
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700532 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533}
534
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700535static int serial_proc_open(struct inode *inode, struct file *file)
536{
537 return single_open(file, serial_proc_show, NULL);
538}
539
540static const struct file_operations serial_proc_fops = {
541 .owner = THIS_MODULE,
542 .open = serial_proc_open,
543 .read = seq_read,
544 .llseek = seq_lseek,
545 .release = single_release,
546};
547
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100548static int serial_tiocmget(struct tty_struct *tty, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200550 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551
Harvey Harrison441b62c2008-03-03 16:08:34 -0800552 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553
Alan Cox95da3102008-07-22 11:09:07 +0100554 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 if (port->serial->type->tiocmget)
Alan Cox95da3102008-07-22 11:09:07 +0100556 return port->serial->type->tiocmget(tty, file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 return -EINVAL;
558}
559
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100560static int serial_tiocmset(struct tty_struct *tty, struct file *file,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561 unsigned int set, unsigned int clear)
562{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200563 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564
Harvey Harrison441b62c2008-03-03 16:08:34 -0800565 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566
Alan Cox95da3102008-07-22 11:09:07 +0100567 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568 if (port->serial->type->tiocmset)
Alan Cox95da3102008-07-22 11:09:07 +0100569 return port->serial->type->tiocmset(tty, file, set, clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 return -EINVAL;
571}
572
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700573/*
574 * We would be calling tty_wakeup here, but unfortunately some line
575 * disciplines have an annoying habit of calling tty->write from
576 * the write wakeup callback (e.g. n_hdlc.c).
577 */
578void usb_serial_port_softint(struct usb_serial_port *port)
579{
580 schedule_work(&port->work);
581}
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100582EXPORT_SYMBOL_GPL(usb_serial_port_softint);
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700583
David Howellsc4028952006-11-22 14:57:56 +0000584static void usb_serial_port_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585{
David Howellsc4028952006-11-22 14:57:56 +0000586 struct usb_serial_port *port =
587 container_of(work, struct usb_serial_port, work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 struct tty_struct *tty;
589
Harvey Harrison441b62c2008-03-03 16:08:34 -0800590 dbg("%s - port %d", __func__, port->number);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100591
Alan Cox4a90f092008-10-13 10:39:46 +0100592 tty = tty_port_tty_get(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593 if (!tty)
594 return;
595
596 tty_wakeup(tty);
Alan Cox4a90f092008-10-13 10:39:46 +0100597 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598}
599
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100600static void kill_traffic(struct usb_serial_port *port)
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700601{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603 usb_kill_urb(port->write_urb);
Oliver Neukum5adceac2007-08-17 14:01:38 +0200604 /*
605 * This is tricky.
606 * Some drivers submit the read_urb in the
607 * handler for the write_urb or vice versa
608 * this order determines the order in which
609 * usb_kill_urb() must be used to reliably
610 * kill the URBs. As it is unknown here,
611 * both orders must be used in turn.
612 * The call below is not redundant.
613 */
614 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 usb_kill_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 usb_kill_urb(port->interrupt_out_urb);
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100617}
618
Alan Stern41bd34d2009-09-01 11:38:34 -0400619static void port_release(struct device *dev)
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100620{
Alan Stern41bd34d2009-09-01 11:38:34 -0400621 struct usb_serial_port *port = to_usb_serial_port(dev);
622
623 dbg ("%s - %s", __func__, dev_name(dev));
624
Alan Stern2d931482009-04-14 11:31:02 -0400625 /*
626 * Stop all the traffic before cancelling the work, so that
627 * nobody will restart it by calling usb_serial_port_softint.
628 */
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100629 kill_traffic(port);
Alan Stern2d931482009-04-14 11:31:02 -0400630 cancel_work_sync(&port->work);
631
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100632 usb_free_urb(port->read_urb);
633 usb_free_urb(port->write_urb);
634 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 usb_free_urb(port->interrupt_out_urb);
636 kfree(port->bulk_in_buffer);
637 kfree(port->bulk_out_buffer);
638 kfree(port->interrupt_in_buffer);
639 kfree(port->interrupt_out_buffer);
640 kfree(port);
641}
642
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100643static struct usb_serial *create_serial(struct usb_device *dev,
644 struct usb_interface *interface,
645 struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646{
647 struct usb_serial *serial;
648
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100649 serial = kzalloc(sizeof(*serial), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 if (!serial) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800651 dev_err(&dev->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 return NULL;
653 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 serial->dev = usb_get_dev(dev);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700655 serial->type = driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 serial->interface = interface;
657 kref_init(&serial->kref);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +0100658 mutex_init(&serial->disc_mutex);
Alan Stern0282b7f2008-07-29 12:01:04 -0400659 serial->minor = SERIAL_TTY_NO_MINOR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660
661 return serial;
662}
663
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100664static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf,
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100665 struct usb_serial_driver *drv)
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100666{
667 struct usb_dynid *dynid;
668
669 spin_lock(&drv->dynids.lock);
670 list_for_each_entry(dynid, &drv->dynids.list, node) {
671 if (usb_match_one_id(intf, &dynid->id)) {
672 spin_unlock(&drv->dynids.lock);
673 return &dynid->id;
674 }
675 }
676 spin_unlock(&drv->dynids.lock);
677 return NULL;
678}
679
680static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv,
681 struct usb_interface *intf)
682{
683 const struct usb_device_id *id;
684
685 id = usb_match_id(intf, drv->id_table);
686 if (id) {
687 dbg("static descriptor matches");
688 goto exit;
689 }
690 id = match_dynamic_id(intf, drv);
691 if (id)
692 dbg("dynamic descriptor matches");
693exit:
694 return id;
695}
696
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100697static struct usb_serial_driver *search_serial_device(
698 struct usb_interface *iface)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 const struct usb_device_id *id;
Alan Stern063a2da2007-10-10 16:24:06 -0400701 struct usb_serial_driver *drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702
Adrian Bunk93b1fae2006-01-10 00:13:33 +0100703 /* Check if the usb id matches a known device */
Alan Stern063a2da2007-10-10 16:24:06 -0400704 list_for_each_entry(drv, &usb_serial_driver_list, driver_list) {
705 id = get_iface_id(drv, iface);
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100706 if (id)
Alan Stern063a2da2007-10-10 16:24:06 -0400707 return drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 }
709
710 return NULL;
711}
712
Alan Cox335f8512009-06-11 12:26:29 +0100713static int serial_carrier_raised(struct tty_port *port)
714{
715 struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
716 struct usb_serial_driver *drv = p->serial->type;
717 if (drv->carrier_raised)
718 return drv->carrier_raised(p);
719 /* No carrier control - don't block */
720 return 1;
721}
722
723static void serial_dtr_rts(struct tty_port *port, int on)
724{
725 struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
726 struct usb_serial_driver *drv = p->serial->type;
727 if (drv->dtr_rts)
728 drv->dtr_rts(p, on);
729}
730
731static const struct tty_port_operations serial_port_ops = {
732 .carrier_raised = serial_carrier_raised,
733 .dtr_rts = serial_dtr_rts,
734};
735
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736int usb_serial_probe(struct usb_interface *interface,
737 const struct usb_device_id *id)
738{
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100739 struct usb_device *dev = interface_to_usbdev(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 struct usb_serial *serial = NULL;
741 struct usb_serial_port *port;
742 struct usb_host_interface *iface_desc;
743 struct usb_endpoint_descriptor *endpoint;
744 struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS];
745 struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS];
746 struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];
747 struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700748 struct usb_serial_driver *type = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 int retval;
Andre Hauptdd9ca5d2008-06-18 15:56:00 +0200750 unsigned int minor;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 int buffer_size;
752 int i;
753 int num_interrupt_in = 0;
754 int num_interrupt_out = 0;
755 int num_bulk_in = 0;
756 int num_bulk_out = 0;
757 int num_ports = 0;
758 int max_endpoints;
759
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100760 lock_kernel(); /* guard against unloading a serial driver module */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 type = search_serial_device(interface);
762 if (!type) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100763 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 dbg("none matched");
765 return -ENODEV;
766 }
767
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100768 serial = create_serial(dev, interface, type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769 if (!serial) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100770 unlock_kernel();
Harvey Harrison441b62c2008-03-03 16:08:34 -0800771 dev_err(&interface->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 return -ENOMEM;
773 }
774
775 /* if this device type has a probe function, call it */
776 if (type->probe) {
777 const struct usb_device_id *id;
778
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700779 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100780 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100781 dev_err(&interface->dev,
782 "module get failed, exiting\n");
783 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 return -EIO;
785 }
786
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100787 id = get_iface_id(type, interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 retval = type->probe(serial, id);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700789 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790
791 if (retval) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100792 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100793 dbg("sub driver rejected device");
794 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 return retval;
796 }
797 }
798
799 /* descriptor matches, let's find the endpoints needed */
800 /* check out the endpoints */
801 iface_desc = interface->cur_altsetting;
802 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
803 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700804
805 if (usb_endpoint_is_bulk_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 /* we found a bulk in endpoint */
807 dbg("found bulk in on endpoint %d", i);
808 bulk_in_endpoint[num_bulk_in] = endpoint;
809 ++num_bulk_in;
810 }
811
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700812 if (usb_endpoint_is_bulk_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813 /* we found a bulk out endpoint */
814 dbg("found bulk out on endpoint %d", i);
815 bulk_out_endpoint[num_bulk_out] = endpoint;
816 ++num_bulk_out;
817 }
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700818
819 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820 /* we found a interrupt in endpoint */
821 dbg("found interrupt in on endpoint %d", i);
822 interrupt_in_endpoint[num_interrupt_in] = endpoint;
823 ++num_interrupt_in;
824 }
825
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700826 if (usb_endpoint_is_int_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 /* we found an interrupt out endpoint */
828 dbg("found interrupt out on endpoint %d", i);
829 interrupt_out_endpoint[num_interrupt_out] = endpoint;
830 ++num_interrupt_out;
831 }
832 }
833
834#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100835 /* BEGIN HORRIBLE HACK FOR PL2303 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 /* this is needed due to the looney way its endpoints are set up */
837 if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&
838 (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||
839 ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) &&
Johannes Steingraeber8fd80132006-09-16 16:17:34 +0200840 (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) ||
841 ((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) &&
Andreas Bombece816cf2008-09-14 01:58:55 +0200842 (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID)) ||
843 ((le16_to_cpu(dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) &&
844 (le16_to_cpu(dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_EF81))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 if (interface != dev->actconfig->interface[0]) {
846 /* check out the endpoints of the other interface*/
847 iface_desc = dev->actconfig->interface[0]->cur_altsetting;
848 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
849 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700850 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 /* we found a interrupt in endpoint */
852 dbg("found interrupt in for Prolific device on separate interface");
853 interrupt_in_endpoint[num_interrupt_in] = endpoint;
854 ++num_interrupt_in;
855 }
856 }
857 }
858
859 /* Now make sure the PL-2303 is configured correctly.
860 * If not, give up now and hope this hack will work
861 * properly during a later invocation of usb_serial_probe
862 */
863 if (num_bulk_in == 0 || num_bulk_out == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100864 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865 dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100866 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867 return -ENODEV;
868 }
869 }
870 /* END HORRIBLE HACK FOR PL2303 */
871#endif
872
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873#ifdef CONFIG_USB_SERIAL_GENERIC
874 if (type == &usb_serial_generic_device) {
875 num_ports = num_bulk_out;
876 if (num_ports == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100877 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100878 dev_err(&interface->dev,
879 "Generic device with no bulk out, not allowed.\n");
880 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 return -EIO;
882 }
883 }
884#endif
885 if (!num_ports) {
886 /* if this device type has a calc_num_ports function, call it */
887 if (type->calc_num_ports) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700888 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100889 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100890 dev_err(&interface->dev,
891 "module get failed, exiting\n");
892 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 return -EIO;
894 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100895 num_ports = type->calc_num_ports(serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700896 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 }
898 if (!num_ports)
899 num_ports = type->num_ports;
900 }
901
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 serial->num_ports = num_ports;
903 serial->num_bulk_in = num_bulk_in;
904 serial->num_bulk_out = num_bulk_out;
905 serial->num_interrupt_in = num_interrupt_in;
906 serial->num_interrupt_out = num_interrupt_out;
907
Alan Stern063a2da2007-10-10 16:24:06 -0400908 /* found all that we need */
909 dev_info(&interface->dev, "%s converter detected\n",
910 type->description);
911
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 /* create our ports, we need as many as the max endpoints */
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100913 /* we don't use num_ports here because some devices have more
914 endpoint pairs than ports */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 max_endpoints = max(num_bulk_in, num_bulk_out);
916 max_endpoints = max(max_endpoints, num_interrupt_in);
917 max_endpoints = max(max_endpoints, num_interrupt_out);
918 max_endpoints = max(max_endpoints, (int)serial->num_ports);
919 serial->num_port_pointers = max_endpoints;
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100920 unlock_kernel();
921
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100922 dbg("%s - setting up %d port structures for this device",
923 __func__, max_endpoints);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 for (i = 0; i < max_endpoints; ++i) {
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100925 port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 if (!port)
927 goto probe_error;
Alan Cox4a90f092008-10-13 10:39:46 +0100928 tty_port_init(&port->port);
Alan Cox335f8512009-06-11 12:26:29 +0100929 port->port.ops = &serial_port_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 port->serial = serial;
Greg Kroah-Hartman507ca9b2005-04-23 12:49:16 -0700931 spin_lock_init(&port->lock);
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300932 mutex_init(&port->mutex);
David Howellsc4028952006-11-22 14:57:56 +0000933 INIT_WORK(&port->work, usb_serial_port_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 serial->port[i] = port;
Alan Stern41bd34d2009-09-01 11:38:34 -0400935 port->dev.parent = &interface->dev;
936 port->dev.driver = NULL;
937 port->dev.bus = &usb_serial_bus_type;
938 port->dev.release = &port_release;
939 device_initialize(&port->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 }
941
942 /* set up the endpoint information */
943 for (i = 0; i < num_bulk_in; ++i) {
944 endpoint = bulk_in_endpoint[i];
945 port = serial->port[i];
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100946 port->read_urb = usb_alloc_urb(0, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947 if (!port->read_urb) {
948 dev_err(&interface->dev, "No free urbs available\n");
949 goto probe_error;
950 }
951 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
952 port->bulk_in_size = buffer_size;
953 port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100954 port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955 if (!port->bulk_in_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100956 dev_err(&interface->dev,
957 "Couldn't allocate bulk_in_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 goto probe_error;
959 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100960 usb_fill_bulk_urb(port->read_urb, dev,
961 usb_rcvbulkpipe(dev,
962 endpoint->bEndpointAddress),
963 port->bulk_in_buffer, buffer_size,
964 serial->type->read_bulk_callback, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 }
966
967 for (i = 0; i < num_bulk_out; ++i) {
968 endpoint = bulk_out_endpoint[i];
969 port = serial->port[i];
970 port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
971 if (!port->write_urb) {
972 dev_err(&interface->dev, "No free urbs available\n");
973 goto probe_error;
974 }
975 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
976 port->bulk_out_size = buffer_size;
977 port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100978 port->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979 if (!port->bulk_out_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100980 dev_err(&interface->dev,
981 "Couldn't allocate bulk_out_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 goto probe_error;
983 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100984 usb_fill_bulk_urb(port->write_urb, dev,
985 usb_sndbulkpipe(dev,
986 endpoint->bEndpointAddress),
987 port->bulk_out_buffer, buffer_size,
988 serial->type->write_bulk_callback, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 }
990
991 if (serial->type->read_int_callback) {
992 for (i = 0; i < num_interrupt_in; ++i) {
993 endpoint = interrupt_in_endpoint[i];
994 port = serial->port[i];
995 port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
996 if (!port->interrupt_in_urb) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100997 dev_err(&interface->dev,
998 "No free urbs available\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999 goto probe_error;
1000 }
1001 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001002 port->interrupt_in_endpointAddress =
1003 endpoint->bEndpointAddress;
1004 port->interrupt_in_buffer = kmalloc(buffer_size,
1005 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 if (!port->interrupt_in_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001007 dev_err(&interface->dev,
1008 "Couldn't allocate interrupt_in_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 goto probe_error;
1010 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001011 usb_fill_int_urb(port->interrupt_in_urb, dev,
1012 usb_rcvintpipe(dev,
1013 endpoint->bEndpointAddress),
1014 port->interrupt_in_buffer, buffer_size,
1015 serial->type->read_int_callback, port,
1016 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 }
1018 } else if (num_interrupt_in) {
1019 dbg("the device claims to support interrupt in transfers, but read_int_callback is not defined");
1020 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001021
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 if (serial->type->write_int_callback) {
1023 for (i = 0; i < num_interrupt_out; ++i) {
1024 endpoint = interrupt_out_endpoint[i];
1025 port = serial->port[i];
1026 port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
1027 if (!port->interrupt_out_urb) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001028 dev_err(&interface->dev,
1029 "No free urbs available\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 goto probe_error;
1031 }
1032 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
1033 port->interrupt_out_size = buffer_size;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001034 port->interrupt_out_endpointAddress =
1035 endpoint->bEndpointAddress;
1036 port->interrupt_out_buffer = kmalloc(buffer_size,
1037 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 if (!port->interrupt_out_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001039 dev_err(&interface->dev,
1040 "Couldn't allocate interrupt_out_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 goto probe_error;
1042 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001043 usb_fill_int_urb(port->interrupt_out_urb, dev,
1044 usb_sndintpipe(dev,
1045 endpoint->bEndpointAddress),
1046 port->interrupt_out_buffer, buffer_size,
1047 serial->type->write_int_callback, port,
1048 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 }
1050 } else if (num_interrupt_out) {
1051 dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined");
1052 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001053
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 /* if this device type has an attach function, call it */
1055 if (type->attach) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -07001056 if (!try_module_get(type->driver.owner)) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001057 dev_err(&interface->dev,
1058 "module get failed, exiting\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 goto probe_error;
1060 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001061 retval = type->attach(serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -07001062 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063 if (retval < 0)
1064 goto probe_error;
1065 if (retval > 0) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001066 /* quietly accept this device, but don't bind to a
1067 serial port as it's about to disappear */
Alan Stern0a3c8542009-05-27 11:25:52 -04001068 serial->num_ports = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 goto exit;
1070 }
1071 }
1072
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001073 if (get_free_serial(serial, num_ports, &minor) == NULL) {
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001074 dev_err(&interface->dev, "No more free serial devices\n");
1075 goto probe_error;
1076 }
Oliver Neukumc744f992007-02-26 15:43:00 +01001077 serial->minor = minor;
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001078
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 /* register all of the individual ports with the driver core */
1080 for (i = 0; i < num_ports; ++i) {
1081 port = serial->port[i];
Kay Sievers0031a062008-05-02 06:02:41 +02001082 dev_set_name(&port->dev, "ttyUSB%d", port->number);
Kay Sievers7071a3c2008-05-02 06:02:41 +02001083 dbg ("%s - registering %s", __func__, dev_name(&port->dev));
Alan Sternc706ebd2009-06-02 11:54:11 -04001084 port->dev_state = PORT_REGISTERING;
Alan Stern41bd34d2009-09-01 11:38:34 -04001085 retval = device_add(&port->dev);
Alan Sternc706ebd2009-06-02 11:54:11 -04001086 if (retval) {
Greg Kroah-Hartman13f4db92006-08-28 11:43:25 -07001087 dev_err(&port->dev, "Error registering port device, "
1088 "continuing\n");
Alan Sternc706ebd2009-06-02 11:54:11 -04001089 port->dev_state = PORT_UNREGISTERED;
1090 } else {
1091 port->dev_state = PORT_REGISTERED;
1092 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 }
1094
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001095 usb_serial_console_init(debug, minor);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096
1097exit:
1098 /* success */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001099 usb_set_intfdata(interface, serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 return 0;
1101
1102probe_error:
Alan Stern41bd34d2009-09-01 11:38:34 -04001103 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 return -EIO;
1105}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001106EXPORT_SYMBOL_GPL(usb_serial_probe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107
1108void usb_serial_disconnect(struct usb_interface *interface)
1109{
1110 int i;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001111 struct usb_serial *serial = usb_get_intfdata(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 struct device *dev = &interface->dev;
1113 struct usb_serial_port *port;
1114
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +02001115 usb_serial_console_disconnect(serial);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001116 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001118 mutex_lock(&serial->disc_mutex);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001119 usb_set_intfdata(interface, NULL);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001120 /* must set a flag, to signal subdrivers */
1121 serial->disconnected = 1;
Alan Stern2d931482009-04-14 11:31:02 -04001122 mutex_unlock(&serial->disc_mutex);
1123
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001124 for (i = 0; i < serial->num_ports; ++i) {
1125 port = serial->port[i];
1126 if (port) {
Alan Cox4a90f092008-10-13 10:39:46 +01001127 struct tty_struct *tty = tty_port_tty_get(&port->port);
1128 if (tty) {
Alan Coxd2b39182009-09-19 13:13:23 -07001129 tty_vhangup(tty);
Alan Cox4a90f092008-10-13 10:39:46 +01001130 tty_kref_put(tty);
1131 }
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001132 kill_traffic(port);
Alan Stern2d931482009-04-14 11:31:02 -04001133 cancel_work_sync(&port->work);
Alan Sternc706ebd2009-06-02 11:54:11 -04001134 if (port->dev_state == PORT_REGISTERED) {
1135
1136 /* Make sure the port is bound so that the
1137 * driver's port_remove method is called.
1138 */
1139 if (!port->dev.driver) {
1140 int rc;
1141
1142 port->dev.driver =
1143 &serial->type->driver;
1144 rc = device_bind_driver(&port->dev);
1145 }
1146 port->dev_state = PORT_UNREGISTERING;
1147 device_del(&port->dev);
1148 port->dev_state = PORT_UNREGISTERED;
1149 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151 }
Alan Sternf9c99bb2009-06-02 11:53:55 -04001152 serial->type->disconnect(serial);
Alan Stern2d931482009-04-14 11:31:02 -04001153
Alan Stern41bd34d2009-09-01 11:38:34 -04001154 /* let the last holder of this object cause it to be cleaned up */
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001155 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 dev_info(dev, "device disconnected\n");
1157}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001158EXPORT_SYMBOL_GPL(usb_serial_disconnect);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159
Oliver Neukumec225592007-04-27 20:54:57 +02001160int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
1161{
1162 struct usb_serial *serial = usb_get_intfdata(intf);
1163 struct usb_serial_port *port;
1164 int i, r = 0;
1165
Oliver Neukumf8bece82009-02-05 16:54:25 +01001166 serial->suspending = 1;
1167
Oliver Neukume31c1882007-07-23 08:58:39 +02001168 for (i = 0; i < serial->num_ports; ++i) {
1169 port = serial->port[i];
1170 if (port)
1171 kill_traffic(port);
Oliver Neukumec225592007-04-27 20:54:57 +02001172 }
1173
1174 if (serial->type->suspend)
Oliver Neukume31c1882007-07-23 08:58:39 +02001175 r = serial->type->suspend(serial, message);
Oliver Neukumec225592007-04-27 20:54:57 +02001176
1177 return r;
1178}
1179EXPORT_SYMBOL(usb_serial_suspend);
1180
1181int usb_serial_resume(struct usb_interface *intf)
1182{
1183 struct usb_serial *serial = usb_get_intfdata(intf);
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001184 int rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001185
Oliver Neukumf8bece82009-02-05 16:54:25 +01001186 serial->suspending = 0;
Sarah Sharp8abaee22007-10-25 10:58:43 -07001187 if (serial->type->resume)
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001188 rv = serial->type->resume(serial);
1189 else
1190 rv = usb_serial_generic_resume(serial);
Oliver Neukumf8bece82009-02-05 16:54:25 +01001191
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001192 return rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001193}
1194EXPORT_SYMBOL(usb_serial_resume);
1195
Jeff Dikeb68e31d2006-10-02 02:17:18 -07001196static const struct tty_operations serial_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197 .open = serial_open,
1198 .close = serial_close,
1199 .write = serial_write,
Alan Cox335f8512009-06-11 12:26:29 +01001200 .hangup = serial_hangup,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 .write_room = serial_write_room,
1202 .ioctl = serial_ioctl,
1203 .set_termios = serial_set_termios,
1204 .throttle = serial_throttle,
1205 .unthrottle = serial_unthrottle,
1206 .break_ctl = serial_break,
1207 .chars_in_buffer = serial_chars_in_buffer,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 .tiocmget = serial_tiocmget,
1209 .tiocmset = serial_tiocmset,
Alan Stern74556122009-09-01 11:39:40 -04001210 .shutdown = serial_release,
Alan Coxfe1ae7f2009-09-19 13:13:33 -07001211 .install = serial_install,
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -07001212 .proc_fops = &serial_proc_fops,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213};
1214
Alan Cox335f8512009-06-11 12:26:29 +01001215
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216struct tty_driver *usb_serial_tty_driver;
1217
1218static int __init usb_serial_init(void)
1219{
1220 int i;
1221 int result;
1222
1223 usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS);
1224 if (!usb_serial_tty_driver)
1225 return -ENOMEM;
1226
1227 /* Initialize our global data */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001228 for (i = 0; i < SERIAL_TTY_MINORS; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229 serial_table[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230
1231 result = bus_register(&usb_serial_bus_type);
1232 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001233 printk(KERN_ERR "usb-serial: %s - registering bus driver "
1234 "failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235 goto exit_bus;
1236 }
1237
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 usb_serial_tty_driver->owner = THIS_MODULE;
1239 usb_serial_tty_driver->driver_name = "usbserial";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240 usb_serial_tty_driver->name = "ttyUSB";
1241 usb_serial_tty_driver->major = SERIAL_TTY_MAJOR;
1242 usb_serial_tty_driver->minor_start = 0;
1243 usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
1244 usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001245 usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW |
1246 TTY_DRIVER_DYNAMIC_DEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247 usb_serial_tty_driver->init_termios = tty_std_termios;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001248 usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD
1249 | HUPCL | CLOCAL;
Alan Coxa5b6f602008-04-08 17:16:06 +01001250 usb_serial_tty_driver->init_termios.c_ispeed = 9600;
1251 usb_serial_tty_driver->init_termios.c_ospeed = 9600;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252 tty_set_operations(usb_serial_tty_driver, &serial_ops);
1253 result = tty_register_driver(usb_serial_tty_driver);
1254 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001255 printk(KERN_ERR "usb-serial: %s - tty_register_driver failed\n",
1256 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257 goto exit_reg_driver;
1258 }
1259
1260 /* register the USB driver */
1261 result = usb_register(&usb_serial_driver);
1262 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001263 printk(KERN_ERR "usb-serial: %s - usb_register failed\n",
1264 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265 goto exit_tty;
1266 }
1267
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001268 /* register the generic driver, if we should */
1269 result = usb_serial_generic_register(debug);
1270 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001271 printk(KERN_ERR "usb-serial: %s - registering generic "
1272 "driver failed\n", __func__);
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001273 goto exit_generic;
1274 }
1275
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001276 printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277
1278 return result;
1279
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001280exit_generic:
1281 usb_deregister(&usb_serial_driver);
1282
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283exit_tty:
1284 tty_unregister_driver(usb_serial_tty_driver);
1285
1286exit_reg_driver:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287 bus_unregister(&usb_serial_bus_type);
1288
1289exit_bus:
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001290 printk(KERN_ERR "usb-serial: %s - returning with error %d\n",
1291 __func__, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 put_tty_driver(usb_serial_tty_driver);
1293 return result;
1294}
1295
1296
1297static void __exit usb_serial_exit(void)
1298{
1299 usb_serial_console_exit();
1300
1301 usb_serial_generic_deregister();
1302
1303 usb_deregister(&usb_serial_driver);
1304 tty_unregister_driver(usb_serial_tty_driver);
1305 put_tty_driver(usb_serial_tty_driver);
1306 bus_unregister(&usb_serial_bus_type);
1307}
1308
1309
1310module_init(usb_serial_init);
1311module_exit(usb_serial_exit);
1312
1313#define set_to_generic_if_null(type, function) \
1314 do { \
1315 if (!type->function) { \
1316 type->function = usb_serial_generic_##function; \
1317 dbg("Had to override the " #function \
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001318 " usb serial operation with the generic one.");\
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 } \
1320 } while (0)
1321
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001322static void fixup_generic(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323{
1324 set_to_generic_if_null(device, open);
1325 set_to_generic_if_null(device, write);
1326 set_to_generic_if_null(device, close);
1327 set_to_generic_if_null(device, write_room);
1328 set_to_generic_if_null(device, chars_in_buffer);
1329 set_to_generic_if_null(device, read_bulk_callback);
1330 set_to_generic_if_null(device, write_bulk_callback);
Alan Sternf9c99bb2009-06-02 11:53:55 -04001331 set_to_generic_if_null(device, disconnect);
1332 set_to_generic_if_null(device, release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333}
1334
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001335int usb_serial_register(struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001337 /* must be called with BKL held */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 int retval;
1339
Dave Younge4abe662009-02-14 21:21:13 +08001340 if (usb_disabled())
1341 return -ENODEV;
1342
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001343 fixup_generic(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001345 if (!driver->description)
1346 driver->description = driver->driver.name;
1347
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 /* Add this device to our list of devices */
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001349 list_add(&driver->driver_list, &usb_serial_driver_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001351 retval = usb_serial_bus_register(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 if (retval) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001353 printk(KERN_ERR "usb-serial: problem %d when registering "
1354 "driver %s\n", retval, driver->description);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001355 list_del(&driver->driver_list);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001356 } else
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001357 printk(KERN_INFO "USB Serial support registered for %s\n",
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001358 driver->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359
1360 return retval;
1361}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001362EXPORT_SYMBOL_GPL(usb_serial_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363
1364
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001365void usb_serial_deregister(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001367 /* must be called with BKL held */
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001368 printk(KERN_INFO "USB Serial deregistering driver %s\n",
1369 device->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370 list_del(&device->driver_list);
1371 usb_serial_bus_deregister(device);
1372}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373EXPORT_SYMBOL_GPL(usb_serial_deregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374
1375/* Module information */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001376MODULE_AUTHOR(DRIVER_AUTHOR);
1377MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378MODULE_LICENSE("GPL");
1379
1380module_param(debug, bool, S_IRUGO | S_IWUSR);
1381MODULE_PARM_DESC(debug, "Debug enabled or not");