blob: c20d90ed1ef21ba33e2f56612b526fbb33fc7c7b [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * USB Serial Converter driver
3 *
Johan Hovold659597b72013-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) {
Johan Hovoldc2fef452017-03-02 12:51:14 +0100755 retval = -ENOMEM;
756 goto err_put_module;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 }
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");
Johan Hovoldc2fef452017-03-02 12:51:14 +0100768 goto err_put_serial;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769 }
770 }
771
772 /* descriptor matches, let's find the endpoints needed */
773 /* check out the endpoints */
774 iface_desc = interface->cur_altsetting;
775 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
776 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700777
778 if (usb_endpoint_is_bulk_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 /* we found a bulk in endpoint */
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -0700780 dev_dbg(ddev, "found bulk in on endpoint %d\n", i);
Johan Hovoldd979e9f2014-08-27 11:55:18 +0200781 if (num_bulk_in < MAX_NUM_PORTS) {
782 bulk_in_endpoint[num_bulk_in] = endpoint;
783 ++num_bulk_in;
784 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785 }
786
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700787 if (usb_endpoint_is_bulk_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 /* we found a bulk out endpoint */
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -0700789 dev_dbg(ddev, "found bulk out on endpoint %d\n", i);
Johan Hovoldd979e9f2014-08-27 11:55:18 +0200790 if (num_bulk_out < MAX_NUM_PORTS) {
791 bulk_out_endpoint[num_bulk_out] = endpoint;
792 ++num_bulk_out;
793 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 }
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700795
796 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 /* we found a interrupt in endpoint */
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -0700798 dev_dbg(ddev, "found interrupt in on endpoint %d\n", i);
Johan Hovoldd979e9f2014-08-27 11:55:18 +0200799 if (num_interrupt_in < MAX_NUM_PORTS) {
800 interrupt_in_endpoint[num_interrupt_in] =
801 endpoint;
802 ++num_interrupt_in;
803 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 }
805
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700806 if (usb_endpoint_is_int_out(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 /* we found an interrupt out endpoint */
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -0700808 dev_dbg(ddev, "found interrupt out on endpoint %d\n", i);
Johan Hovoldd979e9f2014-08-27 11:55:18 +0200809 if (num_interrupt_out < MAX_NUM_PORTS) {
810 interrupt_out_endpoint[num_interrupt_out] =
811 endpoint;
812 ++num_interrupt_out;
813 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814 }
815 }
816
Javier Martinez Canillas8c34d822016-04-20 14:26:58 -0400817#if IS_ENABLED(CONFIG_USB_SERIAL_PL2303)
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100818 /* BEGIN HORRIBLE HACK FOR PL2303 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 /* this is needed due to the looney way its endpoints are set up */
820 if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&
821 (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||
822 ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) &&
Johannes Steingraeber8fd80132006-09-16 16:17:34 +0200823 (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) ||
824 ((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) &&
Andreas Bombece816cf2008-09-14 01:58:55 +0200825 (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID)) ||
826 ((le16_to_cpu(dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) &&
827 (le16_to_cpu(dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_EF81))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828 if (interface != dev->actconfig->interface[0]) {
829 /* check out the endpoints of the other interface*/
830 iface_desc = dev->actconfig->interface[0]->cur_altsetting;
831 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
832 endpoint = &iface_desc->endpoint[i].desc;
Luiz Fernando N. Capitulino4fa1bbf2006-09-27 11:58:53 -0700833 if (usb_endpoint_is_int_in(endpoint)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 /* we found a interrupt in endpoint */
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -0700835 dev_dbg(ddev, "found interrupt in for Prolific device on separate interface\n");
Johan Hovoldd979e9f2014-08-27 11:55:18 +0200836 if (num_interrupt_in < MAX_NUM_PORTS) {
837 interrupt_in_endpoint[num_interrupt_in] = endpoint;
838 ++num_interrupt_in;
839 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 }
841 }
842 }
843
844 /* Now make sure the PL-2303 is configured correctly.
845 * If not, give up now and hope this hack will work
846 * properly during a later invocation of usb_serial_probe
847 */
848 if (num_bulk_in == 0 || num_bulk_out == 0) {
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -0700849 dev_info(ddev, "PL-2303 hack: descriptors matched but endpoints did not\n");
Johan Hovoldc2fef452017-03-02 12:51:14 +0100850 retval = -ENODEV;
851 goto err_put_serial;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 }
853 }
854 /* END HORRIBLE HACK FOR PL2303 */
855#endif
856
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857#ifdef CONFIG_USB_SERIAL_GENERIC
858 if (type == &usb_serial_generic_device) {
859 num_ports = num_bulk_out;
860 if (num_ports == 0) {
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -0700861 dev_err(ddev, "Generic device with no bulk out, not allowed.\n");
Johan Hovoldc2fef452017-03-02 12:51:14 +0100862 retval = -EIO;
863 goto err_put_serial;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 }
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -0700865 dev_info(ddev, "The \"generic\" usb-serial driver is only for testing and one-off prototypes.\n");
866 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 -0700867 }
868#endif
869 if (!num_ports) {
870 /* if this device type has a calc_num_ports function, call it */
Ming Leid92a3ca2010-08-07 16:20:35 +0800871 if (type->calc_num_ports)
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100872 num_ports = type->calc_num_ports(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 if (!num_ports)
874 num_ports = type->num_ports;
875 }
876
Johan Hovold56546992014-08-27 11:55:19 +0200877 if (num_ports > MAX_NUM_PORTS) {
878 dev_warn(ddev, "too many ports requested: %d\n", num_ports);
879 num_ports = MAX_NUM_PORTS;
880 }
881
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 serial->num_ports = num_ports;
883 serial->num_bulk_in = num_bulk_in;
884 serial->num_bulk_out = num_bulk_out;
885 serial->num_interrupt_in = num_interrupt_in;
886 serial->num_interrupt_out = num_interrupt_out;
887
Alan Stern063a2da2007-10-10 16:24:06 -0400888 /* found all that we need */
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -0700889 dev_info(ddev, "%s converter detected\n", type->description);
Alan Stern063a2da2007-10-10 16:24:06 -0400890
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 /* create our ports, we need as many as the max endpoints */
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100892 /* we don't use num_ports here because some devices have more
893 endpoint pairs than ports */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 max_endpoints = max(num_bulk_in, num_bulk_out);
895 max_endpoints = max(max_endpoints, num_interrupt_in);
896 max_endpoints = max(max_endpoints, num_interrupt_out);
897 max_endpoints = max(max_endpoints, (int)serial->num_ports);
898 serial->num_port_pointers = max_endpoints;
Oliver Neukum4b10f0f2007-01-13 07:31:27 +0100899
Johan Hovoldd9a38a82014-03-12 19:09:42 +0100900 dev_dbg(ddev, "setting up %d port structure(s)\n", max_endpoints);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 for (i = 0; i < max_endpoints; ++i) {
Eric Sesterhenn80b6ca42006-02-27 21:29:43 +0100902 port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 if (!port)
904 goto probe_error;
Alan Cox4a90f092008-10-13 10:39:46 +0100905 tty_port_init(&port->port);
Alan Cox335f8512009-06-11 12:26:29 +0100906 port->port.ops = &serial_port_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 port->serial = serial;
Greg Kroah-Hartman507ca9b2005-04-23 12:49:16 -0700908 spin_lock_init(&port->lock);
Alan Coxe1108a62009-10-06 16:06:36 +0100909 /* Keep this for private driver use for the moment but
910 should probably go away */
David Howellsc4028952006-11-22 14:57:56 +0000911 INIT_WORK(&port->work, usb_serial_port_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 serial->port[i] = port;
Alan Stern41bd34d2009-09-01 11:38:34 -0400913 port->dev.parent = &interface->dev;
914 port->dev.driver = NULL;
915 port->dev.bus = &usb_serial_bus_type;
Johan Hovold69a3d212013-03-21 12:36:47 +0100916 port->dev.release = &usb_serial_port_release;
Johan Hovold2deb96b2015-02-18 10:34:52 +0700917 port->dev.groups = usb_serial_port_groups;
Alan Stern41bd34d2009-09-01 11:38:34 -0400918 device_initialize(&port->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 }
920
921 /* set up the endpoint information */
922 for (i = 0; i < num_bulk_in; ++i) {
923 endpoint = bulk_in_endpoint[i];
924 port = serial->port[i];
Alan Stern969e3032011-02-23 15:28:18 -0500925 buffer_size = max_t(int, serial->type->bulk_in_size,
Kuninori Morimoto29cc8892011-08-23 03:12:03 -0700926 usb_endpoint_maxp(endpoint));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 port->bulk_in_size = buffer_size;
928 port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
Johan Hovoldd83b4052011-11-06 19:06:37 +0100929
930 for (j = 0; j < ARRAY_SIZE(port->read_urbs); ++j) {
931 set_bit(j, &port->read_urbs_free);
932 port->read_urbs[j] = usb_alloc_urb(0, GFP_KERNEL);
Johan Hovold6b03f7f2013-03-21 12:36:26 +0100933 if (!port->read_urbs[j])
Johan Hovoldd83b4052011-11-06 19:06:37 +0100934 goto probe_error;
Johan Hovoldd83b4052011-11-06 19:06:37 +0100935 port->bulk_in_buffers[j] = kmalloc(buffer_size,
936 GFP_KERNEL);
Johan Hovold6b03f7f2013-03-21 12:36:26 +0100937 if (!port->bulk_in_buffers[j])
Johan Hovoldd83b4052011-11-06 19:06:37 +0100938 goto probe_error;
Johan Hovoldd83b4052011-11-06 19:06:37 +0100939 usb_fill_bulk_urb(port->read_urbs[j], dev,
940 usb_rcvbulkpipe(dev,
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100941 endpoint->bEndpointAddress),
Johan Hovoldd83b4052011-11-06 19:06:37 +0100942 port->bulk_in_buffers[j], buffer_size,
943 serial->type->read_bulk_callback,
944 port);
945 }
946
947 port->read_urb = port->read_urbs[0];
948 port->bulk_in_buffer = port->bulk_in_buffers[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 }
950
951 for (i = 0; i < num_bulk_out; ++i) {
952 endpoint = bulk_out_endpoint[i];
953 port = serial->port[i];
Stefani Seibold119eecc2009-12-23 09:10:48 +0100954 if (kfifo_alloc(&port->write_fifo, PAGE_SIZE, GFP_KERNEL))
David VomLehn8e8dce02009-08-28 12:54:27 -0700955 goto probe_error;
Johan Hovoldbc4b1f42015-02-15 11:57:53 +0700956 buffer_size = serial->type->bulk_out_size;
957 if (!buffer_size)
958 buffer_size = usb_endpoint_maxp(endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959 port->bulk_out_size = buffer_size;
960 port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
Johan Hovold1ce7b932011-11-06 19:06:31 +0100961
Johan Hovold27c7acf2010-05-05 23:57:37 +0200962 for (j = 0; j < ARRAY_SIZE(port->write_urbs); ++j) {
963 set_bit(j, &port->write_urbs_free);
964 port->write_urbs[j] = usb_alloc_urb(0, GFP_KERNEL);
Johan Hovold6b03f7f2013-03-21 12:36:26 +0100965 if (!port->write_urbs[j])
Johan Hovold27c7acf2010-05-05 23:57:37 +0200966 goto probe_error;
Johan Hovold27c7acf2010-05-05 23:57:37 +0200967 port->bulk_out_buffers[j] = kmalloc(buffer_size,
968 GFP_KERNEL);
Johan Hovold6b03f7f2013-03-21 12:36:26 +0100969 if (!port->bulk_out_buffers[j])
Johan Hovold27c7acf2010-05-05 23:57:37 +0200970 goto probe_error;
Johan Hovold27c7acf2010-05-05 23:57:37 +0200971 usb_fill_bulk_urb(port->write_urbs[j], dev,
972 usb_sndbulkpipe(dev,
973 endpoint->bEndpointAddress),
974 port->bulk_out_buffers[j], buffer_size,
975 serial->type->write_bulk_callback,
976 port);
977 }
Johan Hovold1ce7b932011-11-06 19:06:31 +0100978
979 port->write_urb = port->write_urbs[0];
980 port->bulk_out_buffer = port->bulk_out_buffers[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 }
982
983 if (serial->type->read_int_callback) {
984 for (i = 0; i < num_interrupt_in; ++i) {
985 endpoint = interrupt_in_endpoint[i];
986 port = serial->port[i];
987 port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
Johan Hovold6b03f7f2013-03-21 12:36:26 +0100988 if (!port->interrupt_in_urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 goto probe_error;
Kuninori Morimoto29cc8892011-08-23 03:12:03 -0700990 buffer_size = usb_endpoint_maxp(endpoint);
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100991 port->interrupt_in_endpointAddress =
992 endpoint->bEndpointAddress;
993 port->interrupt_in_buffer = kmalloc(buffer_size,
994 GFP_KERNEL);
Johan Hovold6b03f7f2013-03-21 12:36:26 +0100995 if (!port->interrupt_in_buffer)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 goto probe_error;
Alan Coxa8d6f0a2008-07-22 11:12:24 +0100997 usb_fill_int_urb(port->interrupt_in_urb, dev,
998 usb_rcvintpipe(dev,
999 endpoint->bEndpointAddress),
1000 port->interrupt_in_buffer, buffer_size,
1001 serial->type->read_int_callback, port,
1002 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 }
1004 } else if (num_interrupt_in) {
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -07001005 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 -07001006 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001007
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 if (serial->type->write_int_callback) {
1009 for (i = 0; i < num_interrupt_out; ++i) {
1010 endpoint = interrupt_out_endpoint[i];
1011 port = serial->port[i];
1012 port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
Johan Hovold6b03f7f2013-03-21 12:36:26 +01001013 if (!port->interrupt_out_urb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 goto probe_error;
Kuninori Morimoto29cc8892011-08-23 03:12:03 -07001015 buffer_size = usb_endpoint_maxp(endpoint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 port->interrupt_out_size = buffer_size;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001017 port->interrupt_out_endpointAddress =
1018 endpoint->bEndpointAddress;
1019 port->interrupt_out_buffer = kmalloc(buffer_size,
1020 GFP_KERNEL);
Johan Hovold6b03f7f2013-03-21 12:36:26 +01001021 if (!port->interrupt_out_buffer)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 goto probe_error;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001023 usb_fill_int_urb(port->interrupt_out_urb, dev,
1024 usb_sndintpipe(dev,
1025 endpoint->bEndpointAddress),
1026 port->interrupt_out_buffer, buffer_size,
1027 serial->type->write_int_callback, port,
1028 endpoint->bInterval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 }
1030 } else if (num_interrupt_out) {
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -07001031 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 -07001032 }
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001033
Johan Hovoldbdce6612012-04-25 15:56:32 +02001034 usb_set_intfdata(interface, serial);
1035
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 /* if this device type has an attach function, call it */
1037 if (type->attach) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001038 retval = type->attach(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 if (retval < 0)
1040 goto probe_error;
Alan Sterna4720c62009-10-09 12:43:12 -04001041 serial->attached = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 if (retval > 0) {
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001043 /* quietly accept this device, but don't bind to a
1044 serial port as it's about to disappear */
Alan Stern0a3c8542009-05-27 11:25:52 -04001045 serial->num_ports = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046 goto exit;
1047 }
Alan Sterna4720c62009-10-09 12:43:12 -04001048 } else {
1049 serial->attached = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 }
1051
Johan Hovolda65a6f12012-03-20 16:59:33 +01001052 /* Avoid race with tty_open and serial_install by setting the
1053 * disconnected flag and not clearing it until all ports have been
1054 * registered.
1055 */
1056 serial->disconnected = 1;
1057
Greg Kroah-Hartmane5b1e202013-06-07 11:04:28 -07001058 if (allocate_minors(serial, num_ports)) {
1059 dev_err(ddev, "No more free serial minor numbers\n");
Oliver Neukum34ef50e2007-01-13 07:29:26 +01001060 goto probe_error;
1061 }
1062
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063 /* register all of the individual ports with the driver core */
1064 for (i = 0; i < num_ports; ++i) {
1065 port = serial->port[i];
Greg Kroah-Hartman11438322013-06-06 10:32:00 -07001066 dev_set_name(&port->dev, "ttyUSB%d", port->minor);
Johan Hovoldd9a38a82014-03-12 19:09:42 +01001067 dev_dbg(ddev, "registering %s\n", dev_name(&port->dev));
Ming Leia7a6b792010-07-13 23:56:24 +08001068 device_enable_async_suspend(&port->dev);
1069
Alan Stern41bd34d2009-09-01 11:38:34 -04001070 retval = device_add(&port->dev);
Alan Stern891a3b12012-03-28 16:10:49 -04001071 if (retval)
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -07001072 dev_err(ddev, "Error registering port device, continuing\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073 }
1074
Johan Hovolda65a6f12012-03-20 16:59:33 +01001075 serial->disconnected = 0;
1076
Johan Hovold126d26f2016-10-21 12:56:27 +02001077 if (num_ports > 0)
1078 usb_serial_console_init(serial->port[0]->minor);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079exit:
Ming Leid92a3ca2010-08-07 16:20:35 +08001080 module_put(type->driver.owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081 return 0;
1082
1083probe_error:
Johan Hovoldc2fef452017-03-02 12:51:14 +01001084 retval = -EIO;
1085err_put_serial:
Alan Stern41bd34d2009-09-01 11:38:34 -04001086 usb_serial_put(serial);
Johan Hovoldc2fef452017-03-02 12:51:14 +01001087err_put_module:
Ming Leid92a3ca2010-08-07 16:20:35 +08001088 module_put(type->driver.owner);
Johan Hovoldc2fef452017-03-02 12:51:14 +01001089
1090 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091}
1092
Greg Kroah-Hartman32078f92012-05-07 14:02:13 -07001093static void usb_serial_disconnect(struct usb_interface *interface)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094{
1095 int i;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001096 struct usb_serial *serial = usb_get_intfdata(interface);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 struct device *dev = &interface->dev;
1098 struct usb_serial_port *port;
Johan Hovold3fff3b42014-05-26 19:23:34 +02001099 struct tty_struct *tty;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100
Guennadi Liakhovetski73e487f2006-04-25 07:46:17 +02001101 usb_serial_console_disconnect(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001103 mutex_lock(&serial->disc_mutex);
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001104 /* must set a flag, to signal subdrivers */
1105 serial->disconnected = 1;
Alan Stern2d931482009-04-14 11:31:02 -04001106 mutex_unlock(&serial->disc_mutex);
1107
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001108 for (i = 0; i < serial->num_ports; ++i) {
1109 port = serial->port[i];
Johan Hovold3fff3b42014-05-26 19:23:34 +02001110 tty = tty_port_tty_get(&port->port);
1111 if (tty) {
1112 tty_vhangup(tty);
1113 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114 }
Johan Hovold3fff3b42014-05-26 19:23:34 +02001115 usb_serial_port_poison_urbs(port);
1116 wake_up_interruptible(&port->port.delta_msr_wait);
1117 cancel_work_sync(&port->work);
1118 if (device_is_registered(&port->dev))
1119 device_del(&port->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 }
Johan Hovold0f16cfe2013-03-21 12:36:42 +01001121 if (serial->type->disconnect)
1122 serial->type->disconnect(serial);
Alan Stern2d931482009-04-14 11:31:02 -04001123
Alan Stern41bd34d2009-09-01 11:38:34 -04001124 /* let the last holder of this object cause it to be cleaned up */
Oliver Neukuma1cd7e92008-01-16 17:18:52 +01001125 usb_serial_put(serial);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 dev_info(dev, "device disconnected\n");
1127}
1128
Oliver Neukumec225592007-04-27 20:54:57 +02001129int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
1130{
1131 struct usb_serial *serial = usb_get_intfdata(intf);
Oliver Neukumec225592007-04-27 20:54:57 +02001132 int i, r = 0;
1133
Oliver Neukumf8bece82009-02-05 16:54:25 +01001134 serial->suspending = 1;
1135
Ming Lei93e4f472013-03-15 12:08:54 +08001136 /*
1137 * serial->type->suspend() MUST return 0 in system sleep context,
1138 * otherwise, the resume callback has to recover device from
1139 * previous suspend failure.
1140 */
Oliver Neukum81e5b232009-07-21 08:47:34 +02001141 if (serial->type->suspend) {
1142 r = serial->type->suspend(serial, message);
Oliver Neukuma5f60052009-10-01 15:01:17 +02001143 if (r < 0) {
1144 serial->suspending = 0;
Oliver Neukum81e5b232009-07-21 08:47:34 +02001145 goto err_out;
Oliver Neukuma5f60052009-10-01 15:01:17 +02001146 }
Oliver Neukum81e5b232009-07-21 08:47:34 +02001147 }
1148
Johan Hovold3fff3b42014-05-26 19:23:34 +02001149 for (i = 0; i < serial->num_ports; ++i)
1150 usb_serial_port_poison_urbs(serial->port[i]);
Oliver Neukum81e5b232009-07-21 08:47:34 +02001151err_out:
Oliver Neukumec225592007-04-27 20:54:57 +02001152 return r;
1153}
1154EXPORT_SYMBOL(usb_serial_suspend);
1155
Johan Hovold6a5c8212013-03-21 12:36:49 +01001156static void usb_serial_unpoison_port_urbs(struct usb_serial *serial)
1157{
Johan Hovold6a5c8212013-03-21 12:36:49 +01001158 int i;
1159
Johan Hovold3fff3b42014-05-26 19:23:34 +02001160 for (i = 0; i < serial->num_ports; ++i)
1161 usb_serial_port_unpoison_urbs(serial->port[i]);
Johan Hovold6a5c8212013-03-21 12:36:49 +01001162}
1163
Oliver Neukumec225592007-04-27 20:54:57 +02001164int usb_serial_resume(struct usb_interface *intf)
1165{
1166 struct usb_serial *serial = usb_get_intfdata(intf);
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001167 int rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001168
Johan Hovold6a5c8212013-03-21 12:36:49 +01001169 usb_serial_unpoison_port_urbs(serial);
1170
Oliver Neukumf8bece82009-02-05 16:54:25 +01001171 serial->suspending = 0;
Sarah Sharp8abaee22007-10-25 10:58:43 -07001172 if (serial->type->resume)
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001173 rv = serial->type->resume(serial);
1174 else
1175 rv = usb_serial_generic_resume(serial);
Oliver Neukumf8bece82009-02-05 16:54:25 +01001176
Oliver Neukumc49cfa912009-02-06 18:06:43 +01001177 return rv;
Oliver Neukumec225592007-04-27 20:54:57 +02001178}
1179EXPORT_SYMBOL(usb_serial_resume);
1180
Greg Kroah-Hartman71863642012-05-15 15:40:00 -07001181static int usb_serial_reset_resume(struct usb_interface *intf)
1182{
1183 struct usb_serial *serial = usb_get_intfdata(intf);
1184 int rv;
1185
Johan Hovold6a5c8212013-03-21 12:36:49 +01001186 usb_serial_unpoison_port_urbs(serial);
1187
Greg Kroah-Hartman71863642012-05-15 15:40:00 -07001188 serial->suspending = 0;
Johan Hovoldca0400d2014-03-12 19:09:41 +01001189 if (serial->type->reset_resume) {
Greg Kroah-Hartman71863642012-05-15 15:40:00 -07001190 rv = serial->type->reset_resume(serial);
Johan Hovoldca0400d2014-03-12 19:09:41 +01001191 } else {
Greg Kroah-Hartmandcd82cd2012-05-16 08:37:17 -07001192 rv = -EOPNOTSUPP;
1193 intf->needs_binding = 1;
1194 }
Greg Kroah-Hartman71863642012-05-15 15:40:00 -07001195
1196 return rv;
1197}
1198
Jeff Dikeb68e31d2006-10-02 02:17:18 -07001199static const struct tty_operations serial_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 .open = serial_open,
1201 .close = serial_close,
1202 .write = serial_write,
Johan Hovold3e1f4902011-11-10 17:40:43 +01001203 .hangup = serial_hangup,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 .write_room = serial_write_room,
1205 .ioctl = serial_ioctl,
1206 .set_termios = serial_set_termios,
1207 .throttle = serial_throttle,
1208 .unthrottle = serial_unthrottle,
1209 .break_ctl = serial_break,
1210 .chars_in_buffer = serial_chars_in_buffer,
Johan Hovold06931962013-05-05 20:32:27 +02001211 .wait_until_sent = serial_wait_until_sent,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 .tiocmget = serial_tiocmget,
1213 .tiocmset = serial_tiocmset,
Johan Hovold3e1f4902011-11-10 17:40:43 +01001214 .get_icount = serial_get_icount,
1215 .cleanup = serial_cleanup,
1216 .install = serial_install,
Alexey Dobriyan6fd69d32009-03-31 15:19:21 -07001217 .proc_fops = &serial_proc_fops,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218};
1219
Alan Cox335f8512009-06-11 12:26:29 +01001220
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221struct tty_driver *usb_serial_tty_driver;
1222
Greg Kroah-Hartman32078f92012-05-07 14:02:13 -07001223/* Driver structure we register with the USB core */
1224static struct usb_driver usb_serial_driver = {
1225 .name = "usbserial",
1226 .probe = usb_serial_probe,
1227 .disconnect = usb_serial_disconnect,
1228 .suspend = usb_serial_suspend,
1229 .resume = usb_serial_resume,
1230 .no_dynamic_id = 1,
1231 .supports_autosuspend = 1,
1232};
1233
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234static int __init usb_serial_init(void)
1235{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236 int result;
1237
Greg Kroah-Hartman455b4f72013-06-06 10:31:35 -07001238 usb_serial_tty_driver = alloc_tty_driver(USB_SERIAL_TTY_MINORS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239 if (!usb_serial_tty_driver)
1240 return -ENOMEM;
1241
1242 /* Initialize our global data */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243 result = bus_register(&usb_serial_bus_type);
1244 if (result) {
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -07001245 pr_err("%s - registering bus driver failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246 goto exit_bus;
1247 }
1248
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249 usb_serial_tty_driver->driver_name = "usbserial";
Johan Hovold3e1f4902011-11-10 17:40:43 +01001250 usb_serial_tty_driver->name = "ttyUSB";
Greg Kroah-Hartman455b4f72013-06-06 10:31:35 -07001251 usb_serial_tty_driver->major = USB_SERIAL_TTY_MAJOR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252 usb_serial_tty_driver->minor_start = 0;
1253 usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
1254 usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001255 usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW |
1256 TTY_DRIVER_DYNAMIC_DEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257 usb_serial_tty_driver->init_termios = tty_std_termios;
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001258 usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD
1259 | HUPCL | CLOCAL;
Alan Coxa5b6f602008-04-08 17:16:06 +01001260 usb_serial_tty_driver->init_termios.c_ispeed = 9600;
1261 usb_serial_tty_driver->init_termios.c_ospeed = 9600;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262 tty_set_operations(usb_serial_tty_driver, &serial_ops);
1263 result = tty_register_driver(usb_serial_tty_driver);
1264 if (result) {
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -07001265 pr_err("%s - tty_register_driver failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 goto exit_reg_driver;
1267 }
1268
1269 /* register the USB driver */
1270 result = usb_register(&usb_serial_driver);
1271 if (result < 0) {
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -07001272 pr_err("%s - usb_register failed\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 goto exit_tty;
1274 }
1275
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001276 /* register the generic driver, if we should */
Greg Kroah-Hartman3033bc82012-09-18 16:05:17 +01001277 result = usb_serial_generic_register();
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001278 if (result < 0) {
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -07001279 pr_err("%s - registering generic driver failed\n", __func__);
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001280 goto exit_generic;
1281 }
1282
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283 return result;
1284
Greg Kroah-Hartman06299db2005-05-26 05:55:55 -07001285exit_generic:
1286 usb_deregister(&usb_serial_driver);
1287
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288exit_tty:
1289 tty_unregister_driver(usb_serial_tty_driver);
1290
1291exit_reg_driver:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 bus_unregister(&usb_serial_bus_type);
1293
1294exit_bus:
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -07001295 pr_err("%s - returning with error %d\n", __func__, result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 put_tty_driver(usb_serial_tty_driver);
1297 return result;
1298}
1299
1300
1301static void __exit usb_serial_exit(void)
1302{
1303 usb_serial_console_exit();
1304
1305 usb_serial_generic_deregister();
1306
1307 usb_deregister(&usb_serial_driver);
1308 tty_unregister_driver(usb_serial_tty_driver);
1309 put_tty_driver(usb_serial_tty_driver);
1310 bus_unregister(&usb_serial_bus_type);
Johannes Thumshirnd23f47d2015-07-08 17:26:37 +02001311 idr_destroy(&serial_minors);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312}
1313
1314
1315module_init(usb_serial_init);
1316module_exit(usb_serial_exit);
1317
1318#define set_to_generic_if_null(type, function) \
1319 do { \
1320 if (!type->function) { \
1321 type->function = usb_serial_generic_##function; \
Johan Hovoldc3452f52013-03-21 12:36:44 +01001322 pr_debug("%s: using generic " #function "\n", \
1323 type->driver.name); \
1324 } \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325 } while (0)
1326
Johan Hovoldc3452f52013-03-21 12:36:44 +01001327static void usb_serial_operations_init(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328{
1329 set_to_generic_if_null(device, open);
1330 set_to_generic_if_null(device, write);
1331 set_to_generic_if_null(device, close);
1332 set_to_generic_if_null(device, write_room);
1333 set_to_generic_if_null(device, chars_in_buffer);
Johan Hovolddcf01052013-05-08 17:51:43 +02001334 if (device->tx_empty)
1335 set_to_generic_if_null(device, wait_until_sent);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 set_to_generic_if_null(device, read_bulk_callback);
1337 set_to_generic_if_null(device, write_bulk_callback);
Johan Hovold23154322010-03-17 23:05:57 +01001338 set_to_generic_if_null(device, process_read_urb);
Johan Hovoldeaa3bcb2010-03-17 23:06:08 +01001339 set_to_generic_if_null(device, prepare_write_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340}
1341
Greg Kroah-Hartmanf799e762012-02-24 12:50:30 -08001342static int usb_serial_register(struct usb_serial_driver *driver)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343{
1344 int retval;
1345
Dave Younge4abe662009-02-14 21:21:13 +08001346 if (usb_disabled())
1347 return -ENODEV;
1348
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001349 if (!driver->description)
1350 driver->description = driver->driver.name;
Alan Stern5620b5f2011-01-11 14:16:50 -05001351 if (!driver->usb_driver) {
1352 WARN(1, "Serial driver %s has no usb_driver\n",
1353 driver->description);
1354 return -EINVAL;
1355 }
Greg Kroah-Hartman269bda12005-06-20 21:15:16 -07001356
Johan Hovoldc3452f52013-03-21 12:36:44 +01001357 usb_serial_operations_init(driver);
1358
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 /* Add this device to our list of devices */
Andi Kleen0daeed32010-06-01 23:04:42 +02001360 mutex_lock(&table_lock);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001361 list_add(&driver->driver_list, &usb_serial_driver_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001363 retval = usb_serial_bus_register(driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364 if (retval) {
Greg Kroah-Hartman92931d22012-09-13 16:30:31 -07001365 pr_err("problem %d when registering driver %s\n", retval, driver->description);
Greg Kroah-Hartmanea653702005-06-20 21:15:16 -07001366 list_del(&driver->driver_list);
Johan Hovoldca0400d2014-03-12 19:09:41 +01001367 } else {
Greg Kroah-Hartmanee42f6c2012-09-18 17:10:29 +01001368 pr_info("USB Serial support registered for %s\n", driver->description);
Johan Hovoldca0400d2014-03-12 19:09:41 +01001369 }
Andi Kleen0daeed32010-06-01 23:04:42 +02001370 mutex_unlock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 return retval;
1372}
1373
Greg Kroah-Hartmanf799e762012-02-24 12:50:30 -08001374static void usb_serial_deregister(struct usb_serial_driver *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375{
Greg Kroah-Hartmanee42f6c2012-09-18 17:10:29 +01001376 pr_info("USB Serial deregistering driver %s\n", device->description);
Johan Hovold10164c22014-04-23 11:32:19 +02001377
Andi Kleen0daeed32010-06-01 23:04:42 +02001378 mutex_lock(&table_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379 list_del(&device->driver_list);
Andi Kleen0daeed32010-06-01 23:04:42 +02001380 mutex_unlock(&table_lock);
Johan Hovold10164c22014-04-23 11:32:19 +02001381
1382 usb_serial_bus_deregister(device);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384
Alan Stern765e0ba2012-02-23 14:55:59 -05001385/**
1386 * usb_serial_register_drivers - register drivers for a usb-serial module
Alan Stern765e0ba2012-02-23 14:55:59 -05001387 * @serial_drivers: NULL-terminated array of pointers to drivers to be registered
Greg Kroah-Hartman68e24112012-05-08 15:46:14 -07001388 * @name: name of the usb_driver for this set of @serial_drivers
1389 * @id_table: list of all devices this @serial_drivers set binds to
Alan Stern765e0ba2012-02-23 14:55:59 -05001390 *
Greg Kroah-Hartman68e24112012-05-08 15:46:14 -07001391 * Registers all the drivers in the @serial_drivers array, and dynamically
1392 * creates a struct usb_driver with the name @name and id_table of @id_table.
Alan Stern765e0ba2012-02-23 14:55:59 -05001393 */
Greg Kroah-Hartman68e24112012-05-08 15:46:14 -07001394int usb_serial_register_drivers(struct usb_serial_driver *const serial_drivers[],
1395 const char *name,
1396 const struct usb_device_id *id_table)
Alan Stern765e0ba2012-02-23 14:55:59 -05001397{
1398 int rc;
Greg Kroah-Hartman68e24112012-05-08 15:46:14 -07001399 struct usb_driver *udriver;
Alan Stern765e0ba2012-02-23 14:55:59 -05001400 struct usb_serial_driver * const *sd;
1401
1402 /*
1403 * udriver must be registered before any of the serial drivers,
1404 * because the store_new_id() routine for the serial drivers (in
1405 * bus.c) probes udriver.
1406 *
1407 * Performance hack: We don't want udriver to be probed until
1408 * the serial drivers are registered, because the probe would
1409 * simply fail for lack of a matching serial driver.
Greg Kroah-Hartman68e24112012-05-08 15:46:14 -07001410 * So we leave udriver's id_table set to NULL until we are all set.
Alan Stern5cbe61c2012-05-07 11:20:06 -04001411 *
1412 * Suspend/resume support is implemented in the usb-serial core,
1413 * so fill in the PM-related fields in udriver.
Alan Stern765e0ba2012-02-23 14:55:59 -05001414 */
Greg Kroah-Hartman68e24112012-05-08 15:46:14 -07001415 udriver = kzalloc(sizeof(*udriver), GFP_KERNEL);
1416 if (!udriver)
1417 return -ENOMEM;
Alan Stern765e0ba2012-02-23 14:55:59 -05001418
Greg Kroah-Hartman68e24112012-05-08 15:46:14 -07001419 udriver->name = name;
Alan Stern765e0ba2012-02-23 14:55:59 -05001420 udriver->no_dynamic_id = 1;
Alan Stern5cbe61c2012-05-07 11:20:06 -04001421 udriver->supports_autosuspend = 1;
1422 udriver->suspend = usb_serial_suspend;
1423 udriver->resume = usb_serial_resume;
Greg Kroah-Hartman5026bb02012-05-07 13:48:33 -07001424 udriver->probe = usb_serial_probe;
Greg Kroah-Hartman32078f92012-05-07 14:02:13 -07001425 udriver->disconnect = usb_serial_disconnect;
Greg Kroah-Hartman71863642012-05-15 15:40:00 -07001426
1427 /* we only set the reset_resume field if the serial_driver has one */
1428 for (sd = serial_drivers; *sd; ++sd) {
Greg Kroah-Hartman44b0f082012-09-19 08:15:21 +01001429 if ((*sd)->reset_resume) {
Greg Kroah-Hartman71863642012-05-15 15:40:00 -07001430 udriver->reset_resume = usb_serial_reset_resume;
1431 break;
Greg Kroah-Hartman44b0f082012-09-19 08:15:21 +01001432 }
Greg Kroah-Hartman71863642012-05-15 15:40:00 -07001433 }
1434
Alan Stern765e0ba2012-02-23 14:55:59 -05001435 rc = usb_register(udriver);
1436 if (rc)
Alexey Klimov647024a2016-08-08 02:34:46 +01001437 goto failed_usb_register;
Alan Stern765e0ba2012-02-23 14:55:59 -05001438
1439 for (sd = serial_drivers; *sd; ++sd) {
1440 (*sd)->usb_driver = udriver;
1441 rc = usb_serial_register(*sd);
1442 if (rc)
1443 goto failed;
1444 }
1445
Greg Kroah-Hartman68e24112012-05-08 15:46:14 -07001446 /* Now set udriver's id_table and look for matches */
1447 udriver->id_table = id_table;
Alan Stern765e0ba2012-02-23 14:55:59 -05001448 rc = driver_attach(&udriver->drvwrap.driver);
1449 return 0;
1450
1451 failed:
1452 while (sd-- > serial_drivers)
1453 usb_serial_deregister(*sd);
1454 usb_deregister(udriver);
Alexey Klimov647024a2016-08-08 02:34:46 +01001455failed_usb_register:
1456 kfree(udriver);
Alan Stern765e0ba2012-02-23 14:55:59 -05001457 return rc;
1458}
1459EXPORT_SYMBOL_GPL(usb_serial_register_drivers);
1460
1461/**
1462 * usb_serial_deregister_drivers - deregister drivers for a usb-serial module
Alan Stern765e0ba2012-02-23 14:55:59 -05001463 * @serial_drivers: NULL-terminated array of pointers to drivers to be deregistered
1464 *
Greg Kroah-Hartman68e24112012-05-08 15:46:14 -07001465 * Deregisters all the drivers in the @serial_drivers array and deregisters and
1466 * frees the struct usb_driver that was created by the call to
1467 * usb_serial_register_drivers().
Alan Stern765e0ba2012-02-23 14:55:59 -05001468 */
Greg Kroah-Hartman68e24112012-05-08 15:46:14 -07001469void usb_serial_deregister_drivers(struct usb_serial_driver *const serial_drivers[])
Alan Stern765e0ba2012-02-23 14:55:59 -05001470{
Greg Kroah-Hartman68e24112012-05-08 15:46:14 -07001471 struct usb_driver *udriver = (*serial_drivers)->usb_driver;
1472
Alan Stern765e0ba2012-02-23 14:55:59 -05001473 for (; *serial_drivers; ++serial_drivers)
1474 usb_serial_deregister(*serial_drivers);
1475 usb_deregister(udriver);
Greg Kroah-Hartman68e24112012-05-08 15:46:14 -07001476 kfree(udriver);
Alan Stern765e0ba2012-02-23 14:55:59 -05001477}
1478EXPORT_SYMBOL_GPL(usb_serial_deregister_drivers);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479
Alan Coxa8d6f0a2008-07-22 11:12:24 +01001480MODULE_AUTHOR(DRIVER_AUTHOR);
1481MODULE_DESCRIPTION(DRIVER_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482MODULE_LICENSE("GPL");