blob: d213cf44a7e45ef8ae692bf4a9e63d31088cae8b [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * USB Serial Converter driver
3 *
Johan Hovold659597b2013-03-21 12:37:51 +01004 * Copyright (C) 2009 - 2013 Johan Hovold (jhovold@gmail.com)
Greg Kroah-Hartman71863642012-05-15 15:40:00 -07005 * Copyright (C) 1999 - 2012 Greg Kroah-Hartman (greg@kroah.com)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006 * Copyright (C) 2000 Peter Berger (pberger@brimson.com)
7 * Copyright (C) 2000 Al Borchers (borchers@steinerpoint.com)
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License version
11 * 2 as published by the Free Software Foundation.
12 *
Greg Kroah-Hartman502b95c2005-06-20 21:15:16 -070013 * This driver was originally based on the ACM driver by Armin Fuerst (which was
Linus Torvalds1da177e2005-04-16 15:20:36 -070014 * based on a driver by Brad Keryan)
15 *
Alan Coxa8d6f0a2008-07-22 11:12:24 +010016 * See Documentation/usb/usb-serial.txt for more information on using this
17 * driver
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 */
19
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -070020#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
21
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include <linux/kernel.h>
23#include <linux/errno.h>
24#include <linux/init.h>
25#include <linux/slab.h>
26#include <linux/tty.h>
27#include <linux/tty_driver.h>
28#include <linux/tty_flip.h>
29#include <linux/module.h>
30#include <linux/moduleparam.h>
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -070031#include <linux/seq_file.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include <linux/spinlock.h>
Luiz Fernando Capitulino1ce7dd22006-03-24 17:12:31 -030033#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include <linux/list.h>
Alan Coxa8d6f0a2008-07-22 11:12:24 +010035#include <linux/uaccess.h>
Alan Coxc56d3002009-07-28 00:34:58 +010036#include <linux/serial.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include <linux/usb.h>
Greg Kroah-Hartmana9698882006-07-11 21:22:58 -070038#include <linux/usb/serial.h>
David VomLehn8e8dce02009-08-28 12:54:27 -070039#include <linux/kfifo.h>
Greg Kroah-Hartmane5b1e202013-06-07 11:04:28 -070040#include <linux/idr.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include "pl2303.h"
42
Greg Kroah-Hartmanee42f6c2012-09-18 17:10:29 +010043#define DRIVER_AUTHOR "Greg Kroah-Hartman <gregkh@linuxfoundation.org>"
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#define DRIVER_DESC "USB Serial Driver core"
45
Greg Kroah-Hartman455b4f72013-06-06 10:31:35 -070046#define USB_SERIAL_TTY_MAJOR 188
47#define USB_SERIAL_TTY_MINORS 512 /* should be enough for a while */
48
Linus Torvalds1da177e2005-04-16 15:20:36 -070049/* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead
50 the MODULE_DEVICE_TABLE declarations in each serial driver
51 cause the "hotplug" program to pull in whatever module is necessary
52 via modprobe, and modprobe will load usbserial because the serial
53 drivers depend on it.
54*/
55
Greg Kroah-Hartmane5b1e202013-06-07 11:04:28 -070056static DEFINE_IDR(serial_minors);
Oliver Neukum3ddad822007-07-24 15:13:42 +020057static DEFINE_MUTEX(table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070058static LIST_HEAD(usb_serial_driver_list);
59
Alan Stern8bc2c1b2009-09-01 11:38:59 -040060/*
Greg Kroah-Hartmane5b1e202013-06-07 11:04:28 -070061 * Look up the serial port structure. If it is found and it hasn't been
62 * disconnected, return with the parent usb_serial structure's disc_mutex held
63 * and its refcount incremented. Otherwise return NULL.
Alan Stern8bc2c1b2009-09-01 11:38:59 -040064 */
Greg Kroah-Hartmane5b1e202013-06-07 11:04:28 -070065struct usb_serial_port *usb_serial_port_get_by_minor(unsigned minor)
Linus Torvalds1da177e2005-04-16 15:20:36 -070066{
Oliver Neukum34ef50e2007-01-13 07:29:26 +010067 struct usb_serial *serial;
Greg Kroah-Hartmane5b1e202013-06-07 11:04:28 -070068 struct usb_serial_port *port;
Oliver Neukum34ef50e2007-01-13 07:29:26 +010069
Oliver Neukum3ddad822007-07-24 15:13:42 +020070 mutex_lock(&table_lock);
Greg Kroah-Hartmane5b1e202013-06-07 11:04:28 -070071 port = idr_find(&serial_minors, minor);
72 if (!port)
73 goto exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
Greg Kroah-Hartmane5b1e202013-06-07 11:04:28 -070075 serial = port->serial;
76 mutex_lock(&serial->disc_mutex);
77 if (serial->disconnected) {
78 mutex_unlock(&serial->disc_mutex);
79 port = NULL;
80 } else {
81 kref_get(&serial->kref);
Alan Stern8bc2c1b2009-09-01 11:38:59 -040082 }
Greg Kroah-Hartmane5b1e202013-06-07 11:04:28 -070083exit:
Oliver Neukum3ddad822007-07-24 15:13:42 +020084 mutex_unlock(&table_lock);
Greg Kroah-Hartmane5b1e202013-06-07 11:04:28 -070085 return port;
Linus Torvalds1da177e2005-04-16 15:20:36 -070086}
87
Greg Kroah-Hartmane5b1e202013-06-07 11:04:28 -070088static int allocate_minors(struct usb_serial *serial, int num_ports)
Linus Torvalds1da177e2005-04-16 15:20:36 -070089{
Greg Kroah-Hartmane5b1e202013-06-07 11:04:28 -070090 struct usb_serial_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -070091 unsigned int i, j;
Greg Kroah-Hartmane5b1e202013-06-07 11:04:28 -070092 int minor;
Linus Torvalds1da177e2005-04-16 15:20:36 -070093
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -070094 dev_dbg(&serial->interface->dev, "%s %d\n", __func__, num_ports);
Linus Torvalds1da177e2005-04-16 15:20:36 -070095
Oliver Neukum3ddad822007-07-24 15:13:42 +020096 mutex_lock(&table_lock);
Greg Kroah-Hartmane5b1e202013-06-07 11:04:28 -070097 for (i = 0; i < num_ports; ++i) {
98 port = serial->port[i];
Johan Hovold194e9582016-05-08 20:08:03 +020099 minor = idr_alloc(&serial_minors, port, 0,
100 USB_SERIAL_TTY_MINORS, GFP_KERNEL);
Greg Kroah-Hartmane5b1e202013-06-07 11:04:28 -0700101 if (minor < 0)
102 goto error;
103 port->minor = minor;
104 port->port_number = i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105 }
Greg Kroah-Hartmane5b1e202013-06-07 11:04:28 -0700106 serial->minors_reserved = 1;
Oliver Neukum3ddad822007-07-24 15:13:42 +0200107 mutex_unlock(&table_lock);
Greg Kroah-Hartmane5b1e202013-06-07 11:04:28 -0700108 return 0;
109error:
110 /* unwind the already allocated minors */
111 for (j = 0; j < i; ++j)
112 idr_remove(&serial_minors, serial->port[j]->minor);
113 mutex_unlock(&table_lock);
114 return minor;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115}
116
Greg Kroah-Hartmane5b1e202013-06-07 11:04:28 -0700117static void release_minors(struct usb_serial *serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118{
119 int i;
120
Alan Stern8bc2c1b2009-09-01 11:38:59 -0400121 mutex_lock(&table_lock);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100122 for (i = 0; i < serial->num_ports; ++i)
Greg Kroah-Hartmane5b1e202013-06-07 11:04:28 -0700123 idr_remove(&serial_minors, serial->port[i]->minor);
Alan Stern8bc2c1b2009-09-01 11:38:59 -0400124 mutex_unlock(&table_lock);
Greg Kroah-Hartmane5b1e202013-06-07 11:04:28 -0700125 serial->minors_reserved = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126}
127
128static void destroy_serial(struct kref *kref)
129{
130 struct usb_serial *serial;
131 struct usb_serial_port *port;
132 int i;
133
134 serial = to_usb_serial(kref);
135
Jim Radford521b85a2007-03-13 08:30:50 -0700136 /* return the minor range that this device had */
Greg Kroah-Hartmane5b1e202013-06-07 11:04:28 -0700137 if (serial->minors_reserved)
138 release_minors(serial);
Jim Radford521b85a2007-03-13 08:30:50 -0700139
Johan Hovold79b80b82013-03-21 12:36:43 +0100140 if (serial->attached && serial->type->release)
Alan Sterna4720c62009-10-09 12:43:12 -0400141 serial->type->release(serial);
Alan Sternf9c99bb2009-06-02 11:53:55 -0400142
Alan Stern41bd34d2009-09-01 11:38:34 -0400143 /* Now that nothing is using the ports, they can be freed */
144 for (i = 0; i < serial->num_port_pointers; ++i) {
Alan Sternf9c99bb2009-06-02 11:53:55 -0400145 port = serial->port[i];
Alan Stern41bd34d2009-09-01 11:38:34 -0400146 if (port) {
147 port->serial = NULL;
Alan Sternf9c99bb2009-06-02 11:53:55 -0400148 put_device(&port->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149 }
150 }
151
Johan Hovoldd7971052013-03-19 09:21:09 +0100152 usb_put_intf(serial->interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153 usb_put_dev(serial->dev);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100154 kfree(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155}
156
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200157void usb_serial_put(struct usb_serial *serial)
158{
159 kref_put(&serial->kref, destroy_serial);
160}
161
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162/*****************************************************************************
163 * Driver tty interface functions
164 *****************************************************************************/
Alan Sternf5b09532009-09-01 11:38:44 -0400165
166/**
167 * serial_install - install tty
168 * @driver: the driver (USB in our case)
169 * @tty: the tty being created
170 *
171 * Create the termios objects for this tty. We use the default
172 * USB serial settings but permit them to be overridden by
173 * serial->type->init_termios.
Alan Sterncc56cd02009-09-01 11:39:13 -0400174 *
175 * This is the first place a new tty gets used. Hence this is where we
176 * acquire references to the usb_serial structure and the driver module,
177 * where we store a pointer to the port, and where we do an autoresume.
Dave Youngf278a2f2009-09-27 16:00:42 +0000178 * All these actions are reversed in serial_cleanup().
Alan Sternf5b09532009-09-01 11:38:44 -0400179 */
180static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
181{
182 int idx = tty->index;
183 struct usb_serial *serial;
Alan Sterncc56cd02009-09-01 11:39:13 -0400184 struct usb_serial_port *port;
185 int retval = -ENODEV;
186
Greg Kroah-Hartmane5b1e202013-06-07 11:04:28 -0700187 port = usb_serial_port_get_by_minor(idx);
188 if (!port)
Alan Sterncc56cd02009-09-01 11:39:13 -0400189 return retval;
190
Greg Kroah-Hartmane5b1e202013-06-07 11:04:28 -0700191 serial = port->serial;
Alan Sterncc56cd02009-09-01 11:39:13 -0400192 if (!try_module_get(serial->type->driver.owner))
193 goto error_module_get;
194
195 retval = usb_autopm_get_interface(serial->interface);
196 if (retval)
197 goto error_get_interface;
Alan Sternf5b09532009-09-01 11:38:44 -0400198
Jiri Slabyca4ff102012-06-04 13:35:34 +0200199 retval = tty_port_install(&port->port, driver, tty);
Jiri Slaby76f82a72012-01-30 21:14:29 +0100200 if (retval)
201 goto error_init_termios;
202
Alan Sterncc56cd02009-09-01 11:39:13 -0400203 mutex_unlock(&serial->disc_mutex);
204
Alan Stern7e29bb42009-09-01 11:39:22 -0400205 /* allow the driver to update the settings */
206 if (serial->type->init_termios)
207 serial->type->init_termios(tty);
208
Alan Sterncc56cd02009-09-01 11:39:13 -0400209 tty->driver_data = port;
210
Alan Sterncc56cd02009-09-01 11:39:13 -0400211 return retval;
212
Alan Stern7e29bb42009-09-01 11:39:22 -0400213 error_init_termios:
Jiri Slaby76f82a72012-01-30 21:14:29 +0100214 usb_autopm_put_interface(serial->interface);
215 error_get_interface:
Alan Sterncc56cd02009-09-01 11:39:13 -0400216 module_put(serial->type->driver.owner);
217 error_module_get:
Alan Sterncc56cd02009-09-01 11:39:13 -0400218 usb_serial_put(serial);
219 mutex_unlock(&serial->disc_mutex);
220 return retval;
Alan Sternf5b09532009-09-01 11:38:44 -0400221}
222
Johan Hovold395e08d2013-03-21 12:36:23 +0100223static int serial_port_activate(struct tty_port *tport, struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224{
Alan Cox64bc3972009-10-06 16:06:11 +0100225 struct usb_serial_port *port =
226 container_of(tport, struct usb_serial_port, port);
Alan Stern320348c2009-09-01 11:39:59 -0400227 struct usb_serial *serial = port->serial;
228 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229
Alan Cox64bc3972009-10-06 16:06:11 +0100230 mutex_lock(&serial->disc_mutex);
231 if (serial->disconnected)
232 retval = -ENODEV;
233 else
234 retval = port->serial->type->open(tty, port);
235 mutex_unlock(&serial->disc_mutex);
Johan Hovold3827d872011-11-10 17:38:13 +0100236
237 if (retval < 0)
238 retval = usb_translate_errors(retval);
239
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 return retval;
241}
242
Alan Cox64bc3972009-10-06 16:06:11 +0100243static int serial_open(struct tty_struct *tty, struct file *filp)
244{
245 struct usb_serial_port *port = tty->driver_data;
246
Johan Hovoldd12e2112013-03-21 12:36:25 +0100247 dev_dbg(tty->dev, "%s\n", __func__);
248
Alan Cox64bc3972009-10-06 16:06:11 +0100249 return tty_port_open(&port->port, tty, filp);
250}
251
Alan Cox335f8512009-06-11 12:26:29 +0100252/**
Johan Hovold395e08d2013-03-21 12:36:23 +0100253 * serial_port_shutdown - shut down hardware
Alan Coxe1108a62009-10-06 16:06:36 +0100254 * @tport: tty port to shut down
Alan Cox335f8512009-06-11 12:26:29 +0100255 *
Peter Hurley8a7298d2013-02-23 10:11:35 -0500256 * Shut down a USB serial port. Serialized against activate by the
257 * tport mutex and kept to matching open/close pairs
Peter Hurleyd41861c2016-04-09 17:53:25 -0700258 * of calls by the initialized flag.
Peter Hurley8a7298d2013-02-23 10:11:35 -0500259 *
260 * Not called if tty is console.
Alan Cox335f8512009-06-11 12:26:29 +0100261 */
Johan Hovold395e08d2013-03-21 12:36:23 +0100262static void serial_port_shutdown(struct tty_port *tport)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263{
Alan Coxe1108a62009-10-06 16:06:36 +0100264 struct usb_serial_port *port =
265 container_of(tport, struct usb_serial_port, port);
Alan Cox335f8512009-06-11 12:26:29 +0100266 struct usb_serial_driver *drv = port->serial->type;
Peter Hurley8a7298d2013-02-23 10:11:35 -0500267
Alan Cox335f8512009-06-11 12:26:29 +0100268 if (drv->close)
269 drv->close(port);
Alan Cox335f8512009-06-11 12:26:29 +0100270}
271
Alan Sternf5b09532009-09-01 11:38:44 -0400272static void serial_hangup(struct tty_struct *tty)
Alan Cox335f8512009-06-11 12:26:29 +0100273{
Alan Cox4455e342009-09-19 13:13:24 -0700274 struct usb_serial_port *port = tty->driver_data;
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -0700275
Johan Hovoldd12e2112013-03-21 12:36:25 +0100276 dev_dbg(tty->dev, "%s\n", __func__);
277
Alan Sternf5b09532009-09-01 11:38:44 -0400278 tty_port_hangup(&port->port);
Alan Cox335f8512009-06-11 12:26:29 +0100279}
280
281static void serial_close(struct tty_struct *tty, struct file *filp)
282{
283 struct usb_serial_port *port = tty->driver_data;
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -0700284
Johan Hovoldd12e2112013-03-21 12:36:25 +0100285 dev_dbg(tty->dev, "%s\n", __func__);
286
Alan Coxe1108a62009-10-06 16:06:36 +0100287 tty_port_close(&port->port, tty, filp);
Alan Cox335f8512009-06-11 12:26:29 +0100288}
289
Alan Sternf5b09532009-09-01 11:38:44 -0400290/**
Dave Youngf278a2f2009-09-27 16:00:42 +0000291 * serial_cleanup - free resources post close/hangup
Alan Sternf5b09532009-09-01 11:38:44 -0400292 * @port: port to free up
293 *
294 * Do the resource freeing and refcount dropping for the port.
295 * Avoid freeing the console.
296 *
Alan Cox36b3c072012-07-17 17:06:57 +0100297 * Called asynchronously after the last tty kref is dropped.
Alan Sternf5b09532009-09-01 11:38:44 -0400298 */
Dave Youngf278a2f2009-09-27 16:00:42 +0000299static void serial_cleanup(struct tty_struct *tty)
Alan Cox335f8512009-06-11 12:26:29 +0100300{
301 struct usb_serial_port *port = tty->driver_data;
Alan Sternf5b09532009-09-01 11:38:44 -0400302 struct usb_serial *serial;
303 struct module *owner;
304
Johan Hovoldd12e2112013-03-21 12:36:25 +0100305 dev_dbg(tty->dev, "%s\n", __func__);
306
Alan Sternf5b09532009-09-01 11:38:44 -0400307 /* The console is magical. Do not hang up the console hardware
308 * or there will be tears.
309 */
Jason Wesselbd5afa92010-03-08 21:50:12 -0600310 if (port->port.console)
Alan Sternf5b09532009-09-01 11:38:44 -0400311 return;
312
Alan Sterncc56cd02009-09-01 11:39:13 -0400313 tty->driver_data = NULL;
314
Alan Sternf5b09532009-09-01 11:38:44 -0400315 serial = port->serial;
316 owner = serial->type->driver.owner;
317
318 mutex_lock(&serial->disc_mutex);
319 if (!serial->disconnected)
320 usb_autopm_put_interface(serial->interface);
321 mutex_unlock(&serial->disc_mutex);
322
323 usb_serial_put(serial);
324 module_put(owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325}
326
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100327static int serial_write(struct tty_struct *tty, const unsigned char *buf,
328 int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200330 struct usb_serial_port *port = tty->driver_data;
Oliver Neukum3ff4fd92007-01-13 07:32:27 +0100331 int retval = -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332
Alan Coxf34d7a52008-04-30 00:54:13 -0700333 if (port->serial->dev->state == USB_STATE_NOTATTACHED)
Luiz Fernando Capitulino487f9c62005-11-28 19:16:05 -0200334 goto exit;
335
Johan Hovoldd12e2112013-03-21 12:36:25 +0100336 dev_dbg(tty->dev, "%s - %d byte(s)\n", __func__, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337
Alan Cox95da3102008-07-22 11:09:07 +0100338 retval = port->serial->type->write(tty, port, buf, count);
Johan Hovoldc6249ff2011-11-10 17:40:44 +0100339 if (retval < 0)
340 retval = usb_translate_errors(retval);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341exit:
342 return retval;
343}
344
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100345static int serial_write_room(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200347 struct usb_serial_port *port = tty->driver_data;
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -0700348
Johan Hovoldd12e2112013-03-21 12:36:25 +0100349 dev_dbg(tty->dev, "%s\n", __func__);
Johan Hovold9993b422013-03-21 12:36:24 +0100350
Alan Cox95da3102008-07-22 11:09:07 +0100351 return port->serial->type->write_room(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352}
353
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100354static int serial_chars_in_buffer(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200356 struct usb_serial_port *port = tty->driver_data;
Johan Hovold810360a2013-01-14 16:52:56 +0100357 struct usb_serial *serial = port->serial;
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -0700358
Johan Hovoldd12e2112013-03-21 12:36:25 +0100359 dev_dbg(tty->dev, "%s\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360
Johan Hovold810360a2013-01-14 16:52:56 +0100361 if (serial->disconnected)
Johan Hovold4746b6c2013-05-05 20:32:33 +0200362 return 0;
Johan Hovold810360a2013-01-14 16:52:56 +0100363
Johan Hovold4746b6c2013-05-05 20:32:33 +0200364 return serial->type->chars_in_buffer(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365}
366
Johan Hovold06931962013-05-05 20:32:27 +0200367static void serial_wait_until_sent(struct tty_struct *tty, int timeout)
368{
369 struct usb_serial_port *port = tty->driver_data;
370 struct usb_serial *serial = port->serial;
371
372 dev_dbg(tty->dev, "%s\n", __func__);
373
374 if (!port->serial->type->wait_until_sent)
375 return;
376
377 mutex_lock(&serial->disc_mutex);
378 if (!serial->disconnected)
379 port->serial->type->wait_until_sent(tty, timeout);
380 mutex_unlock(&serial->disc_mutex);
381}
382
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100383static void serial_throttle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200385 struct usb_serial_port *port = tty->driver_data;
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -0700386
Johan Hovoldd12e2112013-03-21 12:36:25 +0100387 dev_dbg(tty->dev, "%s\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 if (port->serial->type->throttle)
Alan Cox95da3102008-07-22 11:09:07 +0100390 port->serial->type->throttle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391}
392
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100393static void serial_unthrottle(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200395 struct usb_serial_port *port = tty->driver_data;
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -0700396
Johan Hovoldd12e2112013-03-21 12:36:25 +0100397 dev_dbg(tty->dev, "%s\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 if (port->serial->type->unthrottle)
Alan Cox95da3102008-07-22 11:09:07 +0100400 port->serial->type->unthrottle(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401}
402
Alan Cox6caa76b2011-02-14 16:27:22 +0000403static int serial_ioctl(struct tty_struct *tty,
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100404 unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200406 struct usb_serial_port *port = tty->driver_data;
Johan Hovoldf4488032013-06-05 12:21:11 +0200407 int retval = -ENOIOCTLCMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408
Johan Hovold4d5147e2013-12-29 19:22:55 +0100409 dev_dbg(tty->dev, "%s - cmd 0x%04x\n", __func__, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410
Johan Hovold143d9d92013-03-21 12:36:51 +0100411 switch (cmd) {
412 case TIOCMIWAIT:
413 if (port->serial->type->tiocmiwait)
414 retval = port->serial->type->tiocmiwait(tty, arg);
415 break;
416 default:
417 if (port->serial->type->ioctl)
418 retval = port->serial->type->ioctl(tty, cmd, arg);
Johan Hovold143d9d92013-03-21 12:36:51 +0100419 }
Johan Hovold9993b422013-03-21 12:36:24 +0100420
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421 return retval;
422}
423
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100424static void serial_set_termios(struct tty_struct *tty, struct ktermios *old)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200426 struct usb_serial_port *port = tty->driver_data;
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -0700427
Johan Hovoldd12e2112013-03-21 12:36:25 +0100428 dev_dbg(tty->dev, "%s\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 if (port->serial->type->set_termios)
Alan Cox95da3102008-07-22 11:09:07 +0100431 port->serial->type->set_termios(tty, port, old);
Alan Cox33785092007-10-18 01:24:22 -0700432 else
Alan Coxadc8d742012-07-14 15:31:47 +0100433 tty_termios_copy_hw(&tty->termios, old);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434}
435
Alan Cox9e989662008-07-22 11:18:03 +0100436static int serial_break(struct tty_struct *tty, int break_state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200438 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439
Johan Hovoldd12e2112013-03-21 12:36:25 +0100440 dev_dbg(tty->dev, "%s\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441
Alan Cox6b447f042009-01-02 13:48:56 +0000442 if (port->serial->type->break_ctl)
Alan Cox95da3102008-07-22 11:09:07 +0100443 port->serial->type->break_ctl(tty, break_state);
Johan Hovold9993b422013-03-21 12:36:24 +0100444
Alan Cox9e989662008-07-22 11:18:03 +0100445 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446}
447
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700448static int serial_proc_show(struct seq_file *m, void *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449{
450 struct usb_serial *serial;
Greg Kroah-Hartmane5b1e202013-06-07 11:04:28 -0700451 struct usb_serial_port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453 char tmp[40];
454
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700455 seq_puts(m, "usbserinfo:1.0 driver:2.0\n");
Greg Kroah-Hartman455b4f72013-06-06 10:31:35 -0700456 for (i = 0; i < USB_SERIAL_TTY_MINORS; ++i) {
Greg Kroah-Hartmane5b1e202013-06-07 11:04:28 -0700457 port = usb_serial_port_get_by_minor(i);
458 if (port == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459 continue;
Greg Kroah-Hartmane5b1e202013-06-07 11:04:28 -0700460 serial = port->serial;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700462 seq_printf(m, "%d:", i);
Greg Kroah-Hartman18fcac32005-06-20 21:15:16 -0700463 if (serial->type->driver.owner)
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700464 seq_printf(m, " module:%s",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100465 module_name(serial->type->driver.owner));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700466 seq_printf(m, " name:\"%s\"",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100467 serial->type->description);
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700468 seq_printf(m, " vendor:%04x product:%04x",
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100469 le16_to_cpu(serial->dev->descriptor.idVendor),
470 le16_to_cpu(serial->dev->descriptor.idProduct));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700471 seq_printf(m, " num_ports:%d", serial->num_ports);
Greg Kroah-Hartmane5b1e202013-06-07 11:04:28 -0700472 seq_printf(m, " port:%d", port->port_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 usb_make_path(serial->dev, tmp, sizeof(tmp));
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700474 seq_printf(m, " path:%s", tmp);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100475
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700476 seq_putc(m, '\n');
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +0200477 usb_serial_put(serial);
Alan Stern8bc2c1b2009-09-01 11:38:59 -0400478 mutex_unlock(&serial->disc_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479 }
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700480 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481}
482
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -0700483static int serial_proc_open(struct inode *inode, struct file *file)
484{
485 return single_open(file, serial_proc_show, NULL);
486}
487
488static const struct file_operations serial_proc_fops = {
489 .owner = THIS_MODULE,
490 .open = serial_proc_open,
491 .read = seq_read,
492 .llseek = seq_lseek,
493 .release = single_release,
494};
495
Alan Cox60b33c12011-02-14 16:26:14 +0000496static int serial_tiocmget(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200498 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499
Johan Hovoldd12e2112013-03-21 12:36:25 +0100500 dev_dbg(tty->dev, "%s\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 if (port->serial->type->tiocmget)
Alan Cox60b33c12011-02-14 16:26:14 +0000503 return port->serial->type->tiocmget(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 return -EINVAL;
505}
506
Alan Cox20b9d172011-02-14 16:26:50 +0000507static int serial_tiocmset(struct tty_struct *tty,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 unsigned int set, unsigned int clear)
509{
Tobias Klauser81671dd2005-07-04 19:32:51 +0200510 struct usb_serial_port *port = tty->driver_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511
Johan Hovoldd12e2112013-03-21 12:36:25 +0100512 dev_dbg(tty->dev, "%s\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 if (port->serial->type->tiocmset)
Alan Cox20b9d172011-02-14 16:26:50 +0000515 return port->serial->type->tiocmset(tty, set, clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 return -EINVAL;
517}
518
Alan Coxd281da72010-09-16 18:21:24 +0100519static int serial_get_icount(struct tty_struct *tty,
520 struct serial_icounter_struct *icount)
521{
522 struct usb_serial_port *port = tty->driver_data;
523
Johan Hovoldd12e2112013-03-21 12:36:25 +0100524 dev_dbg(tty->dev, "%s\n", __func__);
Alan Coxd281da72010-09-16 18:21:24 +0100525
526 if (port->serial->type->get_icount)
527 return port->serial->type->get_icount(tty, icount);
528 return -EINVAL;
529}
530
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700531/*
532 * We would be calling tty_wakeup here, but unfortunately some line
533 * disciplines have an annoying habit of calling tty->write from
534 * the write wakeup callback (e.g. n_hdlc.c).
535 */
536void usb_serial_port_softint(struct usb_serial_port *port)
537{
538 schedule_work(&port->work);
539}
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100540EXPORT_SYMBOL_GPL(usb_serial_port_softint);
Pete Zaitcevcf2c7482006-05-22 21:58:49 -0700541
David Howellsc4028952006-11-22 14:57:56 +0000542static void usb_serial_port_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543{
David Howellsc4028952006-11-22 14:57:56 +0000544 struct usb_serial_port *port =
545 container_of(work, struct usb_serial_port, work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546
Jiri Slaby6aad04f2013-03-07 13:12:29 +0100547 tty_port_tty_wakeup(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548}
549
Johan Hovold6a5c8212013-03-21 12:36:49 +0100550static void usb_serial_port_poison_urbs(struct usb_serial_port *port)
Pete Zaitcev34f8e762006-06-21 15:00:45 -0700551{
Johan Hovold27c7acf2010-05-05 23:57:37 +0200552 int i;
553
Johan Hovoldd83b4052011-11-06 19:06:37 +0100554 for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i)
Johan Hovold6a5c8212013-03-21 12:36:49 +0100555 usb_poison_urb(port->read_urbs[i]);
Johan Hovold27c7acf2010-05-05 23:57:37 +0200556 for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
Johan Hovold6a5c8212013-03-21 12:36:49 +0100557 usb_poison_urb(port->write_urbs[i]);
558
559 usb_poison_urb(port->interrupt_in_urb);
560 usb_poison_urb(port->interrupt_out_urb);
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100561}
562
Johan Hovold6a5c8212013-03-21 12:36:49 +0100563static void usb_serial_port_unpoison_urbs(struct usb_serial_port *port)
564{
565 int i;
566
567 for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i)
568 usb_unpoison_urb(port->read_urbs[i]);
569 for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
570 usb_unpoison_urb(port->write_urbs[i]);
571
572 usb_unpoison_urb(port->interrupt_in_urb);
573 usb_unpoison_urb(port->interrupt_out_urb);
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100574}
575
Johan Hovold69a3d212013-03-21 12:36:47 +0100576static void usb_serial_port_release(struct device *dev)
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100577{
Alan Stern41bd34d2009-09-01 11:38:34 -0400578 struct usb_serial_port *port = to_usb_serial_port(dev);
Johan Hovold27c7acf2010-05-05 23:57:37 +0200579 int i;
Alan Stern41bd34d2009-09-01 11:38:34 -0400580
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -0700581 dev_dbg(dev, "%s\n", __func__);
Alan Stern41bd34d2009-09-01 11:38:34 -0400582
Oliver Neukum34ef50e2007-01-13 07:29:26 +0100583 usb_free_urb(port->interrupt_in_urb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584 usb_free_urb(port->interrupt_out_urb);
Johan Hovoldd83b4052011-11-06 19:06:37 +0100585 for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) {
586 usb_free_urb(port->read_urbs[i]);
587 kfree(port->bulk_in_buffers[i]);
588 }
Johan Hovold27c7acf2010-05-05 23:57:37 +0200589 for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) {
590 usb_free_urb(port->write_urbs[i]);
591 kfree(port->bulk_out_buffers[i]);
592 }
Stefani Seibold119eecc2009-12-23 09:10:48 +0100593 kfifo_free(&port->write_fifo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 kfree(port->interrupt_in_buffer);
595 kfree(port->interrupt_out_buffer);
Jiri Slaby191c5f12012-11-15 09:49:56 +0100596 tty_port_destroy(&port->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 kfree(port);
598}
599
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100600static struct usb_serial *create_serial(struct usb_device *dev,
601 struct usb_interface *interface,
602 struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603{
604 struct usb_serial *serial;
605
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100606 serial = kzalloc(sizeof(*serial), GFP_KERNEL);
Johan Hovold6b03f7f2013-03-21 12:36:26 +0100607 if (!serial)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 serial->dev = usb_get_dev(dev);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700610 serial->type = driver;
Johan Hovoldd7971052013-03-19 09:21:09 +0100611 serial->interface = usb_get_intf(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612 kref_init(&serial->kref);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +0100613 mutex_init(&serial->disc_mutex);
Greg Kroah-Hartmane5b1e202013-06-07 11:04:28 -0700614 serial->minors_reserved = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615
616 return serial;
617}
618
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100619static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf,
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100620 struct usb_serial_driver *drv)
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100621{
622 struct usb_dynid *dynid;
623
624 spin_lock(&drv->dynids.lock);
625 list_for_each_entry(dynid, &drv->dynids.list, node) {
626 if (usb_match_one_id(intf, &dynid->id)) {
627 spin_unlock(&drv->dynids.lock);
628 return &dynid->id;
629 }
630 }
631 spin_unlock(&drv->dynids.lock);
632 return NULL;
633}
634
635static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv,
636 struct usb_interface *intf)
637{
638 const struct usb_device_id *id;
639
640 id = usb_match_id(intf, drv->id_table);
641 if (id) {
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -0700642 dev_dbg(&intf->dev, "static descriptor matches\n");
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100643 goto exit;
644 }
645 id = match_dynamic_id(intf, drv);
646 if (id)
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -0700647 dev_dbg(&intf->dev, "dynamic descriptor matches\n");
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100648exit:
649 return id;
650}
651
Andi Kleen0daeed32010-06-01 23:04:42 +0200652/* Caller must hold table_lock */
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100653static struct usb_serial_driver *search_serial_device(
654 struct usb_interface *iface)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655{
Bjørn Mork954c3f82012-05-30 10:00:14 +0200656 const struct usb_device_id *id = NULL;
Alan Stern063a2da2007-10-10 16:24:06 -0400657 struct usb_serial_driver *drv;
Bjørn Mork954c3f82012-05-30 10:00:14 +0200658 struct usb_driver *driver = to_usb_driver(iface->dev.driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659
Adrian Bunk93b1fae2006-01-10 00:13:33 +0100660 /* Check if the usb id matches a known device */
Alan Stern063a2da2007-10-10 16:24:06 -0400661 list_for_each_entry(drv, &usb_serial_driver_list, driver_list) {
Bjørn Mork954c3f82012-05-30 10:00:14 +0200662 if (drv->usb_driver == driver)
663 id = get_iface_id(drv, iface);
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100664 if (id)
Alan Stern063a2da2007-10-10 16:24:06 -0400665 return drv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 }
667
668 return NULL;
669}
670
Johan Hovold395e08d2013-03-21 12:36:23 +0100671static int serial_port_carrier_raised(struct tty_port *port)
Alan Cox335f8512009-06-11 12:26:29 +0100672{
673 struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
674 struct usb_serial_driver *drv = p->serial->type;
Johan Hovold3e1f4902011-11-10 17:40:43 +0100675
Alan Cox335f8512009-06-11 12:26:29 +0100676 if (drv->carrier_raised)
677 return drv->carrier_raised(p);
678 /* No carrier control - don't block */
Johan Hovold3e1f4902011-11-10 17:40:43 +0100679 return 1;
Alan Cox335f8512009-06-11 12:26:29 +0100680}
681
Johan Hovold395e08d2013-03-21 12:36:23 +0100682static void serial_port_dtr_rts(struct tty_port *port, int on)
Alan Cox335f8512009-06-11 12:26:29 +0100683{
684 struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
Johan Hovoldf5f45302013-06-26 16:47:22 +0200685 struct usb_serial_driver *drv = p->serial->type;
Johan Hovold3e1f4902011-11-10 17:40:43 +0100686
Johan Hovoldf5f45302013-06-26 16:47:22 +0200687 if (drv->dtr_rts)
Alan Cox335f8512009-06-11 12:26:29 +0100688 drv->dtr_rts(p, on);
689}
690
Johan Hovold2deb96b2015-02-18 10:34:52 +0700691static ssize_t port_number_show(struct device *dev,
692 struct device_attribute *attr, char *buf)
693{
694 struct usb_serial_port *port = to_usb_serial_port(dev);
695
696 return sprintf(buf, "%u\n", port->port_number);
697}
698static DEVICE_ATTR_RO(port_number);
699
700static struct attribute *usb_serial_port_attrs[] = {
701 &dev_attr_port_number.attr,
702 NULL
703};
704ATTRIBUTE_GROUPS(usb_serial_port);
705
Alan Cox335f8512009-06-11 12:26:29 +0100706static const struct tty_port_operations serial_port_ops = {
Johan Hovold395e08d2013-03-21 12:36:23 +0100707 .carrier_raised = serial_port_carrier_raised,
708 .dtr_rts = serial_port_dtr_rts,
709 .activate = serial_port_activate,
710 .shutdown = serial_port_shutdown,
Alan Cox335f8512009-06-11 12:26:29 +0100711};
712
Greg Kroah-Hartman2edd2842012-05-07 14:46:48 -0700713static int usb_serial_probe(struct usb_interface *interface,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714 const struct usb_device_id *id)
715{
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -0700716 struct device *ddev = &interface->dev;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100717 struct usb_device *dev = interface_to_usbdev(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 struct usb_serial *serial = NULL;
719 struct usb_serial_port *port;
720 struct usb_host_interface *iface_desc;
721 struct usb_endpoint_descriptor *endpoint;
722 struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS];
723 struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS];
724 struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];
725 struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -0700726 struct usb_serial_driver *type = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 int retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 int buffer_size;
729 int i;
Johan Hovoldd83b4052011-11-06 19:06:37 +0100730 int j;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731 int num_interrupt_in = 0;
732 int num_interrupt_out = 0;
733 int num_bulk_in = 0;
734 int num_bulk_out = 0;
735 int num_ports = 0;
736 int max_endpoints;
737
Andi Kleen0daeed32010-06-01 23:04:42 +0200738 mutex_lock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 type = search_serial_device(interface);
740 if (!type) {
Andi Kleen0daeed32010-06-01 23:04:42 +0200741 mutex_unlock(&table_lock);
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -0700742 dev_dbg(ddev, "none matched\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 return -ENODEV;
744 }
745
Andi Kleen0daeed32010-06-01 23:04:42 +0200746 if (!try_module_get(type->driver.owner)) {
747 mutex_unlock(&table_lock);
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -0700748 dev_err(ddev, "module get failed, exiting\n");
Andi Kleen0daeed32010-06-01 23:04:42 +0200749 return -EIO;
750 }
751 mutex_unlock(&table_lock);
752
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100753 serial = create_serial(dev, interface, type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754 if (!serial) {
Ming Leid92a3ca2010-08-07 16:20:35 +0800755 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 return -ENOMEM;
757 }
758
759 /* if this device type has a probe function, call it */
760 if (type->probe) {
761 const struct usb_device_id *id;
762
Greg Kroah-Hartman93bacef2006-12-17 21:50:23 +0100763 id = get_iface_id(type, interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 retval = type->probe(serial, id);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765
766 if (retval) {
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -0700767 dev_dbg(ddev, "sub driver rejected device\n");
Jan Safrata0658a332012-05-22 14:04:50 +0200768 usb_serial_put(serial);
Ming Leid92a3ca2010-08-07 16:20:35 +0800769 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 return retval;
771 }
772 }
773
774 /* descriptor matches, let's find the endpoints needed */
775 /* check out the endpoints */
776 iface_desc = interface->cur_altsetting;
777 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
778 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700779
780 if (usb_endpoint_is_bulk_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 /* we found a bulk in endpoint */
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -0700782 dev_dbg(ddev, "found bulk in on endpoint %d\n", i);
Johan Hovoldd979e9f2014-08-27 11:55:18 +0200783 if (num_bulk_in < MAX_NUM_PORTS) {
784 bulk_in_endpoint[num_bulk_in] = endpoint;
785 ++num_bulk_in;
786 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 }
788
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700789 if (usb_endpoint_is_bulk_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 /* we found a bulk out endpoint */
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -0700791 dev_dbg(ddev, "found bulk out on endpoint %d\n", i);
Johan Hovoldd979e9f2014-08-27 11:55:18 +0200792 if (num_bulk_out < MAX_NUM_PORTS) {
793 bulk_out_endpoint[num_bulk_out] = endpoint;
794 ++num_bulk_out;
795 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796 }
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700797
798 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 /* we found a interrupt in endpoint */
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -0700800 dev_dbg(ddev, "found interrupt in on endpoint %d\n", i);
Johan Hovoldd979e9f2014-08-27 11:55:18 +0200801 if (num_interrupt_in < MAX_NUM_PORTS) {
802 interrupt_in_endpoint[num_interrupt_in] =
803 endpoint;
804 ++num_interrupt_in;
805 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 }
807
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700808 if (usb_endpoint_is_int_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 /* we found an interrupt out endpoint */
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -0700810 dev_dbg(ddev, "found interrupt out on endpoint %d\n", i);
Johan Hovoldd979e9f2014-08-27 11:55:18 +0200811 if (num_interrupt_out < MAX_NUM_PORTS) {
812 interrupt_out_endpoint[num_interrupt_out] =
813 endpoint;
814 ++num_interrupt_out;
815 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 }
817 }
818
Javier Martinez Canillas8c34d822016-04-20 14:26:58 -0400819#if IS_ENABLED(CONFIG_USB_SERIAL_PL2303)
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100820 /* BEGIN HORRIBLE HACK FOR PL2303 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 /* this is needed due to the looney way its endpoints are set up */
822 if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&
823 (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||
824 ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) &&
Johannes Steingraeber8fd80132006-09-16 16:17:34 +0200825 (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) ||
826 ((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) &&
Andreas Bombece816cf2008-09-14 01:58:55 +0200827 (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID)) ||
828 ((le16_to_cpu(dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) &&
829 (le16_to_cpu(dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_EF81))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 if (interface != dev->actconfig->interface[0]) {
831 /* check out the endpoints of the other interface*/
832 iface_desc = dev->actconfig->interface[0]->cur_altsetting;
833 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
834 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700835 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 /* we found a interrupt in endpoint */
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -0700837 dev_dbg(ddev, "found interrupt in for Prolific device on separate interface\n");
Johan Hovoldd979e9f2014-08-27 11:55:18 +0200838 if (num_interrupt_in < MAX_NUM_PORTS) {
839 interrupt_in_endpoint[num_interrupt_in] = endpoint;
840 ++num_interrupt_in;
841 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 }
843 }
844 }
845
846 /* Now make sure the PL-2303 is configured correctly.
847 * If not, give up now and hope this hack will work
848 * properly during a later invocation of usb_serial_probe
849 */
850 if (num_bulk_in == 0 || num_bulk_out == 0) {
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -0700851 dev_info(ddev, "PL-2303 hack: descriptors matched but endpoints did not\n");
Jan Safrata0658a332012-05-22 14:04:50 +0200852 usb_serial_put(serial);
Ming Leid92a3ca2010-08-07 16:20:35 +0800853 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854 return -ENODEV;
855 }
856 }
857 /* END HORRIBLE HACK FOR PL2303 */
858#endif
859
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860#ifdef CONFIG_USB_SERIAL_GENERIC
861 if (type == &usb_serial_generic_device) {
862 num_ports = num_bulk_out;
863 if (num_ports == 0) {
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -0700864 dev_err(ddev, "Generic device with no bulk out, not allowed.\n");
Jan Safrata0658a332012-05-22 14:04:50 +0200865 usb_serial_put(serial);
Ming Leid92a3ca2010-08-07 16:20:35 +0800866 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867 return -EIO;
868 }
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -0700869 dev_info(ddev, "The \"generic\" usb-serial driver is only for testing and one-off prototypes.\n");
870 dev_info(ddev, "Tell linux-usb@vger.kernel.org to add your device to a proper driver.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 }
872#endif
873 if (!num_ports) {
874 /* if this device type has a calc_num_ports function, call it */
Ming Leid92a3ca2010-08-07 16:20:35 +0800875 if (type->calc_num_ports)
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100876 num_ports = type->calc_num_ports(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 if (!num_ports)
878 num_ports = type->num_ports;
879 }
880
Johan Hovold56546992014-08-27 11:55:19 +0200881 if (num_ports > MAX_NUM_PORTS) {
882 dev_warn(ddev, "too many ports requested: %d\n", num_ports);
883 num_ports = MAX_NUM_PORTS;
884 }
885
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 serial->num_ports = num_ports;
887 serial->num_bulk_in = num_bulk_in;
888 serial->num_bulk_out = num_bulk_out;
889 serial->num_interrupt_in = num_interrupt_in;
890 serial->num_interrupt_out = num_interrupt_out;
891
Alan Stern063a2da2007-10-10 16:24:06 -0400892 /* found all that we need */
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -0700893 dev_info(ddev, "%s converter detected\n", type->description);
Alan Stern063a2da2007-10-10 16:24:06 -0400894
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 /* create our ports, we need as many as the max endpoints */
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100896 /* we don't use num_ports here because some devices have more
897 endpoint pairs than ports */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 max_endpoints = max(num_bulk_in, num_bulk_out);
899 max_endpoints = max(max_endpoints, num_interrupt_in);
900 max_endpoints = max(max_endpoints, num_interrupt_out);
901 max_endpoints = max(max_endpoints, (int)serial->num_ports);
902 serial->num_port_pointers = max_endpoints;
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100903
Johan Hovoldd9a38a82014-03-12 19:09:42 +0100904 dev_dbg(ddev, "setting up %d port structure(s)\n", max_endpoints);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 for (i = 0; i < max_endpoints; ++i) {
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100906 port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 if (!port)
908 goto probe_error;
Alan Cox4a90f092008-10-13 10:39:46 +0100909 tty_port_init(&port->port);
Alan Cox335f8512009-06-11 12:26:29 +0100910 port->port.ops = &serial_port_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 port->serial = serial;
Greg Kroah-Hartman507ca9b2005-04-23 12:49:16 -0700912 spin_lock_init(&port->lock);
Alan Coxe1108a62009-10-06 16:06:36 +0100913 /* Keep this for private driver use for the moment but
914 should probably go away */
David Howellsc4028952006-11-22 14:57:56 +0000915 INIT_WORK(&port->work, usb_serial_port_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 serial->port[i] = port;
Alan Stern41bd34d2009-09-01 11:38:34 -0400917 port->dev.parent = &interface->dev;
918 port->dev.driver = NULL;
919 port->dev.bus = &usb_serial_bus_type;
Johan Hovold69a3d212013-03-21 12:36:47 +0100920 port->dev.release = &usb_serial_port_release;
Johan Hovold2deb96b2015-02-18 10:34:52 +0700921 port->dev.groups = usb_serial_port_groups;
Alan Stern41bd34d2009-09-01 11:38:34 -0400922 device_initialize(&port->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923 }
924
925 /* set up the endpoint information */
926 for (i = 0; i < num_bulk_in; ++i) {
927 endpoint = bulk_in_endpoint[i];
928 port = serial->port[i];
Alan Stern969e3032011-02-23 15:28:18 -0500929 buffer_size = max_t(int, serial->type->bulk_in_size,
Kuninori Morimoto29cc8892011-08-23 03:12:03 -0700930 usb_endpoint_maxp(endpoint));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 port->bulk_in_size = buffer_size;
932 port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
Johan Hovoldd83b4052011-11-06 19:06:37 +0100933
934 for (j = 0; j < ARRAY_SIZE(port->read_urbs); ++j) {
935 set_bit(j, &port->read_urbs_free);
936 port->read_urbs[j] = usb_alloc_urb(0, GFP_KERNEL);
Johan Hovold6b03f7f2013-03-21 12:36:26 +0100937 if (!port->read_urbs[j])
Johan Hovoldd83b4052011-11-06 19:06:37 +0100938 goto probe_error;
Johan Hovoldd83b4052011-11-06 19:06:37 +0100939 port->bulk_in_buffers[j] = kmalloc(buffer_size,
940 GFP_KERNEL);
Johan Hovold6b03f7f2013-03-21 12:36:26 +0100941 if (!port->bulk_in_buffers[j])
Johan Hovoldd83b4052011-11-06 19:06:37 +0100942 goto probe_error;
Johan Hovoldd83b4052011-11-06 19:06:37 +0100943 usb_fill_bulk_urb(port->read_urbs[j], dev,
944 usb_rcvbulkpipe(dev,
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100945 endpoint->bEndpointAddress),
Johan Hovoldd83b4052011-11-06 19:06:37 +0100946 port->bulk_in_buffers[j], buffer_size,
947 serial->type->read_bulk_callback,
948 port);
949 }
950
951 port->read_urb = port->read_urbs[0];
952 port->bulk_in_buffer = port->bulk_in_buffers[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 }
954
955 for (i = 0; i < num_bulk_out; ++i) {
956 endpoint = bulk_out_endpoint[i];
957 port = serial->port[i];
Stefani Seibold119eecc2009-12-23 09:10:48 +0100958 if (kfifo_alloc(&port->write_fifo, PAGE_SIZE, GFP_KERNEL))
David VomLehn8e8dce02009-08-28 12:54:27 -0700959 goto probe_error;
Johan Hovoldbc4b1f42015-02-15 11:57:53 +0700960 buffer_size = serial->type->bulk_out_size;
961 if (!buffer_size)
962 buffer_size = usb_endpoint_maxp(endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 port->bulk_out_size = buffer_size;
964 port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
Johan Hovold1ce7b932011-11-06 19:06:31 +0100965
Johan Hovold27c7acf2010-05-05 23:57:37 +0200966 for (j = 0; j < ARRAY_SIZE(port->write_urbs); ++j) {
967 set_bit(j, &port->write_urbs_free);
968 port->write_urbs[j] = usb_alloc_urb(0, GFP_KERNEL);
Johan Hovold6b03f7f2013-03-21 12:36:26 +0100969 if (!port->write_urbs[j])
Johan Hovold27c7acf2010-05-05 23:57:37 +0200970 goto probe_error;
Johan Hovold27c7acf2010-05-05 23:57:37 +0200971 port->bulk_out_buffers[j] = kmalloc(buffer_size,
972 GFP_KERNEL);
Johan Hovold6b03f7f2013-03-21 12:36:26 +0100973 if (!port->bulk_out_buffers[j])
Johan Hovold27c7acf2010-05-05 23:57:37 +0200974 goto probe_error;
Johan Hovold27c7acf2010-05-05 23:57:37 +0200975 usb_fill_bulk_urb(port->write_urbs[j], dev,
976 usb_sndbulkpipe(dev,
977 endpoint->bEndpointAddress),
978 port->bulk_out_buffers[j], buffer_size,
979 serial->type->write_bulk_callback,
980 port);
981 }
Johan Hovold1ce7b932011-11-06 19:06:31 +0100982
983 port->write_urb = port->write_urbs[0];
984 port->bulk_out_buffer = port->bulk_out_buffers[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 }
986
987 if (serial->type->read_int_callback) {
988 for (i = 0; i < num_interrupt_in; ++i) {
989 endpoint = interrupt_in_endpoint[i];
990 port = serial->port[i];
991 port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
Johan Hovold6b03f7f2013-03-21 12:36:26 +0100992 if (!port->interrupt_in_urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 goto probe_error;
Kuninori Morimoto29cc8892011-08-23 03:12:03 -0700994 buffer_size = usb_endpoint_maxp(endpoint);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100995 port->interrupt_in_endpointAddress =
996 endpoint->bEndpointAddress;
997 port->interrupt_in_buffer = kmalloc(buffer_size,
998 GFP_KERNEL);
Johan Hovold6b03f7f2013-03-21 12:36:26 +0100999 if (!port->interrupt_in_buffer)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 goto probe_error;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001001 usb_fill_int_urb(port->interrupt_in_urb, dev,
1002 usb_rcvintpipe(dev,
1003 endpoint->bEndpointAddress),
1004 port->interrupt_in_buffer, buffer_size,
1005 serial->type->read_int_callback, port,
1006 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 }
1008 } else if (num_interrupt_in) {
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -07001009 dev_dbg(ddev, "The device claims to support interrupt in transfers, but read_int_callback is not defined\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001011
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 if (serial->type->write_int_callback) {
1013 for (i = 0; i < num_interrupt_out; ++i) {
1014 endpoint = interrupt_out_endpoint[i];
1015 port = serial->port[i];
1016 port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
Johan Hovold6b03f7f2013-03-21 12:36:26 +01001017 if (!port->interrupt_out_urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018 goto probe_error;
Kuninori Morimoto29cc8892011-08-23 03:12:03 -07001019 buffer_size = usb_endpoint_maxp(endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 port->interrupt_out_size = buffer_size;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001021 port->interrupt_out_endpointAddress =
1022 endpoint->bEndpointAddress;
1023 port->interrupt_out_buffer = kmalloc(buffer_size,
1024 GFP_KERNEL);
Johan Hovold6b03f7f2013-03-21 12:36:26 +01001025 if (!port->interrupt_out_buffer)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 goto probe_error;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001027 usb_fill_int_urb(port->interrupt_out_urb, dev,
1028 usb_sndintpipe(dev,
1029 endpoint->bEndpointAddress),
1030 port->interrupt_out_buffer, buffer_size,
1031 serial->type->write_int_callback, port,
1032 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 }
1034 } else if (num_interrupt_out) {
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -07001035 dev_dbg(ddev, "The device claims to support interrupt out transfers, but write_int_callback is not defined\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001037
Johan Hovoldbdce6612012-04-25 15:56:32 +02001038 usb_set_intfdata(interface, serial);
1039
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 /* if this device type has an attach function, call it */
1041 if (type->attach) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001042 retval = type->attach(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 if (retval < 0)
1044 goto probe_error;
Alan Sterna4720c62009-10-09 12:43:12 -04001045 serial->attached = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046 if (retval > 0) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001047 /* quietly accept this device, but don't bind to a
1048 serial port as it's about to disappear */
Alan Stern0a3c8542009-05-27 11:25:52 -04001049 serial->num_ports = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 goto exit;
1051 }
Alan Sterna4720c62009-10-09 12:43:12 -04001052 } else {
1053 serial->attached = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 }
1055
Johan Hovolda65a6f12012-03-20 16:59:33 +01001056 /* Avoid race with tty_open and serial_install by setting the
1057 * disconnected flag and not clearing it until all ports have been
1058 * registered.
1059 */
1060 serial->disconnected = 1;
1061
Greg Kroah-Hartmane5b1e202013-06-07 11:04:28 -07001062 if (allocate_minors(serial, num_ports)) {
1063 dev_err(ddev, "No more free serial minor numbers\n");
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001064 goto probe_error;
1065 }
1066
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 /* register all of the individual ports with the driver core */
1068 for (i = 0; i < num_ports; ++i) {
1069 port = serial->port[i];
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07001070 dev_set_name(&port->dev, "ttyUSB%d", port->minor);
Johan Hovoldd9a38a82014-03-12 19:09:42 +01001071 dev_dbg(ddev, "registering %s\n", dev_name(&port->dev));
Ming Leia7a6b792010-07-13 23:56:24 +08001072 device_enable_async_suspend(&port->dev);
1073
Alan Stern41bd34d2009-09-01 11:38:34 -04001074 retval = device_add(&port->dev);
Alan Stern891a3b12012-03-28 16:10:49 -04001075 if (retval)
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -07001076 dev_err(ddev, "Error registering port device, continuing\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077 }
1078
Johan Hovolda65a6f12012-03-20 16:59:33 +01001079 serial->disconnected = 0;
1080
Greg Kroah-Hartmane5b1e202013-06-07 11:04:28 -07001081 usb_serial_console_init(serial->port[0]->minor);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082exit:
Ming Leid92a3ca2010-08-07 16:20:35 +08001083 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 return 0;
1085
1086probe_error:
Alan Stern41bd34d2009-09-01 11:38:34 -04001087 usb_serial_put(serial);
Ming Leid92a3ca2010-08-07 16:20:35 +08001088 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 return -EIO;
1090}
1091
Greg Kroah-Hartman32078f92012-05-07 14:02:13 -07001092static void usb_serial_disconnect(struct usb_interface *interface)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093{
1094 int i;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001095 struct usb_serial *serial = usb_get_intfdata(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 struct device *dev = &interface->dev;
1097 struct usb_serial_port *port;
Johan Hovold3fff3b42014-05-26 19:23:34 +02001098 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +02001100 usb_serial_console_disconnect(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001102 mutex_lock(&serial->disc_mutex);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001103 /* must set a flag, to signal subdrivers */
1104 serial->disconnected = 1;
Alan Stern2d931482009-04-14 11:31:02 -04001105 mutex_unlock(&serial->disc_mutex);
1106
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001107 for (i = 0; i < serial->num_ports; ++i) {
1108 port = serial->port[i];
Johan Hovold3fff3b42014-05-26 19:23:34 +02001109 tty = tty_port_tty_get(&port->port);
1110 if (tty) {
1111 tty_vhangup(tty);
1112 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 }
Johan Hovold3fff3b42014-05-26 19:23:34 +02001114 usb_serial_port_poison_urbs(port);
1115 wake_up_interruptible(&port->port.delta_msr_wait);
1116 cancel_work_sync(&port->work);
1117 if (device_is_registered(&port->dev))
1118 device_del(&port->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 }
Johan Hovold0f16cfe2013-03-21 12:36:42 +01001120 if (serial->type->disconnect)
1121 serial->type->disconnect(serial);
Alan Stern2d931482009-04-14 11:31:02 -04001122
Alan Stern41bd34d2009-09-01 11:38:34 -04001123 /* let the last holder of this object cause it to be cleaned up */
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001124 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 dev_info(dev, "device disconnected\n");
1126}
1127
Oliver Neukumec225592007-04-27 20:54:57 +02001128int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
1129{
1130 struct usb_serial *serial = usb_get_intfdata(intf);
Oliver Neukumec225592007-04-27 20:54:57 +02001131 int i, r = 0;
1132
Oliver Neukumf8bece82009-02-05 16:54:25 +01001133 serial->suspending = 1;
1134
Ming Lei93e4f472013-03-15 12:08:54 +08001135 /*
1136 * serial->type->suspend() MUST return 0 in system sleep context,
1137 * otherwise, the resume callback has to recover device from
1138 * previous suspend failure.
1139 */
Oliver Neukum81e5b232009-07-21 08:47:34 +02001140 if (serial->type->suspend) {
1141 r = serial->type->suspend(serial, message);
Oliver Neukuma5f60052009-10-01 15:01:17 +02001142 if (r < 0) {
1143 serial->suspending = 0;
Oliver Neukum81e5b232009-07-21 08:47:34 +02001144 goto err_out;
Oliver Neukuma5f60052009-10-01 15:01:17 +02001145 }
Oliver Neukum81e5b232009-07-21 08:47:34 +02001146 }
1147
Johan Hovold3fff3b42014-05-26 19:23:34 +02001148 for (i = 0; i < serial->num_ports; ++i)
1149 usb_serial_port_poison_urbs(serial->port[i]);
Oliver Neukum81e5b232009-07-21 08:47:34 +02001150err_out:
Oliver Neukumec225592007-04-27 20:54:57 +02001151 return r;
1152}
1153EXPORT_SYMBOL(usb_serial_suspend);
1154
Johan Hovold6a5c8212013-03-21 12:36:49 +01001155static void usb_serial_unpoison_port_urbs(struct usb_serial *serial)
1156{
Johan Hovold6a5c8212013-03-21 12:36:49 +01001157 int i;
1158
Johan Hovold3fff3b42014-05-26 19:23:34 +02001159 for (i = 0; i < serial->num_ports; ++i)
1160 usb_serial_port_unpoison_urbs(serial->port[i]);
Johan Hovold6a5c8212013-03-21 12:36:49 +01001161}
1162
Oliver Neukumec225592007-04-27 20:54:57 +02001163int usb_serial_resume(struct usb_interface *intf)
1164{
1165 struct usb_serial *serial = usb_get_intfdata(intf);
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001166 int rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001167
Johan Hovold6a5c8212013-03-21 12:36:49 +01001168 usb_serial_unpoison_port_urbs(serial);
1169
Oliver Neukumf8bece82009-02-05 16:54:25 +01001170 serial->suspending = 0;
Sarah Sharp8abaee22007-10-25 10:58:43 -07001171 if (serial->type->resume)
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001172 rv = serial->type->resume(serial);
1173 else
1174 rv = usb_serial_generic_resume(serial);
Oliver Neukumf8bece82009-02-05 16:54:25 +01001175
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001176 return rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001177}
1178EXPORT_SYMBOL(usb_serial_resume);
1179
Greg Kroah-Hartman71863642012-05-15 15:40:00 -07001180static int usb_serial_reset_resume(struct usb_interface *intf)
1181{
1182 struct usb_serial *serial = usb_get_intfdata(intf);
1183 int rv;
1184
Johan Hovold6a5c8212013-03-21 12:36:49 +01001185 usb_serial_unpoison_port_urbs(serial);
1186
Greg Kroah-Hartman71863642012-05-15 15:40:00 -07001187 serial->suspending = 0;
Johan Hovoldca0400d2014-03-12 19:09:41 +01001188 if (serial->type->reset_resume) {
Greg Kroah-Hartman71863642012-05-15 15:40:00 -07001189 rv = serial->type->reset_resume(serial);
Johan Hovoldca0400d2014-03-12 19:09:41 +01001190 } else {
Greg Kroah-Hartmandcd82cd2012-05-16 08:37:17 -07001191 rv = -EOPNOTSUPP;
1192 intf->needs_binding = 1;
1193 }
Greg Kroah-Hartman71863642012-05-15 15:40:00 -07001194
1195 return rv;
1196}
1197
Jeff Dikeb68e31d2006-10-02 02:17:18 -07001198static const struct tty_operations serial_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199 .open = serial_open,
1200 .close = serial_close,
1201 .write = serial_write,
Johan Hovold3e1f4902011-11-10 17:40:43 +01001202 .hangup = serial_hangup,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203 .write_room = serial_write_room,
1204 .ioctl = serial_ioctl,
1205 .set_termios = serial_set_termios,
1206 .throttle = serial_throttle,
1207 .unthrottle = serial_unthrottle,
1208 .break_ctl = serial_break,
1209 .chars_in_buffer = serial_chars_in_buffer,
Johan Hovold06931962013-05-05 20:32:27 +02001210 .wait_until_sent = serial_wait_until_sent,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 .tiocmget = serial_tiocmget,
1212 .tiocmset = serial_tiocmset,
Johan Hovold3e1f4902011-11-10 17:40:43 +01001213 .get_icount = serial_get_icount,
1214 .cleanup = serial_cleanup,
1215 .install = serial_install,
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -07001216 .proc_fops = &serial_proc_fops,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217};
1218
Alan Cox335f8512009-06-11 12:26:29 +01001219
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220struct tty_driver *usb_serial_tty_driver;
1221
Greg Kroah-Hartman32078f92012-05-07 14:02:13 -07001222/* Driver structure we register with the USB core */
1223static struct usb_driver usb_serial_driver = {
1224 .name = "usbserial",
1225 .probe = usb_serial_probe,
1226 .disconnect = usb_serial_disconnect,
1227 .suspend = usb_serial_suspend,
1228 .resume = usb_serial_resume,
1229 .no_dynamic_id = 1,
1230 .supports_autosuspend = 1,
1231};
1232
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233static int __init usb_serial_init(void)
1234{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235 int result;
1236
Greg Kroah-Hartman455b4f72013-06-06 10:31:35 -07001237 usb_serial_tty_driver = alloc_tty_driver(USB_SERIAL_TTY_MINORS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 if (!usb_serial_tty_driver)
1239 return -ENOMEM;
1240
1241 /* Initialize our global data */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 result = bus_register(&usb_serial_bus_type);
1243 if (result) {
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -07001244 pr_err("%s - registering bus driver failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245 goto exit_bus;
1246 }
1247
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248 usb_serial_tty_driver->driver_name = "usbserial";
Johan Hovold3e1f4902011-11-10 17:40:43 +01001249 usb_serial_tty_driver->name = "ttyUSB";
Greg Kroah-Hartman455b4f72013-06-06 10:31:35 -07001250 usb_serial_tty_driver->major = USB_SERIAL_TTY_MAJOR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 usb_serial_tty_driver->minor_start = 0;
1252 usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
1253 usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001254 usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW |
1255 TTY_DRIVER_DYNAMIC_DEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 usb_serial_tty_driver->init_termios = tty_std_termios;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001257 usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD
1258 | HUPCL | CLOCAL;
Alan Coxa5b6f602008-04-08 17:16:06 +01001259 usb_serial_tty_driver->init_termios.c_ispeed = 9600;
1260 usb_serial_tty_driver->init_termios.c_ospeed = 9600;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261 tty_set_operations(usb_serial_tty_driver, &serial_ops);
1262 result = tty_register_driver(usb_serial_tty_driver);
1263 if (result) {
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -07001264 pr_err("%s - tty_register_driver failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265 goto exit_reg_driver;
1266 }
1267
1268 /* register the USB driver */
1269 result = usb_register(&usb_serial_driver);
1270 if (result < 0) {
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -07001271 pr_err("%s - usb_register failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272 goto exit_tty;
1273 }
1274
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001275 /* register the generic driver, if we should */
Greg Kroah-Hartman3033bc82012-09-18 16:05:17 +01001276 result = usb_serial_generic_register();
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001277 if (result < 0) {
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -07001278 pr_err("%s - registering generic driver failed\n", __func__);
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001279 goto exit_generic;
1280 }
1281
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 return result;
1283
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001284exit_generic:
1285 usb_deregister(&usb_serial_driver);
1286
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287exit_tty:
1288 tty_unregister_driver(usb_serial_tty_driver);
1289
1290exit_reg_driver:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 bus_unregister(&usb_serial_bus_type);
1292
1293exit_bus:
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -07001294 pr_err("%s - returning with error %d\n", __func__, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295 put_tty_driver(usb_serial_tty_driver);
1296 return result;
1297}
1298
1299
1300static void __exit usb_serial_exit(void)
1301{
1302 usb_serial_console_exit();
1303
1304 usb_serial_generic_deregister();
1305
1306 usb_deregister(&usb_serial_driver);
1307 tty_unregister_driver(usb_serial_tty_driver);
1308 put_tty_driver(usb_serial_tty_driver);
1309 bus_unregister(&usb_serial_bus_type);
Johannes Thumshirnd23f47d2015-07-08 17:26:37 +02001310 idr_destroy(&serial_minors);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311}
1312
1313
1314module_init(usb_serial_init);
1315module_exit(usb_serial_exit);
1316
1317#define set_to_generic_if_null(type, function) \
1318 do { \
1319 if (!type->function) { \
1320 type->function = usb_serial_generic_##function; \
Johan Hovoldc3452f52013-03-21 12:36:44 +01001321 pr_debug("%s: using generic " #function "\n", \
1322 type->driver.name); \
1323 } \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324 } while (0)
1325
Johan Hovoldc3452f52013-03-21 12:36:44 +01001326static void usb_serial_operations_init(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327{
1328 set_to_generic_if_null(device, open);
1329 set_to_generic_if_null(device, write);
1330 set_to_generic_if_null(device, close);
1331 set_to_generic_if_null(device, write_room);
1332 set_to_generic_if_null(device, chars_in_buffer);
Johan Hovolddcf01052013-05-08 17:51:43 +02001333 if (device->tx_empty)
1334 set_to_generic_if_null(device, wait_until_sent);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335 set_to_generic_if_null(device, read_bulk_callback);
1336 set_to_generic_if_null(device, write_bulk_callback);
Johan Hovold23154322010-03-17 23:05:57 +01001337 set_to_generic_if_null(device, process_read_urb);
Johan Hovoldeaa3bcb2010-03-17 23:06:08 +01001338 set_to_generic_if_null(device, prepare_write_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339}
1340
Greg Kroah-Hartmanf799e762012-02-24 12:50:30 -08001341static int usb_serial_register(struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342{
1343 int retval;
1344
Dave Younge4abe662009-02-14 21:21:13 +08001345 if (usb_disabled())
1346 return -ENODEV;
1347
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001348 if (!driver->description)
1349 driver->description = driver->driver.name;
Alan Stern5620b5f2011-01-11 14:16:50 -05001350 if (!driver->usb_driver) {
1351 WARN(1, "Serial driver %s has no usb_driver\n",
1352 driver->description);
1353 return -EINVAL;
1354 }
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001355
Johan Hovoldc3452f52013-03-21 12:36:44 +01001356 usb_serial_operations_init(driver);
1357
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358 /* Add this device to our list of devices */
Andi Kleen0daeed32010-06-01 23:04:42 +02001359 mutex_lock(&table_lock);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001360 list_add(&driver->driver_list, &usb_serial_driver_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001362 retval = usb_serial_bus_register(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363 if (retval) {
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -07001364 pr_err("problem %d when registering driver %s\n", retval, driver->description);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001365 list_del(&driver->driver_list);
Johan Hovoldca0400d2014-03-12 19:09:41 +01001366 } else {
Greg Kroah-Hartmanee42f6c2012-09-18 17:10:29 +01001367 pr_info("USB Serial support registered for %s\n", driver->description);
Johan Hovoldca0400d2014-03-12 19:09:41 +01001368 }
Andi Kleen0daeed32010-06-01 23:04:42 +02001369 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370 return retval;
1371}
1372
Greg Kroah-Hartmanf799e762012-02-24 12:50:30 -08001373static void usb_serial_deregister(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374{
Greg Kroah-Hartmanee42f6c2012-09-18 17:10:29 +01001375 pr_info("USB Serial deregistering driver %s\n", device->description);
Johan Hovold10164c22014-04-23 11:32:19 +02001376
Andi Kleen0daeed32010-06-01 23:04:42 +02001377 mutex_lock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 list_del(&device->driver_list);
Andi Kleen0daeed32010-06-01 23:04:42 +02001379 mutex_unlock(&table_lock);
Johan Hovold10164c22014-04-23 11:32:19 +02001380
1381 usb_serial_bus_deregister(device);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383
Alan Stern765e0ba2012-02-23 14:55:59 -05001384/**
1385 * usb_serial_register_drivers - register drivers for a usb-serial module
Alan Stern765e0ba2012-02-23 14:55:59 -05001386 * @serial_drivers: NULL-terminated array of pointers to drivers to be registered
Greg Kroah-Hartman68e24112012-05-08 15:46:14 -07001387 * @name: name of the usb_driver for this set of @serial_drivers
1388 * @id_table: list of all devices this @serial_drivers set binds to
Alan Stern765e0ba2012-02-23 14:55:59 -05001389 *
Greg Kroah-Hartman68e24112012-05-08 15:46:14 -07001390 * Registers all the drivers in the @serial_drivers array, and dynamically
1391 * creates a struct usb_driver with the name @name and id_table of @id_table.
Alan Stern765e0ba2012-02-23 14:55:59 -05001392 */
Greg Kroah-Hartman68e24112012-05-08 15:46:14 -07001393int usb_serial_register_drivers(struct usb_serial_driver *const serial_drivers[],
1394 const char *name,
1395 const struct usb_device_id *id_table)
Alan Stern765e0ba2012-02-23 14:55:59 -05001396{
1397 int rc;
Greg Kroah-Hartman68e24112012-05-08 15:46:14 -07001398 struct usb_driver *udriver;
Alan Stern765e0ba2012-02-23 14:55:59 -05001399 struct usb_serial_driver * const *sd;
1400
1401 /*
1402 * udriver must be registered before any of the serial drivers,
1403 * because the store_new_id() routine for the serial drivers (in
1404 * bus.c) probes udriver.
1405 *
1406 * Performance hack: We don't want udriver to be probed until
1407 * the serial drivers are registered, because the probe would
1408 * simply fail for lack of a matching serial driver.
Greg Kroah-Hartman68e24112012-05-08 15:46:14 -07001409 * So we leave udriver's id_table set to NULL until we are all set.
Alan Stern5cbe61c2012-05-07 11:20:06 -04001410 *
1411 * Suspend/resume support is implemented in the usb-serial core,
1412 * so fill in the PM-related fields in udriver.
Alan Stern765e0ba2012-02-23 14:55:59 -05001413 */
Greg Kroah-Hartman68e24112012-05-08 15:46:14 -07001414 udriver = kzalloc(sizeof(*udriver), GFP_KERNEL);
1415 if (!udriver)
1416 return -ENOMEM;
Alan Stern765e0ba2012-02-23 14:55:59 -05001417
Greg Kroah-Hartman68e24112012-05-08 15:46:14 -07001418 udriver->name = name;
Alan Stern765e0ba2012-02-23 14:55:59 -05001419 udriver->no_dynamic_id = 1;
Alan Stern5cbe61c2012-05-07 11:20:06 -04001420 udriver->supports_autosuspend = 1;
1421 udriver->suspend = usb_serial_suspend;
1422 udriver->resume = usb_serial_resume;
Greg Kroah-Hartman5026bb02012-05-07 13:48:33 -07001423 udriver->probe = usb_serial_probe;
Greg Kroah-Hartman32078f92012-05-07 14:02:13 -07001424 udriver->disconnect = usb_serial_disconnect;
Greg Kroah-Hartman71863642012-05-15 15:40:00 -07001425
1426 /* we only set the reset_resume field if the serial_driver has one */
1427 for (sd = serial_drivers; *sd; ++sd) {
Greg Kroah-Hartman44b0f082012-09-19 08:15:21 +01001428 if ((*sd)->reset_resume) {
Greg Kroah-Hartman71863642012-05-15 15:40:00 -07001429 udriver->reset_resume = usb_serial_reset_resume;
1430 break;
Greg Kroah-Hartman44b0f082012-09-19 08:15:21 +01001431 }
Greg Kroah-Hartman71863642012-05-15 15:40:00 -07001432 }
1433
Alan Stern765e0ba2012-02-23 14:55:59 -05001434 rc = usb_register(udriver);
1435 if (rc)
Alexey Klimov647024a2016-08-08 02:34:46 +01001436 goto failed_usb_register;
Alan Stern765e0ba2012-02-23 14:55:59 -05001437
1438 for (sd = serial_drivers; *sd; ++sd) {
1439 (*sd)->usb_driver = udriver;
1440 rc = usb_serial_register(*sd);
1441 if (rc)
1442 goto failed;
1443 }
1444
Greg Kroah-Hartman68e24112012-05-08 15:46:14 -07001445 /* Now set udriver's id_table and look for matches */
1446 udriver->id_table = id_table;
Alan Stern765e0ba2012-02-23 14:55:59 -05001447 rc = driver_attach(&udriver->drvwrap.driver);
1448 return 0;
1449
1450 failed:
1451 while (sd-- > serial_drivers)
1452 usb_serial_deregister(*sd);
1453 usb_deregister(udriver);
Alexey Klimov647024a2016-08-08 02:34:46 +01001454failed_usb_register:
1455 kfree(udriver);
Alan Stern765e0ba2012-02-23 14:55:59 -05001456 return rc;
1457}
1458EXPORT_SYMBOL_GPL(usb_serial_register_drivers);
1459
1460/**
1461 * usb_serial_deregister_drivers - deregister drivers for a usb-serial module
Alan Stern765e0ba2012-02-23 14:55:59 -05001462 * @serial_drivers: NULL-terminated array of pointers to drivers to be deregistered
1463 *
Greg Kroah-Hartman68e24112012-05-08 15:46:14 -07001464 * Deregisters all the drivers in the @serial_drivers array and deregisters and
1465 * frees the struct usb_driver that was created by the call to
1466 * usb_serial_register_drivers().
Alan Stern765e0ba2012-02-23 14:55:59 -05001467 */
Greg Kroah-Hartman68e24112012-05-08 15:46:14 -07001468void usb_serial_deregister_drivers(struct usb_serial_driver *const serial_drivers[])
Alan Stern765e0ba2012-02-23 14:55:59 -05001469{
Greg Kroah-Hartman68e24112012-05-08 15:46:14 -07001470 struct usb_driver *udriver = (*serial_drivers)->usb_driver;
1471
Alan Stern765e0ba2012-02-23 14:55:59 -05001472 for (; *serial_drivers; ++serial_drivers)
1473 usb_serial_deregister(*serial_drivers);
1474 usb_deregister(udriver);
Greg Kroah-Hartman68e24112012-05-08 15:46:14 -07001475 kfree(udriver);
Alan Stern765e0ba2012-02-23 14:55:59 -05001476}
1477EXPORT_SYMBOL_GPL(usb_serial_deregister_drivers);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001479MODULE_AUTHOR(DRIVER_AUTHOR);
1480MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481MODULE_LICENSE("GPL");