summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-04-20 17:22:51 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-04-20 17:22:51 +0200
commit8ebe0e20bf483de2860073898f08cbdf855e93e0 (patch)
tree882f8e11ca110620b6bbbe84cbb57054de5abd77 /drivers/usb
parent6fc091fb0459ade939a795bfdcaf645385b951d4 (diff)
parent31c5d1922b90ddc1da6a6ddecef7cd31f17aa32b (diff)
downloadlinux-8ebe0e20bf483de2860073898f08cbdf855e93e0.tar.gz
linux-8ebe0e20bf483de2860073898f08cbdf855e93e0.tar.bz2
linux-8ebe0e20bf483de2860073898f08cbdf855e93e0.zip
Merge tag 'usb-serial-4.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial into usb-next
Johan writes: USB-serial updates for v4.12-rc1 Here are the USB-serial updates for 4.12, including: - support for devices with up to 16 ports (e.g. some Moxa devices) - support for endpoint sanity checks in core, which allows for code sharing and avoids allocating resources for rejected interfaces - support for endpoint-port remapping, which allows some driver hacks to be removed as well as omninet to use the generic write implementation - removal of an obsolete tty open-race workaround which prevented a port from being opened immediately after having been registered - generic-driver support for interfaces with just a bulk-in endpoint - improved ftdi_sio event-char and latency-timer handling - improved ftdi_sio support for some broken BM chips Included are also various clean ups and a new ftdi_sio device id. All have been in linux-next with no reported issues. Signed-off-by: Johan Hovold <johan@kernel.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/serial/aircable.c36
-rw-r--r--drivers/usb/serial/ark3116.c17
-rw-r--r--drivers/usb/serial/cyberjack.c11
-rw-r--r--drivers/usb/serial/digi_acceleport.c23
-rw-r--r--drivers/usb/serial/f81534.c137
-rw-r--r--drivers/usb/serial/ftdi_sio.c54
-rw-r--r--drivers/usb/serial/ftdi_sio_ids.h6
-rw-r--r--drivers/usb/serial/generic.c32
-rw-r--r--drivers/usb/serial/io_edgeport.c28
-rw-r--r--drivers/usb/serial/io_ti.c49
-rw-r--r--drivers/usb/serial/ipaq.c51
-rw-r--r--drivers/usb/serial/iuu_phoenix.c22
-rw-r--r--drivers/usb/serial/keyspan_pda.c16
-rw-r--r--drivers/usb/serial/kobil_sct.c13
-rw-r--r--drivers/usb/serial/mos7720.c75
-rw-r--r--drivers/usb/serial/mos7840.c36
-rw-r--r--drivers/usb/serial/mxuport.c133
-rw-r--r--drivers/usb/serial/omninet.c130
-rw-r--r--drivers/usb/serial/opticon.c12
-rw-r--r--drivers/usb/serial/oti6858.c19
-rw-r--r--drivers/usb/serial/pl2303.c82
-rw-r--r--drivers/usb/serial/quatech2.c7
-rw-r--r--drivers/usb/serial/sierra.c3
-rw-r--r--drivers/usb/serial/spcp8x5.c16
-rw-r--r--drivers/usb/serial/symbolserial.c12
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c10
-rw-r--r--drivers/usb/serial/usb-serial.c230
-rw-r--r--drivers/usb/serial/usb_debug.c2
-rw-r--r--drivers/usb/serial/visor.c146
-rw-r--r--drivers/usb/serial/whiteheat.c32
30 files changed, 517 insertions, 923 deletions
diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c
index 80a9845cd93f..569c2200ba42 100644
--- a/drivers/usb/serial/aircable.c
+++ b/drivers/usb/serial/aircable.c
@@ -29,12 +29,6 @@
* is any other control code, I will simply check for the first
* one.
*
- * The driver registers himself with the USB-serial core and the USB Core. I had
- * to implement a probe function against USB-serial, because other way, the
- * driver was attaching himself to both interfaces. I have tried with different
- * configurations of usb_serial_driver with out exit, only the probe function
- * could handle this correctly.
- *
* I have taken some info from a Greg Kroah-Hartman article:
* http://www.linuxjournal.com/article/6573
* And from Linux Device Driver Kit CD, which is a great work, the authors taken
@@ -93,30 +87,17 @@ static int aircable_prepare_write_buffer(struct usb_serial_port *port,
return count + HCI_HEADER_LENGTH;
}
-static int aircable_probe(struct usb_serial *serial,
- const struct usb_device_id *id)
+static int aircable_calc_num_ports(struct usb_serial *serial,
+ struct usb_serial_endpoints *epds)
{
- struct usb_host_interface *iface_desc = serial->interface->
- cur_altsetting;
- struct usb_endpoint_descriptor *endpoint;
- int num_bulk_out = 0;
- int i;
-
- for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
- endpoint = &iface_desc->endpoint[i].desc;
- if (usb_endpoint_is_bulk_out(endpoint)) {
- dev_dbg(&serial->dev->dev,
- "found bulk out on endpoint %d\n", i);
- ++num_bulk_out;
- }
- }
-
- if (num_bulk_out == 0) {
- dev_dbg(&serial->dev->dev, "Invalid interface, discarding\n");
+ /* Ignore the first interface, which has no bulk endpoints. */
+ if (epds->num_bulk_out == 0) {
+ dev_dbg(&serial->interface->dev,
+ "ignoring interface with no bulk-out endpoints\n");
return -ENODEV;
}
- return 0;
+ return 1;
}
static int aircable_process_packet(struct usb_serial_port *port,
@@ -164,9 +145,8 @@ static struct usb_serial_driver aircable_device = {
.name = "aircable",
},
.id_table = id_table,
- .num_ports = 1,
.bulk_out_size = HCI_COMPLETE_FRAME,
- .probe = aircable_probe,
+ .calc_num_ports = aircable_calc_num_ports,
.process_read_urb = aircable_process_read_urb,
.prepare_write_buffer = aircable_prepare_write_buffer,
.throttle = usb_serial_generic_throttle,
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index 2779e59c30f1..0adbd38b4eea 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -122,19 +122,6 @@ static inline int calc_divisor(int bps)
return (12000000 + 2*bps) / (4*bps);
}
-static int ark3116_attach(struct usb_serial *serial)
-{
- /* make sure we have our end-points */
- if (serial->num_bulk_in == 0 ||
- serial->num_bulk_out == 0 ||
- serial->num_interrupt_in == 0) {
- dev_err(&serial->interface->dev, "missing endpoint\n");
- return -ENODEV;
- }
-
- return 0;
-}
-
static int ark3116_port_probe(struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
@@ -671,7 +658,9 @@ static struct usb_serial_driver ark3116_device = {
},
.id_table = id_table,
.num_ports = 1,
- .attach = ark3116_attach,
+ .num_bulk_in = 1,
+ .num_bulk_out = 1,
+ .num_interrupt_in = 1,
.port_probe = ark3116_port_probe,
.port_remove = ark3116_port_remove,
.set_termios = ark3116_set_termios,
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index 80260b08398b..47fbd9f0c0c7 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -50,7 +50,6 @@
#define CYBERJACK_PRODUCT_ID 0x0100
/* Function prototypes */
-static int cyberjack_attach(struct usb_serial *serial);
static int cyberjack_port_probe(struct usb_serial_port *port);
static int cyberjack_port_remove(struct usb_serial_port *port);
static int cyberjack_open(struct tty_struct *tty,
@@ -78,7 +77,7 @@ static struct usb_serial_driver cyberjack_device = {
.description = "Reiner SCT Cyberjack USB card reader",
.id_table = id_table,
.num_ports = 1,
- .attach = cyberjack_attach,
+ .num_bulk_out = 1,
.port_probe = cyberjack_port_probe,
.port_remove = cyberjack_port_remove,
.open = cyberjack_open,
@@ -102,14 +101,6 @@ struct cyberjack_private {
short wrsent; /* Data already sent */
};
-static int cyberjack_attach(struct usb_serial *serial)
-{
- if (serial->num_bulk_out < serial->num_ports)
- return -ENODEV;
-
- return 0;
-}
-
static int cyberjack_port_probe(struct usb_serial_port *port)
{
struct cyberjack_private *priv;
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index 6537d3ca2797..2ce39af32cfa 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -273,6 +273,8 @@ static struct usb_serial_driver digi_acceleport_2_device = {
.description = "Digi 2 port USB adapter",
.id_table = id_table_2,
.num_ports = 3,
+ .num_bulk_in = 4,
+ .num_bulk_out = 4,
.open = digi_open,
.close = digi_close,
.dtr_rts = digi_dtr_rts,
@@ -302,6 +304,8 @@ static struct usb_serial_driver digi_acceleport_4_device = {
.description = "Digi 4 port USB adapter",
.id_table = id_table_4,
.num_ports = 4,
+ .num_bulk_in = 5,
+ .num_bulk_out = 5,
.open = digi_open,
.close = digi_close,
.write = digi_write,
@@ -1251,27 +1255,8 @@ static int digi_port_init(struct usb_serial_port *port, unsigned port_num)
static int digi_startup(struct usb_serial *serial)
{
- struct device *dev = &serial->interface->dev;
struct digi_serial *serial_priv;
int ret;
- int i;
-
- /* check whether the device has the expected number of endpoints */
- if (serial->num_port_pointers < serial->type->num_ports + 1) {
- dev_err(dev, "OOB endpoints missing\n");
- return -ENODEV;
- }
-
- for (i = 0; i < serial->type->num_ports + 1 ; i++) {
- if (!serial->port[i]->read_urb) {
- dev_err(dev, "bulk-in endpoint missing\n");
- return -ENODEV;
- }
- if (!serial->port[i]->write_urb) {
- dev_err(dev, "bulk-out endpoint missing\n");
- return -ENODEV;
- }
- }
serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL);
if (!serial_priv)
diff --git a/drivers/usb/serial/f81534.c b/drivers/usb/serial/f81534.c
index 22f23a429a95..3d616a2a9f96 100644
--- a/drivers/usb/serial/f81534.c
+++ b/drivers/usb/serial/f81534.c
@@ -611,20 +611,30 @@ static int f81534_find_config_idx(struct usb_serial *serial, u8 *index)
* The f81534_calc_num_ports() will run to "new style" with checking
* F81534_PORT_UNAVAILABLE section.
*/
-static int f81534_calc_num_ports(struct usb_serial *serial)
+static int f81534_calc_num_ports(struct usb_serial *serial,
+ struct usb_serial_endpoints *epds)
{
+ struct device *dev = &serial->interface->dev;
+ int size_bulk_in = usb_endpoint_maxp(epds->bulk_in[0]);
+ int size_bulk_out = usb_endpoint_maxp(epds->bulk_out[0]);
u8 setting[F81534_CUSTOM_DATA_SIZE];
u8 setting_idx;
u8 num_port = 0;
int status;
size_t i;
+ if (size_bulk_out != F81534_WRITE_BUFFER_SIZE ||
+ size_bulk_in != F81534_MAX_RECEIVE_BLOCK_SIZE) {
+ dev_err(dev, "unsupported endpoint max packet size\n");
+ return -ENODEV;
+ }
+
/* Check had custom setting */
status = f81534_find_config_idx(serial, &setting_idx);
if (status) {
dev_err(&serial->interface->dev, "%s: find idx failed: %d\n",
__func__, status);
- return 0;
+ return status;
}
/*
@@ -640,7 +650,7 @@ static int f81534_calc_num_ports(struct usb_serial *serial)
dev_err(&serial->interface->dev,
"%s: get custom data failed: %d\n",
__func__, status);
- return 0;
+ return status;
}
dev_dbg(&serial->interface->dev,
@@ -656,7 +666,7 @@ static int f81534_calc_num_ports(struct usb_serial *serial)
dev_err(&serial->interface->dev,
"%s: read failed: %d\n", __func__,
status);
- return 0;
+ return status;
}
dev_dbg(&serial->interface->dev, "%s: read default config\n",
@@ -671,12 +681,24 @@ static int f81534_calc_num_ports(struct usb_serial *serial)
++num_port;
}
- if (num_port)
- return num_port;
+ if (!num_port) {
+ dev_warn(&serial->interface->dev,
+ "no config found, assuming 4 ports\n");
+ num_port = 4; /* Nothing found, oldest version IC */
+ }
+
+ /*
+ * Setup bulk-out endpoint multiplexing. All ports share the same
+ * bulk-out endpoint.
+ */
+ BUILD_BUG_ON(ARRAY_SIZE(epds->bulk_out) < F81534_NUM_PORT);
+
+ for (i = 1; i < num_port; ++i)
+ epds->bulk_out[i] = epds->bulk_out[0];
- dev_warn(&serial->interface->dev, "%s: Read Failed. default 4 ports\n",
- __func__);
- return 4; /* Nothing found, oldest version IC */
+ epds->num_bulk_out = num_port;
+
+ return num_port;
}
static void f81534_set_termios(struct tty_struct *tty,
@@ -1067,96 +1089,6 @@ static void f81534_write_usb_callback(struct urb *urb)
}
}
-static int f81534_setup_ports(struct usb_serial *serial)
-{
- struct usb_serial_port *port;
- u8 port0_out_address;
- int buffer_size;
- size_t i;
-
- /*
- * In our system architecture, we had 2 or 4 serial ports,
- * but only get 1 set of bulk in/out endpoints.
- *
- * The usb-serial subsystem will generate port 0 data,
- * but port 1/2/3 will not. It's will generate write URB and buffer
- * by following code and use the port0 read URB for read operation.
- */
- for (i = 1; i < serial->num_ports; ++i) {
- port0_out_address = serial->port[0]->bulk_out_endpointAddress;
- buffer_size = serial->port[0]->bulk_out_size;
- port = serial->port[i];
-
- if (kfifo_alloc(&port->write_fifo, PAGE_SIZE, GFP_KERNEL))
- return -ENOMEM;
-
- port->bulk_out_size = buffer_size;
- port->bulk_out_endpointAddress = port0_out_address;
-
- port->write_urbs[0] = usb_alloc_urb(0, GFP_KERNEL);
- if (!port->write_urbs[0])
- return -ENOMEM;
-
- port->bulk_out_buffers[0] = kzalloc(buffer_size, GFP_KERNEL);
- if (!port->bulk_out_buffers[0])
- return -ENOMEM;
-
- usb_fill_bulk_urb(port->write_urbs[0], serial->dev,
- usb_sndbulkpipe(serial->dev,
- port0_out_address),
- port->bulk_out_buffers[0], buffer_size,
- serial->type->write_bulk_callback, port);
-
- port->write_urb = port->write_urbs[0];
- port->bulk_out_buffer = port->bulk_out_buffers[0];
- }
-
- return 0;
-}
-
-static int f81534_probe(struct usb_serial *serial,
- const struct usb_device_id *id)
-{
- struct usb_endpoint_descriptor *endpoint;
- struct usb_host_interface *iface_desc;
- struct device *dev;
- int num_bulk_in = 0;
- int num_bulk_out = 0;
- int size_bulk_in = 0;
- int size_bulk_out = 0;
- int i;
-
- dev = &serial->interface->dev;
- iface_desc = serial->interface->cur_altsetting;
-
- for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
- endpoint = &iface_desc->endpoint[i].desc;
-
- if (usb_endpoint_is_bulk_in(endpoint)) {
- ++num_bulk_in;
- size_bulk_in = usb_endpoint_maxp(endpoint);
- }
-
- if (usb_endpoint_is_bulk_out(endpoint)) {
- ++num_bulk_out;
- size_bulk_out = usb_endpoint_maxp(endpoint);
- }
- }
-
- if (num_bulk_in != 1 || num_bulk_out != 1) {
- dev_err(dev, "expected endpoints not found\n");
- return -ENODEV;
- }
-
- if (size_bulk_out != F81534_WRITE_BUFFER_SIZE ||
- size_bulk_in != F81534_MAX_RECEIVE_BLOCK_SIZE) {
- dev_err(dev, "unsupported endpoint max packet size\n");
- return -ENODEV;
- }
-
- return 0;
-}
-
static int f81534_attach(struct usb_serial *serial)
{
struct f81534_serial_private *serial_priv;
@@ -1173,10 +1105,6 @@ static int f81534_attach(struct usb_serial *serial)
mutex_init(&serial_priv->urb_mutex);
- status = f81534_setup_ports(serial);
- if (status)
- return status;
-
/* Check had custom setting */
status = f81534_find_config_idx(serial, &serial_priv->setting_idx);
if (status) {
@@ -1380,12 +1308,13 @@ static struct usb_serial_driver f81534_device = {
},
.description = DRIVER_DESC,
.id_table = f81534_id_table,
+ .num_bulk_in = 1,
+ .num_bulk_out = 1,
.open = f81534_open,
.close = f81534_close,
.write = f81534_write,
.tx_empty = f81534_tx_empty,
.calc_num_ports = f81534_calc_num_ports,
- .probe = f81534_probe,
.attach = f81534_attach,
.port_probe = f81534_port_probe,
.dtr_rts = f81534_dtr_rts,
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index c540de15aad2..d38780fa8788 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -873,6 +873,7 @@ static const struct usb_device_id id_table_combined[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID,
USB_CLASS_VENDOR_SPEC,
USB_SUBCLASS_VENDOR_SPEC, 0x00) },
+ { USB_DEVICE_INTERFACE_NUMBER(ACTEL_VID, MICROSEMI_ARROW_SF2PLUS_BOARD_PID, 2) },
{ USB_DEVICE(JETI_VID, JETI_SPC1201_PID) },
{ USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
@@ -1406,6 +1407,9 @@ static int write_latency_timer(struct usb_serial_port *port)
int rv;
int l = priv->latency;
+ if (priv->chip_type == SIO || priv->chip_type == FT8U232AM)
+ return -EINVAL;
+
if (priv->flags & ASYNC_LOW_LATENCY)
l = 1;
@@ -1422,7 +1426,7 @@ static int write_latency_timer(struct usb_serial_port *port)
return rv;
}
-static int read_latency_timer(struct usb_serial_port *port)
+static int _read_latency_timer(struct usb_serial_port *port)
{
struct ftdi_private *priv = usb_get_serial_port_data(port);
struct usb_device *udev = port->serial->dev;
@@ -1440,11 +1444,10 @@ static int read_latency_timer(struct usb_serial_port *port)
0, priv->interface,
buf, 1, WDR_TIMEOUT);
if (rv < 1) {
- dev_err(&port->dev, "Unable to read latency timer: %i\n", rv);
if (rv >= 0)
rv = -EIO;
} else {
- priv->latency = buf[0];
+ rv = buf[0];
}
kfree(buf);
@@ -1452,6 +1455,25 @@ static int read_latency_timer(struct usb_serial_port *port)
return rv;
}
+static int read_latency_timer(struct usb_serial_port *port)
+{
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
+ int rv;
+
+ if (priv->chip_type == SIO || priv->chip_type == FT8U232AM)
+ return -EINVAL;
+
+ rv = _read_latency_timer(port);
+ if (rv < 0) {
+ dev_err(&port->dev, "Unable to read latency timer: %i\n", rv);
+ return rv;
+ }
+
+ priv->latency = rv;
+
+ return 0;
+}
+
static int get_serial_info(struct usb_serial_port *port,
struct serial_struct __user *retinfo)
{
@@ -1603,9 +1625,19 @@ static void ftdi_determine_type(struct usb_serial_port *port)
priv->baud_base = 12000000 / 16;
} else if (version < 0x400) {
/* Assume it's an FT8U232AM (or FT8U245AM) */
- /* (It might be a BM because of the iSerialNumber bug,
- * but it will still work as an AM device.) */
priv->chip_type = FT8U232AM;
+ /*
+ * It might be a BM type because of the iSerialNumber bug.
+ * If iSerialNumber==0 and the latency timer is readable,
+ * assume it is BM type.
+ */
+ if (udev->descriptor.iSerialNumber == 0 &&
+ _read_latency_timer(port) >= 0) {
+ dev_dbg(&port->dev,
+ "%s: has latency timer so not an AM type\n",
+ __func__);
+ priv->chip_type = FT232BM;
+ }
} else if (version < 0x600) {
/* Assume it's an FT232BM (or FT245BM) */
priv->chip_type = FT232BM;
@@ -1685,9 +1717,12 @@ static ssize_t latency_timer_store(struct device *dev,
{
struct usb_serial_port *port = to_usb_serial_port(dev);
struct ftdi_private *priv = usb_get_serial_port_data(port);
- int v = simple_strtoul(valbuf, NULL, 10);
+ u8 v;
int rv;
+ if (kstrtou8(valbuf, 10, &v))
+ return -EINVAL;
+
priv->latency = v;
rv = write_latency_timer(port);
if (rv < 0)
@@ -1704,10 +1739,13 @@ static ssize_t store_event_char(struct device *dev,
struct usb_serial_port *port = to_usb_serial_port(dev);
struct ftdi_private *priv = usb_get_serial_port_data(port);
struct usb_device *udev = port->serial->dev;
- int v = simple_strtoul(valbuf, NULL, 10);
+ unsigned int v;
int rv;
- dev_dbg(&port->dev, "%s: setting event char = %i\n", __func__, v);
+ if (kstrtouint(valbuf, 0, &v) || v >= 0x200)
+ return -EINVAL;
+
+ dev_dbg(&port->dev, "%s: setting event char = 0x%03x\n", __func__, v);
rv = usb_control_msg(udev,
usb_sndctrlpipe(udev, 0),
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index 48ee04c94a75..71fb9e59db71 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -873,6 +873,12 @@
#define FIC_VID 0x1457
#define FIC_NEO1973_DEBUG_PID 0x5118
+/*
+ * Actel / Microsemi
+ */
+#define ACTEL_VID 0x1514
+#define MICROSEMI_ARROW_SF2PLUS_BOARD_PID 0x2008
+
/* Olimex */
#define OLIMEX_VID 0x15BA
#define OLIMEX_ARM_USB_OCD_PID 0x0003
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 49ce2be90fa0..35cb8c0e584f 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -37,13 +37,41 @@ MODULE_PARM_DESC(product, "User specified USB idProduct");
static struct usb_device_id generic_device_ids[2]; /* Initially all zeroes. */
-struct usb_serial_driver usb_serial_generic_device = {
+static int usb_serial_generic_probe(struct usb_serial *serial,
+ const struct usb_device_id *id)
+{
+ struct device *dev = &serial->interface->dev;
+
+ dev_info(dev, "The \"generic\" usb-serial driver is only for testing and one-off prototypes.\n");
+ dev_info(dev, "Tell linux-usb@vger.kernel.org to add your device to a proper driver.\n");
+
+ return 0;
+}
+
+static int usb_serial_generic_calc_num_ports(struct usb_serial *serial,
+ struct usb_serial_endpoints *epds)
+{
+ struct device *dev = &serial->interface->dev;
+ int num_ports;
+
+ num_ports = max(epds->num_bulk_in, epds->num_bulk_out);
+
+ if (num_ports == 0) {
+ dev_err(dev, "device has no bulk endpoints\n");
+ return -ENODEV;
+ }
+
+ return num_ports;
+}
+
+static struct usb_serial_driver usb_serial_generic_device = {
.driver = {
.owner = THIS_MODULE,
.name = "generic",
},
.id_table = generic_device_ids,
- .num_ports = 1,
+ .probe = usb_serial_generic_probe,
+ .calc_num_ports = usb_serial_generic_calc_num_ports,
.throttle = usb_serial_generic_throttle,
.unthrottle = usb_serial_generic_unthrottle,
.resume = usb_serial_generic_resume,
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index bb7673e80a57..bdf8bd814a9a 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -1544,11 +1544,6 @@ static void edge_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
{
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
- unsigned int cflag;
-
- cflag = tty->termios.c_cflag;
- dev_dbg(&port->dev, "%s - clfag %08x iflag %08x\n", __func__, tty->termios.c_cflag, tty->termios.c_iflag);
- dev_dbg(&port->dev, "%s - old clfag %08x old iflag %08x\n", __func__, old_termios->c_cflag, old_termios->c_iflag);
if (edge_port == NULL)
return;
@@ -2844,14 +2839,9 @@ static int edge_startup(struct usb_serial *serial)
bool interrupt_in_found;
bool bulk_in_found;
bool bulk_out_found;
- static __u32 descriptor[3] = { EDGE_COMPATIBILITY_MASK0,
- EDGE_COMPATIBILITY_MASK1,
- EDGE_COMPATIBILITY_MASK2 };
-
- if (serial->num_bulk_in < 1 || serial->num_interrupt_in < 1) {
- dev_err(&serial->interface->dev, "missing endpoints\n");
- return -ENODEV;
- }
+ static const __u32 descriptor[3] = { EDGE_COMPATIBILITY_MASK0,
+ EDGE_COMPATIBILITY_MASK1,
+ EDGE_COMPATIBILITY_MASK2 };
dev = serial->dev;
@@ -3120,6 +3110,9 @@ static struct usb_serial_driver edgeport_2port_device = {
.description = "Edgeport 2 port adapter",
.id_table = edgeport_2port_id_table,
.num_ports = 2,
+ .num_bulk_in = 1,
+ .num_bulk_out = 1,
+ .num_interrupt_in = 1,
.open = edge_open,
.close = edge_close,
.throttle = edge_throttle,
@@ -3152,6 +3145,9 @@ static struct usb_serial_driver edgeport_4port_device = {
.description = "Edgeport 4 port adapter",
.id_table = edgeport_4port_id_table,
.num_ports = 4,
+ .num_bulk_in = 1,
+ .num_bulk_out = 1,
+ .num_interrupt_in = 1,
.open = edge_open,
.close = edge_close,
.throttle = edge_throttle,
@@ -3184,6 +3180,9 @@ static struct usb_serial_driver edgeport_8port_device = {
.description = "Edgeport 8 port adapter",
.id_table = edgeport_8port_id_table,
.num_ports = 8,
+ .num_bulk_in = 1,
+ .num_bulk_out = 1,
+ .num_interrupt_in = 1,
.open = edge_open,
.close = edge_close,
.throttle = edge_throttle,
@@ -3216,6 +3215,9 @@ static struct usb_serial_driver epic_device = {
.description = "EPiC device",
.id_table = Epic_port_id_table,
.num_ports = 1,
+ .num_bulk_in = 1,
+ .num_bulk_out = 1,
+ .num_interrupt_in = 1,
.open = edge_open,
.close = edge_close,
.throttle = edge_throttle,
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index a76b95d32157..87798e625d6c 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -1933,13 +1933,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
if (edge_serial->num_ports_open == 0) {
/* we are the first port to open, post the interrupt urb */
urb = edge_serial->serial->port[0]->interrupt_in_urb;
- if (!urb) {
- dev_err(&port->dev,
- "%s - no interrupt urb present, exiting\n",
- __func__);
- status = -EINVAL;
- goto release_es_lock;
- }
urb->context = edge_serial;
status = usb_submit_urb(urb, GFP_KERNEL);
if (status) {
@@ -1959,12 +1952,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
/* start up our bulk read urb */
urb = port->read_urb;
- if (!urb) {
- dev_err(&port->dev, "%s - no read urb present, exiting\n",
- __func__);
- status = -EINVAL;
- goto unlink_int_urb;
- }
edge_port->ep_read_urb_state = EDGE_READ_URB_RUNNING;
urb->context = edge_port;
status = usb_submit_urb(urb, GFP_KERNEL);
@@ -2385,14 +2372,6 @@ static void edge_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
{
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
- unsigned int cflag;
-
- cflag = tty->termios.c_cflag;
-
- dev_dbg(&port->dev, "%s - clfag %08x iflag %08x\n", __func__,
- tty->termios.c_cflag, tty->termios.c_iflag);
- dev_dbg(&port->dev, "%s - old clfag %08x old iflag %08x\n", __func__,
- old_termios->c_cflag, old_termios->c_iflag);
if (edge_port == NULL)
return;
@@ -2544,19 +2523,31 @@ static void edge_heartbeat_work(struct work_struct *work)
edge_heartbeat_schedule(serial);
}
-static int edge_startup(struct usb_serial *serial)
+static int edge_calc_num_ports(struct usb_serial *serial,
+ struct usb_serial_endpoints *epds)
{
- struct edgeport_serial *edge_serial;
- int status;
- u16 product_id;
+ struct device *dev = &serial->interface->dev;
+ unsigned char num_ports = serial->type->num_ports;
/* Make sure we have the required endpoints when in download mode. */
if (serial->interface->cur_altsetting->desc.bNumEndpoints > 1) {
- if (serial->num_bulk_in < serial->num_ports ||
- serial->num_bulk_out < serial->num_ports)
+ if (epds->num_bulk_in < num_ports ||
+ epds->num_bulk_out < num_ports ||
+ epds->num_interrupt_in < 1) {
+ dev_err(dev, "required endpoints missing\n");
return -ENODEV;
+ }
}
+ return num_ports;
+}
+
+static int edge_startup(struct usb_serial *serial)
+{
+ struct edgeport_serial *edge_serial;
+ int status;
+ u16 product_id;
+
/* create our private serial structure */
edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL);
if (!edge_serial)
@@ -2736,11 +2727,13 @@ static struct usb_serial_driver edgeport_1port_device = {
.description = "Edgeport TI 1 port adapter",
.id_table = edgeport_1port_id_table,
.num_ports = 1,
+ .num_bulk_out = 1,
.open = edge_open,
.close = edge_close,
.throttle = edge_throttle,
.unthrottle = edge_unthrottle,
.attach = edge_startup,
+ .calc_num_ports = edge_calc_num_ports,
.disconnect = edge_disconnect,
.release = edge_release,
.port_probe = edge_port_probe,
@@ -2773,11 +2766,13 @@ static struct usb_serial_driver edgeport_2port_device = {
.description = "Edgeport TI 2 port adapter",
.id_table = edgeport_2port_id_table,
.num_ports = 2,
+ .num_bulk_out = 1,
.open = edge_open,