blob: 7d207d91a6a8859e2a93ce40824bbc35ff520534 [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.
194 * All these actions are reversed in serial_do_free().
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
213 retval = usb_autopm_get_interface(serial->interface);
214 if (retval)
215 goto error_get_interface;
Alan Sternf5b09532009-09-01 11:38:44 -0400216
217 /* If the termios setup has yet to be done */
218 if (tty->driver->termios[idx] == NULL) {
219 /* perform the standard setup */
220 retval = tty_init_termios(tty);
221 if (retval)
Alan Sterncc56cd02009-09-01 11:39:13 -0400222 goto error_init_termios;
Alan Sternf5b09532009-09-01 11:38:44 -0400223 /* allow the driver to update it */
Alan Sterncc56cd02009-09-01 11:39:13 -0400224 if (serial->type->init_termios)
225 serial->type->init_termios(tty);
Alan Sternf5b09532009-09-01 11:38:44 -0400226 }
Alan Sterncc56cd02009-09-01 11:39:13 -0400227 mutex_unlock(&serial->disc_mutex);
228
229 tty->driver_data = port;
230
Alan Sternf5b09532009-09-01 11:38:44 -0400231 /* Final install (we use the default method) */
232 tty_driver_kref_get(driver);
233 tty->count++;
234 driver->ttys[idx] = tty;
Alan Sterncc56cd02009-09-01 11:39:13 -0400235 return retval;
236
237 error_init_termios:
238 usb_autopm_put_interface(serial->interface);
239 error_get_interface:
240 module_put(serial->type->driver.owner);
241 error_module_get:
242 error_no_port:
243 usb_serial_put(serial);
244 mutex_unlock(&serial->disc_mutex);
245 return retval;
Alan Sternf5b09532009-09-01 11:38:44 -0400246}
247
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100248static int serial_open (struct tty_struct *tty, struct file *filp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249{
250 struct usb_serial *serial;
251 struct usb_serial_port *port;
Alan Stern2d931482009-04-14 11:31:02 -0400252 int retval = 0;
Alan Coxc56d3002009-07-28 00:34:58 +0100253 int first = 0;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100254
Harvey Harrison441b62c2008-03-03 16:08:34 -0800255 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256
Alan Sterncc56cd02009-09-01 11:39:13 -0400257 port = tty->driver_data;
258 serial = port->serial;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259
Alan Sterncc56cd02009-09-01 11:39:13 -0400260 if (mutex_lock_interruptible(&port->mutex))
261 return -ERESTARTSYS;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100262
Alan Cox95da3102008-07-22 11:09:07 +0100263 ++port->port.count;
Alan Cox4a90f092008-10-13 10:39:46 +0100264 tty_port_tty_set(&port->port, tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265
Jason Wessel6e406122009-06-22 11:32:20 -0500266 /* If the console is attached, the device is already open */
267 if (port->port.count == 1 && !port->console) {
Alan Coxc56d3002009-07-28 00:34:58 +0100268 first = 1;
Alan Stern2d931482009-04-14 11:31:02 -0400269 mutex_lock(&serial->disc_mutex);
Alan Stern2d931482009-04-14 11:31:02 -0400270
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100271 /* only call the device specific open if this
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 * is the first time the port is opened */
Alan Coxa509a7e2009-09-19 13:13:26 -0700273 retval = serial->type->open(tty, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 if (retval)
Alan Sterncc56cd02009-09-01 11:39:13 -0400275 goto bailout_module_put;
Alan Stern2d931482009-04-14 11:31:02 -0400276 mutex_unlock(&serial->disc_mutex);
Alan Coxc56d3002009-07-28 00:34:58 +0100277 set_bit(ASYNCB_INITIALIZED, &port->port.flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 }
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300279 mutex_unlock(&port->mutex);
Alan Cox335f8512009-06-11 12:26:29 +0100280 /* Now do the correct tty layer semantics */
281 retval = tty_port_block_til_ready(&port->port, tty, filp);
Alan Coxc56d3002009-07-28 00:34:58 +0100282 if (retval == 0) {
283 if (!first)
284 usb_serial_put(serial);
Alan Cox335f8512009-06-11 12:26:29 +0100285 return 0;
Alan Coxc56d3002009-07-28 00:34:58 +0100286 }
287 mutex_lock(&port->mutex);
288 if (first == 0)
289 goto bailout_mutex_unlock;
290 /* Undo the initial port actions */
291 mutex_lock(&serial->disc_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292bailout_module_put:
Alan Stern2d931482009-04-14 11:31:02 -0400293 mutex_unlock(&serial->disc_mutex);
Luiz Fernando Capitulino71a84162006-05-11 22:34:24 -0300294bailout_mutex_unlock:
Alan Cox95da3102008-07-22 11:09:07 +0100295 port->port.count = 0;
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300296 mutex_unlock(&port->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 return retval;
298}
299
Alan Cox335f8512009-06-11 12:26:29 +0100300/**
Alan Sternf5b09532009-09-01 11:38:44 -0400301 * serial_do_down - shut down hardware
302 * @port: port to shut down
Alan Cox335f8512009-06-11 12:26:29 +0100303 *
Alan Sternf5b09532009-09-01 11:38:44 -0400304 * Shut down a USB serial port unless it is the console. We never
305 * shut down the console hardware as it will always be in use.
Alan Cox335f8512009-06-11 12:26:29 +0100306 */
307static void serial_do_down(struct usb_serial_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308{
Alan Cox335f8512009-06-11 12:26:29 +0100309 struct usb_serial_driver *drv = port->serial->type;
Alan Stern2d931482009-04-14 11:31:02 -0400310 struct usb_serial *serial;
311 struct module *owner;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312
Alan Sternf5b09532009-09-01 11:38:44 -0400313 /*
314 * The console is magical. Do not hang up the console hardware
315 * or there will be tears.
316 */
Alan Cox335f8512009-06-11 12:26:29 +0100317 if (port->console)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 return;
319
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300320 mutex_lock(&port->mutex);
Alan Stern2d931482009-04-14 11:31:02 -0400321 serial = port->serial;
322 owner = serial->type->driver.owner;
Luiz Fernando Capitulino8a4613f2005-11-28 19:16:07 -0200323
Alan Cox335f8512009-06-11 12:26:29 +0100324 if (drv->close)
325 drv->close(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300327 mutex_unlock(&port->mutex);
Alan Cox335f8512009-06-11 12:26:29 +0100328}
329
Alan Sternf5b09532009-09-01 11:38:44 -0400330static void serial_hangup(struct tty_struct *tty)
Alan Cox335f8512009-06-11 12:26:29 +0100331{
Alan Cox4455e342009-09-19 13:13:24 -0700332 struct usb_serial_port *port = tty->driver_data;
Alan Sternf5b09532009-09-01 11:38:44 -0400333 serial_do_down(port);
334 tty_port_hangup(&port->port);
335 /* We must not free port yet - the USB serial layer depends on it's
336 continued existence */
Alan Cox335f8512009-06-11 12:26:29 +0100337}
338
339static void serial_close(struct tty_struct *tty, struct file *filp)
340{
341 struct usb_serial_port *port = tty->driver_data;
342
343 dbg("%s - port %d", __func__, port->number);
344
Alan Cox335f8512009-06-11 12:26:29 +0100345 if (tty_port_close_start(&port->port, tty, filp) == 0)
346 return;
Alan Sternf5b09532009-09-01 11:38:44 -0400347 serial_do_down(port);
Alan Cox335f8512009-06-11 12:26:29 +0100348 tty_port_close_end(&port->port, tty);
349 tty_port_tty_set(&port->port, NULL);
Alan Cox335f8512009-06-11 12:26:29 +0100350}
351
Alan Sternf5b09532009-09-01 11:38:44 -0400352/**
353 * serial_do_free - free resources post close/hangup
354 * @port: port to free up
355 *
356 * Do the resource freeing and refcount dropping for the port.
357 * Avoid freeing the console.
358 *
359 * Called when the last tty kref is dropped.
360 */
361static void serial_do_free(struct tty_struct *tty)
Alan Cox335f8512009-06-11 12:26:29 +0100362{
363 struct usb_serial_port *port = tty->driver_data;
Alan Sternf5b09532009-09-01 11:38:44 -0400364 struct usb_serial *serial;
365 struct module *owner;
366
367 /* The console is magical. Do not hang up the console hardware
368 * or there will be tears.
369 */
Alan Sterncc56cd02009-09-01 11:39:13 -0400370 if (port->console)
Alan Sternf5b09532009-09-01 11:38:44 -0400371 return;
372
Alan Sterncc56cd02009-09-01 11:39:13 -0400373 tty->driver_data = NULL;
374
Alan Sternf5b09532009-09-01 11:38:44 -0400375 serial = port->serial;
376 owner = serial->type->driver.owner;
377
378 mutex_lock(&serial->disc_mutex);
379 if (!serial->disconnected)
380 usb_autopm_put_interface(serial->interface);
381 mutex_unlock(&serial->disc_mutex);
382
383 usb_serial_put(serial);
384 module_put(owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385}
386
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100387static int serial_write(struct tty_struct *tty, const unsigned char *buf,
388 int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200390 struct usb_serial_port *port = tty->driver_data;
Oliver Neukum3ff4fd92007-01-13 07:32:27 +0100391 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392
Alan Coxf34d7a52008-04-30 00:54:13 -0700393 if (port->serial->dev->state == USB_STATE_NOTATTACHED)
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200394 goto exit;
395
Harvey Harrison441b62c2008-03-03 16:08:34 -0800396 dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397
Alan Cox95da3102008-07-22 11:09:07 +0100398 /* count is managed under the mutex lock for the tty so cannot
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100399 drop to zero until after the last close completes */
Alan Cox95da3102008-07-22 11:09:07 +0100400 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401
402 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100403 retval = port->serial->type->write(tty, port, buf, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404
405exit:
406 return retval;
407}
408
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100409static int serial_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200411 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800412 dbg("%s - port %d", __func__, port->number);
Alan Cox95da3102008-07-22 11:09:07 +0100413 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100415 return port->serial->type->write_room(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416}
417
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100418static int serial_chars_in_buffer(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200420 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800421 dbg("%s = port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422
Alan Coxeff69372009-01-02 13:47:06 +0000423 /* if the device was unplugged then any remaining characters
424 fell out of the connector ;) */
425 if (port->serial->disconnected)
426 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 /* pass on to the driver specific version of this function */
Alan Cox95da3102008-07-22 11:09:07 +0100428 return port->serial->type->chars_in_buffer(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429}
430
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100431static void serial_throttle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200433 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800434 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435
Alan Cox95da3102008-07-22 11:09:07 +0100436 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 /* pass on to the driver specific version of this function */
438 if (port->serial->type->throttle)
Alan Cox95da3102008-07-22 11:09:07 +0100439 port->serial->type->throttle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440}
441
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100442static void serial_unthrottle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200444 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800445 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446
Alan Cox95da3102008-07-22 11:09:07 +0100447 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 /* pass on to the driver specific version of this function */
449 if (port->serial->type->unthrottle)
Alan Cox95da3102008-07-22 11:09:07 +0100450 port->serial->type->unthrottle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451}
452
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100453static int serial_ioctl(struct tty_struct *tty, struct file *file,
454 unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200456 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457 int retval = -ENODEV;
458
Harvey Harrison441b62c2008-03-03 16:08:34 -0800459 dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460
Alan Cox95da3102008-07-22 11:09:07 +0100461 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100463 /* pass on to the driver specific version of this function
464 if it is available */
Alan Coxf34d7a52008-04-30 00:54:13 -0700465 if (port->serial->type->ioctl) {
Alan Cox95da3102008-07-22 11:09:07 +0100466 retval = port->serial->type->ioctl(tty, file, cmd, arg);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100467 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468 retval = -ENOIOCTLCMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 return retval;
470}
471
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100472static void serial_set_termios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200474 struct usb_serial_port *port = tty->driver_data;
Harvey Harrison441b62c2008-03-03 16:08:34 -0800475 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476
Alan Cox95da3102008-07-22 11:09:07 +0100477 WARN_ON(!port->port.count);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100478 /* pass on to the driver specific version of this function
479 if it is available */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480 if (port->serial->type->set_termios)
Alan Cox95da3102008-07-22 11:09:07 +0100481 port->serial->type->set_termios(tty, port, old);
Alan Cox33785092007-10-18 01:24:22 -0700482 else
483 tty_termios_copy_hw(tty->termios, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484}
485
Alan Cox9e989662008-07-22 11:18:03 +0100486static int serial_break(struct tty_struct *tty, int break_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200488 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489
Harvey Harrison441b62c2008-03-03 16:08:34 -0800490 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491
Alan Cox95da3102008-07-22 11:09:07 +0100492 WARN_ON(!port->port.count);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100493 /* pass on to the driver specific version of this function
494 if it is available */
Alan Cox6b447f042009-01-02 13:48:56 +0000495 if (port->serial->type->break_ctl)
Alan Cox95da3102008-07-22 11:09:07 +0100496 port->serial->type->break_ctl(tty, break_state);
Alan Cox9e989662008-07-22 11:18:03 +0100497 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498}
499
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700500static int serial_proc_show(struct seq_file *m, void *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501{
502 struct usb_serial *serial;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 char tmp[40];
505
Harvey Harrison441b62c2008-03-03 16:08:34 -0800506 dbg("%s", __func__);
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700507 seq_puts(m, "usbserinfo:1.0 driver:2.0\n");
508 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 serial = usb_serial_get_by_index(i);
510 if (serial == NULL)
511 continue;
512
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700513 seq_printf(m, "%d:", i);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700514 if (serial->type->driver.owner)
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700515 seq_printf(m, " module:%s",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100516 module_name(serial->type->driver.owner));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700517 seq_printf(m, " name:\"%s\"",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100518 serial->type->description);
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700519 seq_printf(m, " vendor:%04x product:%04x",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100520 le16_to_cpu(serial->dev->descriptor.idVendor),
521 le16_to_cpu(serial->dev->descriptor.idProduct));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700522 seq_printf(m, " num_ports:%d", serial->num_ports);
523 seq_printf(m, " port:%d", i - serial->minor + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 usb_make_path(serial->dev, tmp, sizeof(tmp));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700525 seq_printf(m, " path:%s", tmp);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100526
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700527 seq_putc(m, '\n');
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200528 usb_serial_put(serial);
Alan Stern8bc2c1b2009-09-01 11:38:59 -0400529 mutex_unlock(&serial->disc_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 }
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700531 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532}
533
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700534static int serial_proc_open(struct inode *inode, struct file *file)
535{
536 return single_open(file, serial_proc_show, NULL);
537}
538
539static const struct file_operations serial_proc_fops = {
540 .owner = THIS_MODULE,
541 .open = serial_proc_open,
542 .read = seq_read,
543 .llseek = seq_lseek,
544 .release = single_release,
545};
546
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100547static int serial_tiocmget(struct tty_struct *tty, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200549 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550
Harvey Harrison441b62c2008-03-03 16:08:34 -0800551 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552
Alan Cox95da3102008-07-22 11:09:07 +0100553 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 if (port->serial->type->tiocmget)
Alan Cox95da3102008-07-22 11:09:07 +0100555 return port->serial->type->tiocmget(tty, file);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556 return -EINVAL;
557}
558
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100559static int serial_tiocmset(struct tty_struct *tty, struct file *file,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 unsigned int set, unsigned int clear)
561{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200562 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563
Harvey Harrison441b62c2008-03-03 16:08:34 -0800564 dbg("%s - port %d", __func__, port->number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565
Alan Cox95da3102008-07-22 11:09:07 +0100566 WARN_ON(!port->port.count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567 if (port->serial->type->tiocmset)
Alan Cox95da3102008-07-22 11:09:07 +0100568 return port->serial->type->tiocmset(tty, file, set, clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 return -EINVAL;
570}
571
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700572/*
573 * We would be calling tty_wakeup here, but unfortunately some line
574 * disciplines have an annoying habit of calling tty->write from
575 * the write wakeup callback (e.g. n_hdlc.c).
576 */
577void usb_serial_port_softint(struct usb_serial_port *port)
578{
579 schedule_work(&port->work);
580}
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100581EXPORT_SYMBOL_GPL(usb_serial_port_softint);
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700582
David Howellsc4028952006-11-22 14:57:56 +0000583static void usb_serial_port_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584{
David Howellsc4028952006-11-22 14:57:56 +0000585 struct usb_serial_port *port =
586 container_of(work, struct usb_serial_port, work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587 struct tty_struct *tty;
588
Harvey Harrison441b62c2008-03-03 16:08:34 -0800589 dbg("%s - port %d", __func__, port->number);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100590
Alan Cox4a90f092008-10-13 10:39:46 +0100591 tty = tty_port_tty_get(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592 if (!tty)
593 return;
594
595 tty_wakeup(tty);
Alan Cox4a90f092008-10-13 10:39:46 +0100596 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597}
598
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100599static void kill_traffic(struct usb_serial_port *port)
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700600{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602 usb_kill_urb(port->write_urb);
Oliver Neukum5adceac2007-08-17 14:01:38 +0200603 /*
604 * This is tricky.
605 * Some drivers submit the read_urb in the
606 * handler for the write_urb or vice versa
607 * this order determines the order in which
608 * usb_kill_urb() must be used to reliably
609 * kill the URBs. As it is unknown here,
610 * both orders must be used in turn.
611 * The call below is not redundant.
612 */
613 usb_kill_urb(port->read_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 usb_kill_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 usb_kill_urb(port->interrupt_out_urb);
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100616}
617
Alan Stern41bd34d2009-09-01 11:38:34 -0400618static void port_release(struct device *dev)
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100619{
Alan Stern41bd34d2009-09-01 11:38:34 -0400620 struct usb_serial_port *port = to_usb_serial_port(dev);
621
622 dbg ("%s - %s", __func__, dev_name(dev));
623
Alan Stern2d931482009-04-14 11:31:02 -0400624 /*
625 * Stop all the traffic before cancelling the work, so that
626 * nobody will restart it by calling usb_serial_port_softint.
627 */
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100628 kill_traffic(port);
Alan Stern2d931482009-04-14 11:31:02 -0400629 cancel_work_sync(&port->work);
630
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100631 usb_free_urb(port->read_urb);
632 usb_free_urb(port->write_urb);
633 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 usb_free_urb(port->interrupt_out_urb);
635 kfree(port->bulk_in_buffer);
636 kfree(port->bulk_out_buffer);
637 kfree(port->interrupt_in_buffer);
638 kfree(port->interrupt_out_buffer);
639 kfree(port);
640}
641
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100642static struct usb_serial *create_serial(struct usb_device *dev,
643 struct usb_interface *interface,
644 struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645{
646 struct usb_serial *serial;
647
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100648 serial = kzalloc(sizeof(*serial), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649 if (!serial) {
Harvey Harrison441b62c2008-03-03 16:08:34 -0800650 dev_err(&dev->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651 return NULL;
652 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 serial->dev = usb_get_dev(dev);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700654 serial->type = driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655 serial->interface = interface;
656 kref_init(&serial->kref);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +0100657 mutex_init(&serial->disc_mutex);
Alan Stern0282b7f2008-07-29 12:01:04 -0400658 serial->minor = SERIAL_TTY_NO_MINOR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659
660 return serial;
661}
662
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100663static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf,
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100664 struct usb_serial_driver *drv)
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100665{
666 struct usb_dynid *dynid;
667
668 spin_lock(&drv->dynids.lock);
669 list_for_each_entry(dynid, &drv->dynids.list, node) {
670 if (usb_match_one_id(intf, &dynid->id)) {
671 spin_unlock(&drv->dynids.lock);
672 return &dynid->id;
673 }
674 }
675 spin_unlock(&drv->dynids.lock);
676 return NULL;
677}
678
679static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv,
680 struct usb_interface *intf)
681{
682 const struct usb_device_id *id;
683
684 id = usb_match_id(intf, drv->id_table);
685 if (id) {
686 dbg("static descriptor matches");
687 goto exit;
688 }
689 id = match_dynamic_id(intf, drv);
690 if (id)
691 dbg("dynamic descriptor matches");
692exit:
693 return id;
694}
695
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100696static struct usb_serial_driver *search_serial_device(
697 struct usb_interface *iface)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699 const struct usb_device_id *id;
Alan Stern063a2da2007-10-10 16:24:06 -0400700 struct usb_serial_driver *drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701
Adrian Bunk93b1fae2006-01-10 00:13:33 +0100702 /* Check if the usb id matches a known device */
Alan Stern063a2da2007-10-10 16:24:06 -0400703 list_for_each_entry(drv, &usb_serial_driver_list, driver_list) {
704 id = get_iface_id(drv, iface);
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100705 if (id)
Alan Stern063a2da2007-10-10 16:24:06 -0400706 return drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707 }
708
709 return NULL;
710}
711
Alan Cox335f8512009-06-11 12:26:29 +0100712static int serial_carrier_raised(struct tty_port *port)
713{
714 struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
715 struct usb_serial_driver *drv = p->serial->type;
716 if (drv->carrier_raised)
717 return drv->carrier_raised(p);
718 /* No carrier control - don't block */
719 return 1;
720}
721
722static void serial_dtr_rts(struct tty_port *port, int on)
723{
724 struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
725 struct usb_serial_driver *drv = p->serial->type;
726 if (drv->dtr_rts)
727 drv->dtr_rts(p, on);
728}
729
730static const struct tty_port_operations serial_port_ops = {
731 .carrier_raised = serial_carrier_raised,
732 .dtr_rts = serial_dtr_rts,
733};
734
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735int usb_serial_probe(struct usb_interface *interface,
736 const struct usb_device_id *id)
737{
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100738 struct usb_device *dev = interface_to_usbdev(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 struct usb_serial *serial = NULL;
740 struct usb_serial_port *port;
741 struct usb_host_interface *iface_desc;
742 struct usb_endpoint_descriptor *endpoint;
743 struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS];
744 struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS];
745 struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];
746 struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700747 struct usb_serial_driver *type = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 int retval;
Andre Hauptdd9ca5d2008-06-18 15:56:00 +0200749 unsigned int minor;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 int buffer_size;
751 int i;
752 int num_interrupt_in = 0;
753 int num_interrupt_out = 0;
754 int num_bulk_in = 0;
755 int num_bulk_out = 0;
756 int num_ports = 0;
757 int max_endpoints;
758
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100759 lock_kernel(); /* guard against unloading a serial driver module */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 type = search_serial_device(interface);
761 if (!type) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100762 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 dbg("none matched");
764 return -ENODEV;
765 }
766
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100767 serial = create_serial(dev, interface, type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 if (!serial) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100769 unlock_kernel();
Harvey Harrison441b62c2008-03-03 16:08:34 -0800770 dev_err(&interface->dev, "%s - out of memory\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 return -ENOMEM;
772 }
773
774 /* if this device type has a probe function, call it */
775 if (type->probe) {
776 const struct usb_device_id *id;
777
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700778 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100779 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100780 dev_err(&interface->dev,
781 "module get failed, exiting\n");
782 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 return -EIO;
784 }
785
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100786 id = get_iface_id(type, interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 retval = type->probe(serial, id);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700788 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789
790 if (retval) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100791 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100792 dbg("sub driver rejected device");
793 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 return retval;
795 }
796 }
797
798 /* descriptor matches, let's find the endpoints needed */
799 /* check out the endpoints */
800 iface_desc = interface->cur_altsetting;
801 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
802 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700803
804 if (usb_endpoint_is_bulk_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 /* we found a bulk in endpoint */
806 dbg("found bulk in on endpoint %d", i);
807 bulk_in_endpoint[num_bulk_in] = endpoint;
808 ++num_bulk_in;
809 }
810
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700811 if (usb_endpoint_is_bulk_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 /* we found a bulk out endpoint */
813 dbg("found bulk out on endpoint %d", i);
814 bulk_out_endpoint[num_bulk_out] = endpoint;
815 ++num_bulk_out;
816 }
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700817
818 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 /* we found a interrupt in endpoint */
820 dbg("found interrupt in on endpoint %d", i);
821 interrupt_in_endpoint[num_interrupt_in] = endpoint;
822 ++num_interrupt_in;
823 }
824
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700825 if (usb_endpoint_is_int_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826 /* we found an interrupt out endpoint */
827 dbg("found interrupt out on endpoint %d", i);
828 interrupt_out_endpoint[num_interrupt_out] = endpoint;
829 ++num_interrupt_out;
830 }
831 }
832
833#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100834 /* BEGIN HORRIBLE HACK FOR PL2303 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 /* this is needed due to the looney way its endpoints are set up */
836 if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&
837 (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||
838 ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) &&
Johannes Steingraeber8fd80132006-09-16 16:17:34 +0200839 (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) ||
840 ((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) &&
Andreas Bombece816cf2008-09-14 01:58:55 +0200841 (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID)) ||
842 ((le16_to_cpu(dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) &&
843 (le16_to_cpu(dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_EF81))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 if (interface != dev->actconfig->interface[0]) {
845 /* check out the endpoints of the other interface*/
846 iface_desc = dev->actconfig->interface[0]->cur_altsetting;
847 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
848 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700849 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 /* we found a interrupt in endpoint */
851 dbg("found interrupt in for Prolific device on separate interface");
852 interrupt_in_endpoint[num_interrupt_in] = endpoint;
853 ++num_interrupt_in;
854 }
855 }
856 }
857
858 /* Now make sure the PL-2303 is configured correctly.
859 * If not, give up now and hope this hack will work
860 * properly during a later invocation of usb_serial_probe
861 */
862 if (num_bulk_in == 0 || num_bulk_out == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100863 unlock_kernel();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100865 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 return -ENODEV;
867 }
868 }
869 /* END HORRIBLE HACK FOR PL2303 */
870#endif
871
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872#ifdef CONFIG_USB_SERIAL_GENERIC
873 if (type == &usb_serial_generic_device) {
874 num_ports = num_bulk_out;
875 if (num_ports == 0) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100876 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100877 dev_err(&interface->dev,
878 "Generic device with no bulk out, not allowed.\n");
879 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 return -EIO;
881 }
882 }
883#endif
884 if (!num_ports) {
885 /* if this device type has a calc_num_ports function, call it */
886 if (type->calc_num_ports) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700887 if (!try_module_get(type->driver.owner)) {
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100888 unlock_kernel();
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100889 dev_err(&interface->dev,
890 "module get failed, exiting\n");
891 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 return -EIO;
893 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100894 num_ports = type->calc_num_ports(serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700895 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 }
897 if (!num_ports)
898 num_ports = type->num_ports;
899 }
900
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 serial->num_ports = num_ports;
902 serial->num_bulk_in = num_bulk_in;
903 serial->num_bulk_out = num_bulk_out;
904 serial->num_interrupt_in = num_interrupt_in;
905 serial->num_interrupt_out = num_interrupt_out;
906
Alan Stern063a2da2007-10-10 16:24:06 -0400907 /* found all that we need */
908 dev_info(&interface->dev, "%s converter detected\n",
909 type->description);
910
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 /* create our ports, we need as many as the max endpoints */
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100912 /* we don't use num_ports here because some devices have more
913 endpoint pairs than ports */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 max_endpoints = max(num_bulk_in, num_bulk_out);
915 max_endpoints = max(max_endpoints, num_interrupt_in);
916 max_endpoints = max(max_endpoints, num_interrupt_out);
917 max_endpoints = max(max_endpoints, (int)serial->num_ports);
918 serial->num_port_pointers = max_endpoints;
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100919 unlock_kernel();
920
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100921 dbg("%s - setting up %d port structures for this device",
922 __func__, max_endpoints);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923 for (i = 0; i < max_endpoints; ++i) {
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100924 port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 if (!port)
926 goto probe_error;
Alan Cox4a90f092008-10-13 10:39:46 +0100927 tty_port_init(&port->port);
Alan Cox335f8512009-06-11 12:26:29 +0100928 port->port.ops = &serial_port_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 port->serial = serial;
Greg Kroah-Hartman507ca9b2005-04-23 12:49:16 -0700930 spin_lock_init(&port->lock);
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -0300931 mutex_init(&port->mutex);
David Howellsc4028952006-11-22 14:57:56 +0000932 INIT_WORK(&port->work, usb_serial_port_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 serial->port[i] = port;
Alan Stern41bd34d2009-09-01 11:38:34 -0400934 port->dev.parent = &interface->dev;
935 port->dev.driver = NULL;
936 port->dev.bus = &usb_serial_bus_type;
937 port->dev.release = &port_release;
938 device_initialize(&port->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939 }
940
941 /* set up the endpoint information */
942 for (i = 0; i < num_bulk_in; ++i) {
943 endpoint = bulk_in_endpoint[i];
944 port = serial->port[i];
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100945 port->read_urb = usb_alloc_urb(0, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 if (!port->read_urb) {
947 dev_err(&interface->dev, "No free urbs available\n");
948 goto probe_error;
949 }
950 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
951 port->bulk_in_size = buffer_size;
952 port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100953 port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 if (!port->bulk_in_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100955 dev_err(&interface->dev,
956 "Couldn't allocate bulk_in_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 goto probe_error;
958 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100959 usb_fill_bulk_urb(port->read_urb, dev,
960 usb_rcvbulkpipe(dev,
961 endpoint->bEndpointAddress),
962 port->bulk_in_buffer, buffer_size,
963 serial->type->read_bulk_callback, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964 }
965
966 for (i = 0; i < num_bulk_out; ++i) {
967 endpoint = bulk_out_endpoint[i];
968 port = serial->port[i];
969 port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
970 if (!port->write_urb) {
971 dev_err(&interface->dev, "No free urbs available\n");
972 goto probe_error;
973 }
974 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
975 port->bulk_out_size = buffer_size;
976 port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100977 port->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 if (!port->bulk_out_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100979 dev_err(&interface->dev,
980 "Couldn't allocate bulk_out_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 goto probe_error;
982 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100983 usb_fill_bulk_urb(port->write_urb, dev,
984 usb_sndbulkpipe(dev,
985 endpoint->bEndpointAddress),
986 port->bulk_out_buffer, buffer_size,
987 serial->type->write_bulk_callback, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 }
989
990 if (serial->type->read_int_callback) {
991 for (i = 0; i < num_interrupt_in; ++i) {
992 endpoint = interrupt_in_endpoint[i];
993 port = serial->port[i];
994 port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
995 if (!port->interrupt_in_urb) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100996 dev_err(&interface->dev,
997 "No free urbs available\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 goto probe_error;
999 }
1000 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001001 port->interrupt_in_endpointAddress =
1002 endpoint->bEndpointAddress;
1003 port->interrupt_in_buffer = kmalloc(buffer_size,
1004 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005 if (!port->interrupt_in_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001006 dev_err(&interface->dev,
1007 "Couldn't allocate interrupt_in_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 goto probe_error;
1009 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001010 usb_fill_int_urb(port->interrupt_in_urb, dev,
1011 usb_rcvintpipe(dev,
1012 endpoint->bEndpointAddress),
1013 port->interrupt_in_buffer, buffer_size,
1014 serial->type->read_int_callback, port,
1015 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 }
1017 } else if (num_interrupt_in) {
1018 dbg("the device claims to support interrupt in transfers, but read_int_callback is not defined");
1019 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001020
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 if (serial->type->write_int_callback) {
1022 for (i = 0; i < num_interrupt_out; ++i) {
1023 endpoint = interrupt_out_endpoint[i];
1024 port = serial->port[i];
1025 port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
1026 if (!port->interrupt_out_urb) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001027 dev_err(&interface->dev,
1028 "No free urbs available\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 goto probe_error;
1030 }
1031 buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
1032 port->interrupt_out_size = buffer_size;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001033 port->interrupt_out_endpointAddress =
1034 endpoint->bEndpointAddress;
1035 port->interrupt_out_buffer = kmalloc(buffer_size,
1036 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 if (!port->interrupt_out_buffer) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001038 dev_err(&interface->dev,
1039 "Couldn't allocate interrupt_out_buffer\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 goto probe_error;
1041 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001042 usb_fill_int_urb(port->interrupt_out_urb, dev,
1043 usb_sndintpipe(dev,
1044 endpoint->bEndpointAddress),
1045 port->interrupt_out_buffer, buffer_size,
1046 serial->type->write_int_callback, port,
1047 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 }
1049 } else if (num_interrupt_out) {
1050 dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined");
1051 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001052
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 /* if this device type has an attach function, call it */
1054 if (type->attach) {
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -07001055 if (!try_module_get(type->driver.owner)) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001056 dev_err(&interface->dev,
1057 "module get failed, exiting\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 goto probe_error;
1059 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001060 retval = type->attach(serial);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -07001061 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 if (retval < 0)
1063 goto probe_error;
1064 if (retval > 0) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001065 /* quietly accept this device, but don't bind to a
1066 serial port as it's about to disappear */
Alan Stern0a3c8542009-05-27 11:25:52 -04001067 serial->num_ports = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 goto exit;
1069 }
1070 }
1071
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001072 if (get_free_serial(serial, num_ports, &minor) == NULL) {
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001073 dev_err(&interface->dev, "No more free serial devices\n");
1074 goto probe_error;
1075 }
Oliver Neukumc744f992007-02-26 15:43:00 +01001076 serial->minor = minor;
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001077
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078 /* register all of the individual ports with the driver core */
1079 for (i = 0; i < num_ports; ++i) {
1080 port = serial->port[i];
Kay Sievers0031a062008-05-02 06:02:41 +02001081 dev_set_name(&port->dev, "ttyUSB%d", port->number);
Kay Sievers7071a3c2008-05-02 06:02:41 +02001082 dbg ("%s - registering %s", __func__, dev_name(&port->dev));
Alan Sternc706ebd2009-06-02 11:54:11 -04001083 port->dev_state = PORT_REGISTERING;
Alan Stern41bd34d2009-09-01 11:38:34 -04001084 retval = device_add(&port->dev);
Alan Sternc706ebd2009-06-02 11:54:11 -04001085 if (retval) {
Greg Kroah-Hartman13f4db92006-08-28 11:43:25 -07001086 dev_err(&port->dev, "Error registering port device, "
1087 "continuing\n");
Alan Sternc706ebd2009-06-02 11:54:11 -04001088 port->dev_state = PORT_UNREGISTERED;
1089 } else {
1090 port->dev_state = PORT_REGISTERED;
1091 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 }
1093
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001094 usb_serial_console_init(debug, minor);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095
1096exit:
1097 /* success */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001098 usb_set_intfdata(interface, serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099 return 0;
1100
1101probe_error:
Alan Stern41bd34d2009-09-01 11:38:34 -04001102 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 return -EIO;
1104}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001105EXPORT_SYMBOL_GPL(usb_serial_probe);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106
1107void usb_serial_disconnect(struct usb_interface *interface)
1108{
1109 int i;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001110 struct usb_serial *serial = usb_get_intfdata(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 struct device *dev = &interface->dev;
1112 struct usb_serial_port *port;
1113
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +02001114 usb_serial_console_disconnect(serial);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001115 dbg("%s", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001117 mutex_lock(&serial->disc_mutex);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001118 usb_set_intfdata(interface, NULL);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001119 /* must set a flag, to signal subdrivers */
1120 serial->disconnected = 1;
Alan Stern2d931482009-04-14 11:31:02 -04001121 mutex_unlock(&serial->disc_mutex);
1122
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001123 for (i = 0; i < serial->num_ports; ++i) {
1124 port = serial->port[i];
1125 if (port) {
Alan Cox4a90f092008-10-13 10:39:46 +01001126 struct tty_struct *tty = tty_port_tty_get(&port->port);
1127 if (tty) {
Alan Coxd2b39182009-09-19 13:13:23 -07001128 tty_vhangup(tty);
Alan Cox4a90f092008-10-13 10:39:46 +01001129 tty_kref_put(tty);
1130 }
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001131 kill_traffic(port);
Alan Stern2d931482009-04-14 11:31:02 -04001132 cancel_work_sync(&port->work);
Alan Sternc706ebd2009-06-02 11:54:11 -04001133 if (port->dev_state == PORT_REGISTERED) {
1134
1135 /* Make sure the port is bound so that the
1136 * driver's port_remove method is called.
1137 */
1138 if (!port->dev.driver) {
1139 int rc;
1140
1141 port->dev.driver =
1142 &serial->type->driver;
1143 rc = device_bind_driver(&port->dev);
1144 }
1145 port->dev_state = PORT_UNREGISTERING;
1146 device_del(&port->dev);
1147 port->dev_state = PORT_UNREGISTERED;
1148 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 }
Alan Sternf9c99bb2009-06-02 11:53:55 -04001151 serial->type->disconnect(serial);
Alan Stern2d931482009-04-14 11:31:02 -04001152
Alan Stern41bd34d2009-09-01 11:38:34 -04001153 /* let the last holder of this object cause it to be cleaned up */
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001154 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 dev_info(dev, "device disconnected\n");
1156}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001157EXPORT_SYMBOL_GPL(usb_serial_disconnect);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158
Oliver Neukumec225592007-04-27 20:54:57 +02001159int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
1160{
1161 struct usb_serial *serial = usb_get_intfdata(intf);
1162 struct usb_serial_port *port;
1163 int i, r = 0;
1164
Oliver Neukumf8bece82009-02-05 16:54:25 +01001165 serial->suspending = 1;
1166
Oliver Neukume31c1882007-07-23 08:58:39 +02001167 for (i = 0; i < serial->num_ports; ++i) {
1168 port = serial->port[i];
1169 if (port)
1170 kill_traffic(port);
Oliver Neukumec225592007-04-27 20:54:57 +02001171 }
1172
1173 if (serial->type->suspend)
Oliver Neukume31c1882007-07-23 08:58:39 +02001174 r = serial->type->suspend(serial, message);
Oliver Neukumec225592007-04-27 20:54:57 +02001175
1176 return r;
1177}
1178EXPORT_SYMBOL(usb_serial_suspend);
1179
1180int usb_serial_resume(struct usb_interface *intf)
1181{
1182 struct usb_serial *serial = usb_get_intfdata(intf);
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001183 int rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001184
Oliver Neukumf8bece82009-02-05 16:54:25 +01001185 serial->suspending = 0;
Sarah Sharp8abaee22007-10-25 10:58:43 -07001186 if (serial->type->resume)
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001187 rv = serial->type->resume(serial);
1188 else
1189 rv = usb_serial_generic_resume(serial);
Oliver Neukumf8bece82009-02-05 16:54:25 +01001190
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001191 return rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001192}
1193EXPORT_SYMBOL(usb_serial_resume);
1194
Jeff Dikeb68e31d2006-10-02 02:17:18 -07001195static const struct tty_operations serial_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196 .open = serial_open,
1197 .close = serial_close,
1198 .write = serial_write,
Alan Cox335f8512009-06-11 12:26:29 +01001199 .hangup = serial_hangup,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 .write_room = serial_write_room,
1201 .ioctl = serial_ioctl,
1202 .set_termios = serial_set_termios,
1203 .throttle = serial_throttle,
1204 .unthrottle = serial_unthrottle,
1205 .break_ctl = serial_break,
1206 .chars_in_buffer = serial_chars_in_buffer,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207 .tiocmget = serial_tiocmget,
1208 .tiocmset = serial_tiocmset,
Alan Coxfe1ae7f2009-09-19 13:13:33 -07001209 .shutdown = serial_do_free,
1210 .install = serial_install,
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -07001211 .proc_fops = &serial_proc_fops,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212};
1213
Alan Cox335f8512009-06-11 12:26:29 +01001214
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215struct tty_driver *usb_serial_tty_driver;
1216
1217static int __init usb_serial_init(void)
1218{
1219 int i;
1220 int result;
1221
1222 usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS);
1223 if (!usb_serial_tty_driver)
1224 return -ENOMEM;
1225
1226 /* Initialize our global data */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001227 for (i = 0; i < SERIAL_TTY_MINORS; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 serial_table[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229
1230 result = bus_register(&usb_serial_bus_type);
1231 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001232 printk(KERN_ERR "usb-serial: %s - registering bus driver "
1233 "failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 goto exit_bus;
1235 }
1236
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237 usb_serial_tty_driver->owner = THIS_MODULE;
1238 usb_serial_tty_driver->driver_name = "usbserial";
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239 usb_serial_tty_driver->name = "ttyUSB";
1240 usb_serial_tty_driver->major = SERIAL_TTY_MAJOR;
1241 usb_serial_tty_driver->minor_start = 0;
1242 usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
1243 usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001244 usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW |
1245 TTY_DRIVER_DYNAMIC_DEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246 usb_serial_tty_driver->init_termios = tty_std_termios;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001247 usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD
1248 | HUPCL | CLOCAL;
Alan Coxa5b6f602008-04-08 17:16:06 +01001249 usb_serial_tty_driver->init_termios.c_ispeed = 9600;
1250 usb_serial_tty_driver->init_termios.c_ospeed = 9600;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 tty_set_operations(usb_serial_tty_driver, &serial_ops);
1252 result = tty_register_driver(usb_serial_tty_driver);
1253 if (result) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001254 printk(KERN_ERR "usb-serial: %s - tty_register_driver failed\n",
1255 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 goto exit_reg_driver;
1257 }
1258
1259 /* register the USB driver */
1260 result = usb_register(&usb_serial_driver);
1261 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001262 printk(KERN_ERR "usb-serial: %s - usb_register failed\n",
1263 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264 goto exit_tty;
1265 }
1266
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001267 /* register the generic driver, if we should */
1268 result = usb_serial_generic_register(debug);
1269 if (result < 0) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001270 printk(KERN_ERR "usb-serial: %s - registering generic "
1271 "driver failed\n", __func__);
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001272 goto exit_generic;
1273 }
1274
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001275 printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276
1277 return result;
1278
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001279exit_generic:
1280 usb_deregister(&usb_serial_driver);
1281
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282exit_tty:
1283 tty_unregister_driver(usb_serial_tty_driver);
1284
1285exit_reg_driver:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 bus_unregister(&usb_serial_bus_type);
1287
1288exit_bus:
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001289 printk(KERN_ERR "usb-serial: %s - returning with error %d\n",
1290 __func__, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 put_tty_driver(usb_serial_tty_driver);
1292 return result;
1293}
1294
1295
1296static void __exit usb_serial_exit(void)
1297{
1298 usb_serial_console_exit();
1299
1300 usb_serial_generic_deregister();
1301
1302 usb_deregister(&usb_serial_driver);
1303 tty_unregister_driver(usb_serial_tty_driver);
1304 put_tty_driver(usb_serial_tty_driver);
1305 bus_unregister(&usb_serial_bus_type);
1306}
1307
1308
1309module_init(usb_serial_init);
1310module_exit(usb_serial_exit);
1311
1312#define set_to_generic_if_null(type, function) \
1313 do { \
1314 if (!type->function) { \
1315 type->function = usb_serial_generic_##function; \
1316 dbg("Had to override the " #function \
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001317 " usb serial operation with the generic one.");\
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318 } \
1319 } while (0)
1320
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001321static void fixup_generic(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322{
1323 set_to_generic_if_null(device, open);
1324 set_to_generic_if_null(device, write);
1325 set_to_generic_if_null(device, close);
1326 set_to_generic_if_null(device, write_room);
1327 set_to_generic_if_null(device, chars_in_buffer);
1328 set_to_generic_if_null(device, read_bulk_callback);
1329 set_to_generic_if_null(device, write_bulk_callback);
Alan Sternf9c99bb2009-06-02 11:53:55 -04001330 set_to_generic_if_null(device, disconnect);
1331 set_to_generic_if_null(device, release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332}
1333
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001334int usb_serial_register(struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001336 /* must be called with BKL held */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337 int retval;
1338
Dave Younge4abe662009-02-14 21:21:13 +08001339 if (usb_disabled())
1340 return -ENODEV;
1341
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001342 fixup_generic(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001344 if (!driver->description)
1345 driver->description = driver->driver.name;
1346
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 /* Add this device to our list of devices */
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001348 list_add(&driver->driver_list, &usb_serial_driver_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001350 retval = usb_serial_bus_register(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 if (retval) {
Greg Kroah-Hartman194343d2008-08-20 16:56:34 -07001352 printk(KERN_ERR "usb-serial: problem %d when registering "
1353 "driver %s\n", retval, driver->description);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001354 list_del(&driver->driver_list);
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001355 } else
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001356 printk(KERN_INFO "USB Serial support registered for %s\n",
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001357 driver->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358
1359 return retval;
1360}
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001361EXPORT_SYMBOL_GPL(usb_serial_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362
1363
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001364void usb_serial_deregister(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365{
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001366 /* must be called with BKL held */
Greg Kroah-Hartmanc197a8d2008-08-18 13:21:04 -07001367 printk(KERN_INFO "USB Serial deregistering driver %s\n",
1368 device->description);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369 list_del(&device->driver_list);
1370 usb_serial_bus_deregister(device);
1371}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372EXPORT_SYMBOL_GPL(usb_serial_deregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373
1374/* Module information */
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001375MODULE_AUTHOR(DRIVER_AUTHOR);
1376MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377MODULE_LICENSE("GPL");
1378
1379module_param(debug, bool, S_IRUGO | S_IWUSR);
1380MODULE_PARM_DESC(debug, "Debug enabled or not");