Commit 8ebe0e20 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'usb-serial-4.12-rc1' of...

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: default avatarJohan Hovold <johan@kernel.org>
parents 6fc091fb 31c5d192
...@@ -29,12 +29,6 @@ ...@@ -29,12 +29,6 @@
* is any other control code, I will simply check for the first * is any other control code, I will simply check for the first
* one. * 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: * I have taken some info from a Greg Kroah-Hartman article:
* http://www.linuxjournal.com/article/6573 * http://www.linuxjournal.com/article/6573
* And from Linux Device Driver Kit CD, which is a great work, the authors taken * 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, ...@@ -93,30 +87,17 @@ static int aircable_prepare_write_buffer(struct usb_serial_port *port,
return count + HCI_HEADER_LENGTH; return count + HCI_HEADER_LENGTH;
} }
static int aircable_probe(struct usb_serial *serial, static int aircable_calc_num_ports(struct usb_serial *serial,
const struct usb_device_id *id) struct usb_serial_endpoints *epds)
{ {
struct usb_host_interface *iface_desc = serial->interface-> /* Ignore the first interface, which has no bulk endpoints. */
cur_altsetting; if (epds->num_bulk_out == 0) {
struct usb_endpoint_descriptor *endpoint; dev_dbg(&serial->interface->dev,
int num_bulk_out = 0; "ignoring interface with no bulk-out endpoints\n");
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");
return -ENODEV; return -ENODEV;
} }
return 0; return 1;
} }
static int aircable_process_packet(struct usb_serial_port *port, static int aircable_process_packet(struct usb_serial_port *port,
...@@ -164,9 +145,8 @@ static struct usb_serial_driver aircable_device = { ...@@ -164,9 +145,8 @@ static struct usb_serial_driver aircable_device = {
.name = "aircable", .name = "aircable",
}, },
.id_table = id_table, .id_table = id_table,
.num_ports = 1,
.bulk_out_size = HCI_COMPLETE_FRAME, .bulk_out_size = HCI_COMPLETE_FRAME,
.probe = aircable_probe, .calc_num_ports = aircable_calc_num_ports,
.process_read_urb = aircable_process_read_urb, .process_read_urb = aircable_process_read_urb,
.prepare_write_buffer = aircable_prepare_write_buffer, .prepare_write_buffer = aircable_prepare_write_buffer,
.throttle = usb_serial_generic_throttle, .throttle = usb_serial_generic_throttle,
......
...@@ -122,19 +122,6 @@ static inline int calc_divisor(int bps) ...@@ -122,19 +122,6 @@ static inline int calc_divisor(int bps)
return (12000000 + 2*bps) / (4*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) static int ark3116_port_probe(struct usb_serial_port *port)
{ {
struct usb_serial *serial = port->serial; struct usb_serial *serial = port->serial;
...@@ -671,7 +658,9 @@ static struct usb_serial_driver ark3116_device = { ...@@ -671,7 +658,9 @@ static struct usb_serial_driver ark3116_device = {
}, },
.id_table = id_table, .id_table = id_table,
.num_ports = 1, .num_ports = 1,
.attach = ark3116_attach, .num_bulk_in = 1,
.num_bulk_out = 1,
.num_interrupt_in = 1,
.port_probe = ark3116_port_probe, .port_probe = ark3116_port_probe,
.port_remove = ark3116_port_remove, .port_remove = ark3116_port_remove,
.set_termios = ark3116_set_termios, .set_termios = ark3116_set_termios,
......
...@@ -50,7 +50,6 @@ ...@@ -50,7 +50,6 @@
#define CYBERJACK_PRODUCT_ID 0x0100 #define CYBERJACK_PRODUCT_ID 0x0100
/* Function prototypes */ /* Function prototypes */
static int cyberjack_attach(struct usb_serial *serial);
static int cyberjack_port_probe(struct usb_serial_port *port); static int cyberjack_port_probe(struct usb_serial_port *port);
static int cyberjack_port_remove(struct usb_serial_port *port); static int cyberjack_port_remove(struct usb_serial_port *port);
static int cyberjack_open(struct tty_struct *tty, static int cyberjack_open(struct tty_struct *tty,
...@@ -78,7 +77,7 @@ static struct usb_serial_driver cyberjack_device = { ...@@ -78,7 +77,7 @@ static struct usb_serial_driver cyberjack_device = {
.description = "Reiner SCT Cyberjack USB card reader", .description = "Reiner SCT Cyberjack USB card reader",
.id_table = id_table, .id_table = id_table,
.num_ports = 1, .num_ports = 1,
.attach = cyberjack_attach, .num_bulk_out = 1,
.port_probe = cyberjack_port_probe, .port_probe = cyberjack_port_probe,
.port_remove = cyberjack_port_remove, .port_remove = cyberjack_port_remove,
.open = cyberjack_open, .open = cyberjack_open,
...@@ -102,14 +101,6 @@ struct cyberjack_private { ...@@ -102,14 +101,6 @@ struct cyberjack_private {
short wrsent; /* Data already sent */ 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) static int cyberjack_port_probe(struct usb_serial_port *port)
{ {
struct cyberjack_private *priv; struct cyberjack_private *priv;
......
...@@ -273,6 +273,8 @@ static struct usb_serial_driver digi_acceleport_2_device = { ...@@ -273,6 +273,8 @@ static struct usb_serial_driver digi_acceleport_2_device = {
.description = "Digi 2 port USB adapter", .description = "Digi 2 port USB adapter",
.id_table = id_table_2, .id_table = id_table_2,
.num_ports = 3, .num_ports = 3,
.num_bulk_in = 4,
.num_bulk_out = 4,
.open = digi_open, .open = digi_open,
.close = digi_close, .close = digi_close,
.dtr_rts = digi_dtr_rts, .dtr_rts = digi_dtr_rts,
...@@ -302,6 +304,8 @@ static struct usb_serial_driver digi_acceleport_4_device = { ...@@ -302,6 +304,8 @@ static struct usb_serial_driver digi_acceleport_4_device = {
.description = "Digi 4 port USB adapter", .description = "Digi 4 port USB adapter",
.id_table = id_table_4, .id_table = id_table_4,
.num_ports = 4, .num_ports = 4,
.num_bulk_in = 5,
.num_bulk_out = 5,
.open = digi_open, .open = digi_open,
.close = digi_close, .close = digi_close,
.write = digi_write, .write = digi_write,
...@@ -1251,27 +1255,8 @@ static int digi_port_init(struct usb_serial_port *port, unsigned port_num) ...@@ -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) static int digi_startup(struct usb_serial *serial)
{ {
struct device *dev = &serial->interface->dev;
struct digi_serial *serial_priv; struct digi_serial *serial_priv;
int ret; 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); serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL);
if (!serial_priv) if (!serial_priv)
......
...@@ -611,20 +611,30 @@ static int f81534_find_config_idx(struct usb_serial *serial, u8 *index) ...@@ -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 * The f81534_calc_num_ports() will run to "new style" with checking
* F81534_PORT_UNAVAILABLE section. * 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[F81534_CUSTOM_DATA_SIZE];
u8 setting_idx; u8 setting_idx;
u8 num_port = 0; u8 num_port = 0;
int status; int status;
size_t i; 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 */ /* Check had custom setting */
status = f81534_find_config_idx(serial, &setting_idx); status = f81534_find_config_idx(serial, &setting_idx);
if (status) { if (status) {
dev_err(&serial->interface->dev, "%s: find idx failed: %d\n", dev_err(&serial->interface->dev, "%s: find idx failed: %d\n",
__func__, status); __func__, status);
return 0; return status;
} }
/* /*
...@@ -640,7 +650,7 @@ static int f81534_calc_num_ports(struct usb_serial *serial) ...@@ -640,7 +650,7 @@ static int f81534_calc_num_ports(struct usb_serial *serial)
dev_err(&serial->interface->dev, dev_err(&serial->interface->dev,
"%s: get custom data failed: %d\n", "%s: get custom data failed: %d\n",
__func__, status); __func__, status);
return 0; return status;
} }
dev_dbg(&serial->interface->dev, dev_dbg(&serial->interface->dev,
...@@ -656,7 +666,7 @@ static int f81534_calc_num_ports(struct usb_serial *serial) ...@@ -656,7 +666,7 @@ static int f81534_calc_num_ports(struct usb_serial *serial)
dev_err(&serial->interface->dev, dev_err(&serial->interface->dev,
"%s: read failed: %d\n", __func__, "%s: read failed: %d\n", __func__,
status); status);
return 0; return status;
} }
dev_dbg(&serial->interface->dev, "%s: read default config\n", dev_dbg(&serial->interface->dev, "%s: read default config\n",
...@@ -671,12 +681,24 @@ static int f81534_calc_num_ports(struct usb_serial *serial) ...@@ -671,12 +681,24 @@ static int f81534_calc_num_ports(struct usb_serial *serial)
++num_port; ++num_port;
} }
if (num_port) if (!num_port) {
return 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", epds->num_bulk_out = num_port;
__func__);
return 4; /* Nothing found, oldest version IC */ return num_port;
} }
static void f81534_set_termios(struct tty_struct *tty, static void f81534_set_termios(struct tty_struct *tty,
...@@ -1067,96 +1089,6 @@ static void f81534_write_usb_callback(struct urb *urb) ...@@ -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) static int f81534_attach(struct usb_serial *serial)
{ {
struct f81534_serial_private *serial_priv; struct f81534_serial_private *serial_priv;
...@@ -1173,10 +1105,6 @@ static int f81534_attach(struct usb_serial *serial) ...@@ -1173,10 +1105,6 @@ static int f81534_attach(struct usb_serial *serial)
mutex_init(&serial_priv->urb_mutex); mutex_init(&serial_priv->urb_mutex);
status = f81534_setup_ports(serial);
if (status)
return status;
/* Check had custom setting */ /* Check had custom setting */
status = f81534_find_config_idx(serial, &serial_priv->setting_idx); status = f81534_find_config_idx(serial, &serial_priv->setting_idx);
if (status) { if (status) {
...@@ -1380,12 +1308,13 @@ static struct usb_serial_driver f81534_device = { ...@@ -1380,12 +1308,13 @@ static struct usb_serial_driver f81534_device = {
}, },
.description = DRIVER_DESC, .description = DRIVER_DESC,
.id_table = f81534_id_table, .id_table = f81534_id_table,
.num_bulk_in = 1,
.num_bulk_out = 1,
.open = f81534_open, .open = f81534_open,
.close = f81534_close, .close = f81534_close,
.write = f81534_write, .write = f81534_write,
.tx_empty = f81534_tx_empty, .tx_empty = f81534_tx_empty,
.calc_num_ports = f81534_calc_num_ports, .calc_num_ports = f81534_calc_num_ports,
.probe = f81534_probe,
.attach = f81534_attach, .attach = f81534_attach,
.port_probe = f81534_port_probe, .port_probe = f81534_port_probe,
.dtr_rts = f81534_dtr_rts, .dtr_rts = f81534_dtr_rts,
......
...@@ -873,6 +873,7 @@ static const struct usb_device_id id_table_combined[] = { ...@@ -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_DEVICE_AND_INTERFACE_INFO(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID,
USB_CLASS_VENDOR_SPEC, USB_CLASS_VENDOR_SPEC,
USB_SUBCLASS_VENDOR_SPEC, 0x00) }, 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(JETI_VID, JETI_SPC1201_PID) },
{ USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID), { USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
...@@ -1406,6 +1407,9 @@ static int write_latency_timer(struct usb_serial_port *port) ...@@ -1406,6 +1407,9 @@ static int write_latency_timer(struct usb_serial_port *port)
int rv; int rv;
int l = priv->latency; int l = priv->latency;
if (priv->chip_type == SIO || priv->chip_type == FT8U232AM)
return -EINVAL;
if (priv->flags & ASYNC_LOW_LATENCY) if (priv->flags & ASYNC_LOW_LATENCY)
l = 1; l = 1;
...@@ -1422,7 +1426,7 @@ static int write_latency_timer(struct usb_serial_port *port) ...@@ -1422,7 +1426,7 @@ static int write_latency_timer(struct usb_serial_port *port)
return rv; 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 ftdi_private *priv = usb_get_serial_port_data(port);
struct usb_device *udev = port->serial->dev; struct usb_device *udev = port->serial->dev;
...@@ -1440,11 +1444,10 @@ static int read_latency_timer(struct usb_serial_port *port) ...@@ -1440,11 +1444,10 @@ static int read_latency_timer(struct usb_serial_port *port)
0, priv->interface, 0, priv->interface,
buf, 1, WDR_TIMEOUT); buf, 1, WDR_TIMEOUT);
if (rv < 1) { if (rv < 1) {
dev_err(&port->dev, "Unable to read latency timer: %i\n", rv);
if (rv >= 0) if (rv >= 0)
rv = -EIO; rv = -EIO;
} else { } else {
priv->latency = buf[0]; rv = buf[0];
} }
kfree(buf); kfree(buf);
...@@ -1452,6 +1455,25 @@ static int read_latency_timer(struct usb_serial_port *port) ...@@ -1452,6 +1455,25 @@ static int read_latency_timer(struct usb_serial_port *port)
return rv; 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, static int get_serial_info(struct usb_serial_port *port,
struct serial_struct __user *retinfo) struct serial_struct __user *retinfo)
{ {
...@@ -1603,9 +1625,19 @@ static void ftdi_determine_type(struct usb_serial_port *port) ...@@ -1603,9 +1625,19 @@ static void ftdi_determine_type(struct usb_serial_port *port)
priv->baud_base = 12000000 / 16; priv->baud_base = 12000000 / 16;
} else if (version < 0x400) { } else if (version < 0x400) {
/* Assume it's an FT8U232AM (or FT8U245AM) */ /* 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; 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) { } else if (version < 0x600) {
/* Assume it's an FT232BM (or FT245BM) */ /* Assume it's an FT232BM (or FT245BM) */
priv->chip_type = FT232BM; priv->chip_type = FT232BM;
...@@ -1685,9 +1717,12 @@ static ssize_t latency_timer_store(struct device *dev, ...@@ -1685,9 +1717,12 @@ static ssize_t latency_timer_store(struct device *dev,
{ {
struct usb_serial_port *port = to_usb_serial_port(dev); struct usb_serial_port *port = to_usb_serial_port(dev);
struct ftdi_private *priv = usb_get_serial_port_data(port); struct ftdi_private *priv = usb_get_serial_port_data(port);
int v = simple_strtoul(valbuf, NULL, 10); u8 v;
int rv; int rv;
if (kstrtou8(valbuf, 10, &v))
return -EINVAL;
priv->latency = v; priv->latency = v;
rv = write_latency_timer(port); rv = write_latency_timer(port);
if (rv < 0) if (rv < 0)
...@@ -1704,10 +1739,13 @@ static ssize_t store_event_char(struct device *dev, ...@@ -1704,10 +1739,13 @@ static ssize_t store_event_char(struct device *dev,
struct usb_serial_port *port = to_usb_serial_port(dev); struct usb_serial_port *port = to_usb_serial_port(dev);
struct ftdi_private *priv = usb_get_serial_port_data(port); struct ftdi_private *priv = usb_get_serial_port_data(port);
struct usb_device *udev = port->serial->dev; struct usb_device *udev = port->serial->dev;
int v = simple_strtoul(valbuf, NULL, 10); unsigned int v;
int rv; 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, rv = usb_control_msg(udev,
usb_sndctrlpipe(udev, 0), usb_sndctrlpipe(udev, 0),
......
...@@ -873,6 +873,12 @@ ...@@ -873,6 +873,12 @@
#define FIC_VID 0x1457 #define FIC_VID 0x1457
#define FIC_NEO1973_DEBUG_PID 0x5118 #define FIC_NEO1973_DEBUG_PID 0x5118
/*
* Actel / Microsemi
*/
#define ACTEL_VID 0x1514
#define MICROSEMI_ARROW_SF2PLUS_BOARD_PID 0x2008
/* Olimex */ /* Olimex */
#define OLIMEX_VID 0x15BA #define OLIMEX_VID 0x15BA
#define OLIMEX_ARM_USB_OCD_PID 0x0003 #define OLIMEX_ARM_USB_OCD_PID 0x0003
......
...@@ -37,13 +37,41 @@ MODULE_PARM_DESC(product, "User specified USB idProduct"); ...@@ -37,13 +37,41 @@ MODULE_PARM_DESC(product, "User specified USB idProduct");
static struct usb_device_id generic_device_ids[2]; /* Initially all zeroes. */ 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 = { .driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "generic", .name = "generic",
}, },
.id_table = generic_device_ids, .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, .throttle = usb_serial_generic_throttle,
.unthrottle = usb_serial_generic_unthrottle, .unthrottle = usb_serial_generic_unthrottle,
.resume = usb_serial_generic_resume, .resume = usb_serial_generic_resume,
......
...@@ -1544,11 +1544,6 @@ static void edge_set_termios(struct tty_struct *tty, ...@@ -1544,11 +1544,6 @@ static void edge_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios) struct usb_serial_port *port, struct ktermios *old_termios)
{ {
struct edgeport_port *edge_port = usb_get_serial_port_data(port); 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) if (edge_port == NULL)
return; return;
...@@ -2844,14 +2839,9 @@ static int edge_startup(struct usb_serial *serial) ...@@ -2844,14 +2839,9 @@ static int edge_startup(struct usb_serial *serial)
bool interrupt_in_found; bool interrupt_in_found;
bool bulk_in_found; bool bulk_in_found;
bool bulk_out_found; bool bulk_out_found;
static __u32 descriptor[3] = { EDGE_COMPATIBILITY_MASK0, static const __u32 descriptor[3] = { EDGE_COMPATIBILITY_MASK0,
EDGE_COMPATIBILITY_MASK1, EDGE_COMPATIBILITY_MASK1,
EDGE_COMPATIBILITY_MASK2 }; EDGE_COMPATIBILITY_MASK2 };
if (serial->num_bulk_in < 1 || serial->num_interrupt_in < 1) {
dev_err(&serial->interface->dev, "missing endpoints\n");
return -ENODEV;
}
dev = serial->dev; dev = serial->dev;
...@@ -3120,6 +3110,9 @@ static struct usb_serial_driver edgeport_2port_device = { ...@@ -3120,6 +3110,9 @@ static struct usb_serial_driver edgeport_2port_device = {
.description = "Edgeport 2 port adapter", .description = "Edgeport 2 port adapter",
.id_table = edgeport_2port_id_table, .id_table = edgeport_2port_id_table,
.num_ports = 2, .num_ports = 2,
.num_bulk_in = 1,
.num_bulk_out = 1,
.num_interrupt_in = 1,
.open = edge_open, .open = edge_open,
.close = edge_close, .close = edge_close,
.throttle = edge_throttle, .throttle = edge_throttle,
...@@ -3152,6 +3145,9 @@ static struct usb_serial_driver edgeport_4port_device = { ...@@ -3152,6 +3145,9 @@ static struct usb_serial_driver edgeport_4port_device = {
.description = "Edgeport 4 port adapter", .description = "Edgeport 4 port adapter",
.id_table = edgeport_4port_id_table, .id_table = edgeport_4port_id_table,
.num_ports = 4, .num_ports = 4,
.num_bulk_in = 1,
.num_bulk_out = 1,
.num_interrupt_in = 1,
.open = edge_open, .open = edge_open,
.close = edge_close, .close = edge_close,
.throttle = edge_throttle, .throttle = edge_throttle,
...@@ -3184,6 +3180,9 @@ static struct usb_serial_driver edgeport_8port_device = { ...@@ -3184,6 +3180,9 @@ static struct usb_serial_driver edgeport_8port_device = {
.description = "Edgeport 8 port adapter", .description = "Edgeport 8 port adapter",
.id_table = edgeport_8port_id_table, .id_table = edgeport_8port_id_table,
.num_ports = 8, .num_ports = 8,
.num_bulk_in = 1,
.num_bulk_out = 1,
.num_interrupt_in = 1,
.open = edge_open, .open = edge_open,
.close = edge_close, .close = edge_close,
.throttle = edge_throttle, .throttle = edge_throttle,
...@@ -3216,6 +3215,9 @@ static struct usb_serial_driver epic_device = { ...@@ -3216,6 +3215,9 @@ static struct usb_serial_driver epic_device = {
.description = "EPiC device", .description = "EPiC device",
.id_table = Epic_port_id_table, .id_table = Epic_port_id_table,
.num_ports = 1, .num_ports = 1,
.num_bulk_in = 1,
.num_bulk_out = 1,
.num_interrupt_in = 1,
.open = edge_open, .open = edge_open,
.close = edge_close, .close = edge_close,
.throttle = edge_throttle, .throttle = edge_throttle,
......
...@@ -1933,13 +1933,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port) ...@@ -1933,13 +1933,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
if (edge_serial->num_ports_open == 0) { if (edge_serial->num_ports_open == 0) {
/* we are the first port to open, post the interrupt urb */ /* we are the first port to open, post the interrupt urb */
urb = edge_serial->serial->port[0]->interrupt_in_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; urb->context = edge_serial;
status = usb_submit_urb(urb, GFP_KERNEL); status = usb_submit_urb(urb, GFP_KERNEL);
if (status) { if (status) {
...@@ -1959,12 +1952,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port) ...@@ -1959,12 +1952,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
/* start up our bulk read urb */ /* start up our bulk read urb */
urb = port->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; edge_port->ep_read_urb_state = EDGE_READ_URB_RUNNING;
urb->context = edge_port; urb->context = edge_port;
status = usb_submit_urb(urb, GFP_KERNEL); status = usb_submit_urb(urb, GFP_KERNEL);
...@@ -2385,14 +2372,6 @@ static void edge_set_termios(struct tty_struct *tty, ...@@ -2385,14 +2372,6 @@ static void edge_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios) struct usb_serial_port *port, struct ktermios *old_termios)
{ {
struct edgeport_port *edge_port = usb_get_serial_port_data(port); 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) if (edge_port == NULL)
return; return;
...@@ -2544,19 +2523,31 @@ static void edge_heartbeat_work(struct work_struct *work) ...@@ -2544,19 +2523,31 @@ static void edge_heartbeat_work(struct work_struct *work)
edge_heartbeat_schedule(serial); 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; struct device *dev = &serial->interface->dev;
int status; unsigned char num_ports = serial->type->num_ports;
u16 product_id;
/* Make sure we have the required endpoints when in download mode. */ /* Make sure we have the required endpoints when in download mode. */
if (serial->interface->cur_altsetting->desc.bNumEndpoints > 1) { if (serial->interface->cur_altsetting->desc.bNumEndpoints > 1) {
if (serial->num_bulk_in < serial->num_ports || if (epds->num_bulk_in < num_ports ||
serial->num_bulk_out < serial->num_ports) epds->num_bulk_out < num_ports ||
epds->num_interrupt_in < 1) {
dev_err(dev, "required endpoints missing\n");
return -ENODEV; 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 */ /* create our private serial structure */
edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL); edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL);
if (!edge_serial) if (!edge_serial)
...@@ -2736,11 +2727,13 @@ static struct usb_serial_driver edgeport_1port_device = { ...@@ -2736,11 +2727,13 @@ static struct usb_serial_driver edgeport_1port_device = {
.description = "Edgeport TI 1 port adapter", .description = "Edgeport TI 1 port adapter",
.id_table = edgeport_1port_id_table, .id_table = edgeport_1port_id_table,
.num_ports = 1, .num_ports = 1,
.num_bulk_out = 1,
.open = edge_open, .open = edge_open,
.close = edge_close, .close = edge_close,
.throttle = edge_throttle, .throttle = edge_throttle,
.unthrottle = edge_unthrottle, .unthrottle = edge_unthrottle,
.attach = edge_startup, .attach = edge_startup,
.calc_num_ports = edge_calc_num_ports,
.disconnect = edge_disconnect, .disconnect = edge_disconnect,
.release = edge_release, .release = edge_release,
.port_probe = edge_port_probe, .port_probe = edge_port_probe,
...@@ -2773,11 +2766,13 @@ static struct usb_serial_driver edgeport_2port_device = { ...@@ -2773,11 +2766,13 @@ static struct usb_serial_driver edgeport_2port_device = {
.description = "Edgeport TI 2 port adapter", .description = "Edgeport TI 2 port adapter",
.id_table = edgeport_2port_id_table, .id_table = edgeport_2port_id_table,
.num_ports = 2, .num_ports = 2,
.num_bulk_out = 1,
.open = edge_open, .open = edge_open,
.close = edge_close, .close = edge_close,
.throttle = edge_throttle, .throttle = edge_throttle,
.unthrottle = edge_unthrottle, .unthrottle = edge_unthrottle,
.attach = edge_startup, .attach = edge_startup,
.calc_num_ports = edge_calc_num_ports,
.disconnect = edge_disconnect, .disconnect = edge_disconnect,
.release = edge_release, .release = edge_release,
.port_probe = edge_port_probe, .port_probe = edge_port_probe,
......
...@@ -33,7 +33,8 @@ static int initial_wait; ...@@ -33,7 +33,8 @@ static int initial_wait;
/* Function prototypes for an ipaq */ /* Function prototypes for an ipaq */
static int ipaq_open(struct tty_struct *tty, static int ipaq_open(struct tty_struct *tty,
struct usb_serial_port *port); struct usb_serial_port *port);
static int ipaq_calc_num_ports(struct usb_serial *serial); static int ipaq_calc_num_ports(struct usb_serial *serial,
struct usb_serial_endpoints *epds);
static int ipaq_startup(struct usb_serial *serial); static int ipaq_startup(struct usb_serial *serial);
static const struct usb_device_id ipaq_id_table[] = { static const struct usb_device_id ipaq_id_table[] = {
...@@ -550,42 +551,38 @@ static int ipaq_open(struct tty_struct *tty, ...@@ -550,42 +551,38 @@ static int ipaq_open(struct tty_struct *tty,
return usb_serial_generic_open(tty, port); return usb_serial_generic_open(tty, port);
} }
static int ipaq_calc_num_ports(struct usb_serial *serial) static int ipaq_calc_num_ports(struct usb_serial *serial,
struct usb_serial_endpoints *epds)
{ {
/* /*
* some devices have 3 endpoints, the 3rd of which * Some of the devices in ipaq_id_table[] are composite, and we
* must be ignored as it would make the core * shouldn't bind to all the interfaces. This test will rule out
* create a second port which oopses when used * some obviously invalid possibilities.
*/ */
int ipaq_num_ports = 1; if (epds->num_bulk_in == 0 || epds->num_bulk_out == 0)
return -ENODEV;
dev_dbg(&serial->dev->dev, "%s - numberofendpoints: %d\n", __func__,
(int)serial->interface->cur_altsetting->desc.bNumEndpoints);
/* /*
* a few devices have 4 endpoints, seemingly Yakuma devices, * A few devices have four endpoints, seemingly Yakuma devices, and
* and we need the second pair, so let them have 2 ports * we need the second pair.
*
* TODO: can we drop port 1 ?
*/ */
if (serial->interface->cur_altsetting->desc.bNumEndpoints > 3) { if (epds->num_bulk_in > 1 && epds->num_bulk_out > 1) {
ipaq_num_ports = 2; epds->bulk_in[0] = epds->bulk_in[1];
epds->bulk_out[0] = epds->bulk_out[1];
} }
return ipaq_num_ports; /*
} * Other devices have 3 endpoints, but we only use the first bulk in
* and out endpoints.
*/
epds->num_bulk_in = 1;
epds->num_bulk_out = 1;
return 1;
}
static int ipaq_startup(struct usb_serial *serial) static int ipaq_startup(struct usb_serial *serial)
{ {
/* Some of the devices in ipaq_id_table[] are composite, and we
* shouldn't bind to all the interfaces. This test will rule out
* some obviously invalid possibilities.
*/
if (serial->num_bulk_in < serial->num_ports ||
serial->num_bulk_out < serial->num_ports)
return -ENODEV;
if (serial->dev->actconfig->desc.bConfigurationValue != 1) { if (serial->dev->actconfig->desc.bConfigurationValue != 1) {
/* /*
* FIXME: HP iPaq rx3715, possibly others, have 1 config that * FIXME: HP iPaq rx3715, possibly others, have 1 config that
...@@ -597,10 +594,6 @@ static int ipaq_startup(struct usb_serial *serial) ...@@ -597,10 +594,6 @@ static int ipaq_startup(struct usb_serial *serial)
return -ENODEV; return -ENODEV;
} }
dev_dbg(&serial->dev->dev,
"%s - iPAQ module configured for %d ports\n", __func__,
serial->num_ports);
return usb_reset_configuration(serial->dev); return usb_reset_configuration(serial->dev);
} }
......
...@@ -68,16 +68,6 @@ struct iuu_private { ...@@ -68,16 +68,6 @@ struct iuu_private {
u32 clk; u32 clk;
}; };
static int iuu_attach(struct usb_serial *serial)
{
unsigned char num_ports = serial->num_ports;
if (serial->num_bulk_in < num_ports || serial->num_bulk_out < num_ports)
return -ENODEV;
return 0;
}
static int iuu_port_probe(struct usb_serial_port *port) static int iuu_port_probe(struct usb_serial_port *port)
{ {
struct iuu_private *priv; struct iuu_private *priv;
...@@ -598,9 +588,8 @@ static void read_buf_callback(struct urb *urb) ...@@ -598,9 +588,8 @@ static void read_buf_callback(struct urb *urb)
} }
dev_dbg(&port->dev, "%s - %i chars to write\n", __func__, urb->actual_length); dev_dbg(&port->dev, "%s - %i chars to write\n", __func__, urb->actual_length);
if (data == NULL)
dev_dbg(&port->dev, "%s - data is NULL !!!\n", __func__); if (urb->actual_length) {
if (urb->actual_length && data) {
tty_insert_flip_string(&port->port, data, urb->actual_length); tty_insert_flip_string(&port->port, data, urb->actual_length);
tty_flip_buffer_push(&port->port); tty_flip_buffer_push(&port->port);
} }
...@@ -665,10 +654,8 @@ static void iuu_uart_read_callback(struct urb *urb) ...@@ -665,10 +654,8 @@ static void iuu_uart_read_callback(struct urb *urb)
/* error stop all */ /* error stop all */
return; return;
} }
if (data == NULL)
dev_dbg(&port->dev, "%s - data is NULL !!!\n", __func__);
if (urb->actual_length == 1 && data != NULL) if (urb->actual_length == 1)
len = (int) data[0]; len = (int) data[0];
if (urb->actual_length > 1) { if (urb->actual_length > 1) {
...@@ -1183,6 +1170,8 @@ static struct usb_serial_driver iuu_device = { ...@@ -1183,6 +1170,8 @@ static struct usb_serial_driver iuu_device = {
}, },
.id_table = id_table, .id_table = id_table,
.num_ports = 1, .num_ports = 1,
.num_bulk_in = 1,
.num_bulk_out = 1,
.bulk_in_size = 512, .bulk_in_size = 512,
.bulk_out_size = 512, .bulk_out_size = 512,
.open = iuu_open, .open = iuu_open,
...@@ -1193,7 +1182,6 @@ static struct usb_serial_driver iuu_device = { ...@@ -1193,7 +1182,6 @@ static struct usb_serial_driver iuu_device = {
.tiocmset = iuu_tiocmset, .tiocmset = iuu_tiocmset,
.set_termios = iuu_set_termios, .set_termios = iuu_set_termios,
.init_termios = iuu_init_termios, .init_termios = iuu_init_termios,
.attach = iuu_attach,
.port_probe = iuu_port_probe, .port_probe = iuu_port_probe,
.port_remove = iuu_port_remove, .port_remove = iuu_port_remove,
}; };
......
...@@ -708,19 +708,6 @@ MODULE_FIRMWARE("keyspan_pda/keyspan_pda.fw"); ...@@ -708,19 +708,6 @@ MODULE_FIRMWARE("keyspan_pda/keyspan_pda.fw");
MODULE_FIRMWARE("keyspan_pda/xircom_pgs.fw"); MODULE_FIRMWARE("keyspan_pda/xircom_pgs.fw");
#endif #endif
static int keyspan_pda_attach(struct usb_serial *serial)
{
unsigned char num_ports = serial->num_ports;
if (serial->num_bulk_out < num_ports ||
serial->num_interrupt_in < num_ports) {
dev_err(&serial->interface->dev, "missing endpoints\n");
return -ENODEV;
}
return 0;
}
static int keyspan_pda_port_probe(struct usb_serial_port *port) static int keyspan_pda_port_probe(struct usb_serial_port *port)
{ {
...@@ -784,6 +771,8 @@ static struct usb_serial_driver keyspan_pda_device = { ...@@ -784,6 +771,8 @@ static struct usb_serial_driver keyspan_pda_device = {
.description = "Keyspan PDA", .description = "Keyspan PDA",
.id_table = id_table_std, .id_table = id_table_std,
.num_ports = 1, .num_ports = 1,
.num_bulk_out = 1,
.num_interrupt_in = 1,
.dtr_rts = keyspan_pda_dtr_rts, .dtr_rts = keyspan_pda_dtr_rts,
.open = keyspan_pda_open, .open = keyspan_pda_open,
.close = keyspan_pda_close, .close = keyspan_pda_close,
...@@ -798,7 +787,6 @@ static struct usb_serial_driver keyspan_pda_device = { ...@@ -798,7 +787,6 @@ static struct usb_serial_driver keyspan_pda_device = {
.break_ctl = keyspan_pda_break_ctl, .break_ctl = keyspan_pda_break_ctl,
.tiocmget = keyspan_pda_tiocmget, .tiocmget = keyspan_pda_tiocmget,
.tiocmset = keyspan_pda_tiocmset, .tiocmset = keyspan_pda_tiocmset,
.attach = keyspan_pda_attach,
.port_probe = keyspan_pda_port_probe, .port_probe = keyspan_pda_port_probe,
.port_remove = keyspan_pda_port_remove, .port_remove = keyspan_pda_port_remove,
}; };
......
...@@ -51,7 +51,6 @@ ...@@ -51,7 +51,6 @@
/* Function prototypes */ /* Function prototypes */
static int kobil_attach(struct usb_serial *serial);
static int kobil_port_probe(struct usb_serial_port *probe); static int kobil_port_probe(struct usb_serial_port *probe);
static int kobil_port_remove(struct usb_serial_port *probe); static int kobil_port_remove(struct usb_serial_port *probe);
static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port); static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port);
...@@ -87,7 +86,7 @@ static struct usb_serial_driver kobil_device = { ...@@ -87,7 +86,7 @@ static struct usb_serial_driver kobil_device = {
.description = "KOBIL USB smart card terminal", .description = "KOBIL USB smart card terminal",
.id_table = id_table, .id_table = id_table,
.num_ports = 1, .num_ports = 1,
.attach = kobil_attach, .num_interrupt_out = 1,
.port_probe = kobil_port_probe, .port_probe = kobil_port_probe,
.port_remove = kobil_port_remove, .port_remove = kobil_port_remove,
.ioctl = kobil_ioctl, .ioctl = kobil_ioctl,
...@@ -115,16 +114,6 @@ struct kobil_private { ...@@ -115,16 +114,6 @@ struct kobil_private {
}; };
static int kobil_attach(struct usb_serial *serial)
{
if (serial->num_interrupt_out < serial->num_ports) {
dev_err(&serial->interface->dev, "missing interrupt-out endpoint\n");
return -ENODEV;
}
return 0;
}
static int kobil_port_probe(struct usb_serial_port *port) static int kobil_port_probe(struct usb_serial_port *port)
{ {
struct usb_serial *serial = port->serial; struct usb_serial *serial = port->serial;
......
...@@ -973,11 +973,24 @@ static void mos7720_bulk_out_data_callback(struct urb *urb) ...@@ -973,11 +973,24 @@ static void mos7720_bulk_out_data_callback(struct urb *urb)
tty_port_tty_wakeup(&mos7720_port->port->port); tty_port_tty_wakeup(&mos7720_port->port->port);
} }
static int mos77xx_calc_num_ports(struct usb_serial *serial) static int mos77xx_calc_num_ports(struct usb_serial *serial,
struct usb_serial_endpoints *epds)
{ {
u16 product = le16_to_cpu(serial->dev->descriptor.idProduct); u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
if (product == MOSCHIP_DEVICE_ID_7715)
if (product == MOSCHIP_DEVICE_ID_7715) {
/*
* The 7715 uses the first bulk in/out endpoint pair for the
* parallel port, and the second for the serial port. We swap
* the endpoint descriptors here so that the the first and
* only registered port structure uses the serial-port
* endpoints.
*/
swap(epds->bulk_in[0], epds->bulk_in[1]);
swap(epds->bulk_out[0], epds->bulk_out[1]);
return 1; return 1;
}
return 2; return 2;
} }
...@@ -1395,7 +1408,7 @@ struct divisor_table_entry { ...@@ -1395,7 +1408,7 @@ struct divisor_table_entry {
/* Define table of divisors for moschip 7720 hardware * /* Define table of divisors for moschip 7720 hardware *
* These assume a 3.6864MHz crystal, the standard /16, and * * These assume a 3.6864MHz crystal, the standard /16, and *
* MCR.7 = 0. */ * MCR.7 = 0. */
static struct divisor_table_entry divisor_table[] = { static const struct divisor_table_entry divisor_table[] = {
{ 50, 2304}, { 50, 2304},
{ 110, 1047}, /* 2094.545455 => 230450 => .0217 % over */ { 110, 1047}, /* 2094.545455 => 230450 => .0217 % over */
{ 134, 857}, /* 1713.011152 => 230398.5 => .00065% under */ { 134, 857}, /* 1713.011152 => 230398.5 => .00065% under */
...@@ -1675,7 +1688,6 @@ static void mos7720_set_termios(struct tty_struct *tty, ...@@ -1675,7 +1688,6 @@ static void mos7720_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios) struct usb_serial_port *port, struct ktermios *old_termios)
{ {
int status; int status;
unsigned int cflag;
struct usb_serial *serial; struct usb_serial *serial;
struct moschip_port *mos7720_port; struct moschip_port *mos7720_port;
...@@ -1691,16 +1703,6 @@ static void mos7720_set_termios(struct tty_struct *tty, ...@@ -1691,16 +1703,6 @@ static void mos7720_set_termios(struct tty_struct *tty,
return; return;
} }
dev_dbg(&port->dev, "setting termios - ASPIRE\n");
cflag = tty->termios.c_cflag;
dev_dbg(&port->dev, "%s - cflag %08x iflag %08x\n", __func__,
tty->termios.c_cflag, RELEVANT_IFLAG(tty->termios.c_iflag));
dev_dbg(&port->dev, "%s - old cflag %08x old iflag %08x\n", __func__,
old_termios->c_cflag, RELEVANT_IFLAG(old_termios->c_iflag));
/* change the port settings to the new ones specified */ /* change the port settings to the new ones specified */
change_port_settings(tty, mos7720_port, old_termios); change_port_settings(tty, mos7720_port, old_termios);
...@@ -1900,54 +1902,24 @@ static int mos7720_startup(struct usb_serial *serial) ...@@ -1900,54 +1902,24 @@ static int mos7720_startup(struct usb_serial *serial)
u16 product; u16 product;
int ret_val; int ret_val;
if (serial->num_bulk_in < 2 || serial->num_bulk_out < 2) {
dev_err(&serial->interface->dev, "missing bulk endpoints\n");
return -ENODEV;
}
product = le16_to_cpu(serial->dev->descriptor.idProduct); product = le16_to_cpu(serial->dev->descriptor.idProduct);
dev = serial->dev; dev = serial->dev;
/*
* The 7715 uses the first bulk in/out endpoint pair for the parallel
* port, and the second for the serial port. Because the usbserial core
* assumes both pairs are serial ports, we must engage in a bit of
* subterfuge and swap the pointers for ports 0 and 1 in order to make
* port 0 point to the serial port. However, both moschip devices use a
* single interrupt-in endpoint for both ports (as mentioned a little
* further down), and this endpoint was assigned to port 0. So after
* the swap, we must copy the interrupt endpoint elements from port 1
* (as newly assigned) to port 0, and null out port 1 pointers.
*/
if (product == MOSCHIP_DEVICE_ID_7715) {
struct usb_serial_port *tmp = serial->port[0];
serial->port[0] = serial->port[1];
serial->port[1] = tmp;
serial->port[0]->interrupt_in_urb = tmp->interrupt_in_urb;
serial->port[0]->interrupt_in_buffer = tmp->interrupt_in_buffer;
serial->port[0]->interrupt_in_endpointAddress =
tmp->interrupt_in_endpointAddress;
serial->port[1]->interrupt_in_urb = NULL;
serial->port[1]->interrupt_in_buffer = NULL;
if (serial->port[0]->interrupt_in_urb) {
struct urb *urb = serial->port[0]->interrupt_in_urb;
urb->complete = mos7715_interrupt_callback;
}
}
/* setting configuration feature to one */ /* setting configuration feature to one */
usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
(__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5000); (__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5000);
#ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT
if (product == MOSCHIP_DEVICE_ID_7715) { if (product == MOSCHIP_DEVICE_ID_7715) {
struct urb *urb = serial->port[0]->interrupt_in_urb;
urb->complete = mos7715_interrupt_callback;
#ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT
ret_val = mos7715_parport_init(serial); ret_val = mos7715_parport_init(serial);
if (ret_val < 0) if (ret_val < 0)
return ret_val; return ret_val;
}
#endif #endif
}
/* start the interrupt urb */ /* start the interrupt urb */
ret_val = usb_submit_urb(serial->port[0]->interrupt_in_urb, GFP_KERNEL); ret_val = usb_submit_urb(serial->port[0]->interrupt_in_urb, GFP_KERNEL);
if (ret_val) { if (ret_val) {
...@@ -2039,6 +2011,9 @@ static struct usb_serial_driver moschip7720_2port_driver = { ...@@ -2039,6 +2011,9 @@ static struct usb_serial_driver moschip7720_2port_driver = {
}, },
.description = "Moschip 2 port adapter", .description = "Moschip 2 port adapter",
.id_table = id_table, .id_table = id_table,
.num_bulk_in = 2,
.num_bulk_out = 2,
.num_interrupt_in = 1,
.calc_num_ports = mos77xx_calc_num_ports, .calc_num_ports = mos77xx_calc_num_ports,
.open = mos7720_open, .open = mos7720_open,
.close = mos7720_close, .close = mos7720_close,
......
...@@ -1868,7 +1868,6 @@ static void mos7840_set_termios(struct tty_struct *tty, ...@@ -1868,7 +1868,6 @@ static void mos7840_set_termios(struct tty_struct *tty,
struct ktermios *old_termios) struct ktermios *old_termios)
{ {
int status; int status;
unsigned int cflag;
struct usb_serial *serial; struct usb_serial *serial;
struct moschip_port *mos7840_port; struct moschip_port *mos7840_port;
...@@ -1890,15 +1889,6 @@ static void mos7840_set_termios(struct tty_struct *tty, ...@@ -1890,15 +1889,6 @@ static void mos7840_set_termios(struct tty_struct *tty,
return; return;
} }
dev_dbg(&port->dev, "%s", "setting termios - \n");
cflag = tty->termios.c_cflag;
dev_dbg(&port->dev, "%s - clfag %08x iflag %08x\n", __func__,
tty->termios.c_cflag, RELEVANT_IFLAG(tty->termios.c_iflag));
dev_dbg(&port->dev, "%s - old clfag %08x old iflag %08x\n", __func__,
old_termios->c_cflag, RELEVANT_IFLAG(old_termios->c_iflag));
/* change the port settings to the new ones specified */ /* change the port settings to the new ones specified */
mos7840_change_port_settings(tty, mos7840_port, old_termios); mos7840_change_port_settings(tty, mos7840_port, old_termios);
...@@ -2104,26 +2094,27 @@ static int mos7840_probe(struct usb_serial *serial, ...@@ -2104,26 +2094,27 @@ static int mos7840_probe(struct usb_serial *serial,
return 0; return 0;
} }
static int mos7840_calc_num_ports(struct usb_serial *serial) static int mos7840_calc_num_ports(struct usb_serial *serial,
struct usb_serial_endpoints *epds)
{ {
int device_type = (unsigned long)usb_get_serial_data(serial); int device_type = (unsigned long)usb_get_serial_data(serial);
int mos7840_num_ports; int num_ports;
mos7840_num_ports = (device_type >> 4) & 0x000F; num_ports = (device_type >> 4) & 0x000F;
return mos7840_num_ports; /*
} * num_ports is currently never zero as device_type is one of
* MOSCHIP_DEVICE_ID_78{1,2,4}0.
*/
if (num_ports == 0)
return -ENODEV;
static int mos7840_attach(struct usb_serial *serial) if (epds->num_bulk_in < num_ports || epds->num_bulk_out < num_ports) {
{
if (serial->num_bulk_in < serial->num_ports ||
serial->num_bulk_out < serial->num_ports ||
serial->num_interrupt_in < 1) {
dev_err(&serial->interface->dev, "missing endpoints\n"); dev_err(&serial->interface->dev, "missing endpoints\n");
return -ENODEV; return -ENODEV;
} }
return 0; return num_ports;
} }
static int mos7840_port_probe(struct usb_serial_port *port) static int mos7840_port_probe(struct usb_serial_port *port)
...@@ -2384,7 +2375,7 @@ static struct usb_serial_driver moschip7840_4port_device = { ...@@ -2384,7 +2375,7 @@ static struct usb_serial_driver moschip7840_4port_device = {
}, },
.description = DRIVER_DESC, .description = DRIVER_DESC,
.id_table = id_table, .id_table = id_table,
.num_ports = 4, .num_interrupt_in = 1,
.open = mos7840_open, .open = mos7840_open,
.close = mos7840_close, .close = mos7840_close,
.write = mos7840_write, .write = mos7840_write,
...@@ -2401,7 +2392,6 @@ static struct usb_serial_driver moschip7840_4port_device = { ...@@ -2401,7 +2392,6 @@ static struct usb_serial_driver moschip7840_4port_device = {
.tiocmset = mos7840_tiocmset, .tiocmset = mos7840_tiocmset,
.tiocmiwait = usb_serial_generic_tiocmiwait, .tiocmiwait = usb_serial_generic_tiocmiwait,
.get_icount = usb_serial_generic_get_icount, .get_icount = usb_serial_generic_get_icount,
.attach = mos7840_attach,
.port_probe = mos7840_port_probe, .port_probe = mos7840_port_probe,
.port_remove = mos7840_port_remove, .port_remove = mos7840_port_remove,
.read_bulk_callback = mos7840_bulk_in_callback, .read_bulk_callback = mos7840_bulk_in_callback,
......
...@@ -946,20 +946,39 @@ static void mxuport_set_termios(struct tty_struct *tty, ...@@ -946,20 +946,39 @@ static void mxuport_set_termios(struct tty_struct *tty,
* Determine how many ports this device has dynamically. It will be * Determine how many ports this device has dynamically. It will be
* called after the probe() callback is called, but before attach(). * called after the probe() callback is called, but before attach().
*/ */
static int mxuport_calc_num_ports(struct usb_serial *serial) static int mxuport_calc_num_ports(struct usb_serial *serial,
struct usb_serial_endpoints *epds)
{ {
unsigned long features = (unsigned long)usb_get_serial_data(serial); unsigned long features = (unsigned long)usb_get_serial_data(serial);
int num_ports;
int i;
if (features & MX_UPORT_2_PORT) if (features & MX_UPORT_2_PORT) {
return 2; num_ports = 2;
if (features & MX_UPORT_4_PORT) } else if (features & MX_UPORT_4_PORT) {
return 4; num_ports = 4;
if (features & MX_UPORT_8_PORT) } else if (features & MX_UPORT_8_PORT) {
return 8; num_ports = 8;
if (features & MX_UPORT_16_PORT) } else if (features & MX_UPORT_16_PORT) {
return 16; num_ports = 16;
} else {
dev_warn(&serial->interface->dev,
"unknown device, assuming two ports\n");
num_ports = 2;
}
return 0; /*
* Setup bulk-out endpoint multiplexing. All ports share the same
* bulk-out endpoint.
*/
BUILD_BUG_ON(ARRAY_SIZE(epds->bulk_out) < 16);
for (i = 1; i < num_ports; ++i)
epds->bulk_out[i] = epds->bulk_out[0];
epds->num_bulk_out = num_ports;
return num_ports;
} }
/* Get the version of the firmware currently running. */ /* Get the version of the firmware currently running. */
...@@ -1142,102 +1161,11 @@ static int mxuport_port_probe(struct usb_serial_port *port) ...@@ -1142,102 +1161,11 @@ static int mxuport_port_probe(struct usb_serial_port *port)
port->port_number); port->port_number);
} }
static int mxuport_alloc_write_urb(struct usb_serial *serial,
struct usb_serial_port *port,
struct usb_serial_port *port0,
int j)
{
struct usb_device *dev = interface_to_usbdev(serial->interface);
set_bit(j, &port->write_urbs_free);
port->write_urbs[j] = usb_alloc_urb(0, GFP_KERNEL);
if (!port->write_urbs[j])
return -ENOMEM;
port->bulk_out_buffers[j] = kmalloc(port0->bulk_out_size, GFP_KERNEL);
if (!port->bulk_out_buffers[j])
return -ENOMEM;
usb_fill_bulk_urb(port->write_urbs[j], dev,
usb_sndbulkpipe(dev, port->bulk_out_endpointAddress),
port->bulk_out_buffers[j],
port->bulk_out_size,
serial->type->write_bulk_callback,
port);
return 0;
}
static int mxuport_alloc_write_urbs(struct usb_serial *serial,
struct usb_serial_port *port,
struct usb_serial_port *port0)
{
int j;
int ret;
for (j = 0; j < ARRAY_SIZE(port->write_urbs); ++j) {
ret = mxuport_alloc_write_urb(serial, port, port0, j);
if (ret)
return ret;
}
return 0;
}
static int mxuport_attach(struct usb_serial *serial) static int mxuport_attach(struct usb_serial *serial)
{ {
struct usb_serial_port *port0 = serial->port[0]; struct usb_serial_port *port0 = serial->port[0];
struct usb_serial_port *port1 = serial->port[1]; struct usb_serial_port *port1 = serial->port[1];
struct usb_serial_port *port;
int err; int err;
int i;
int j;
/*
* Throw away all but the first allocated write URBs so we can
* set them up again to fit the multiplexing scheme.
*/
for (i = 1; i < serial->num_bulk_out; ++i) {
port = serial->port[i];
for (j = 0; j < ARRAY_SIZE(port->write_urbs); ++j) {
usb_free_urb(port->write_urbs[j]);
kfree(port->bulk_out_buffers[j]);
port->write_urbs[j] = NULL;
port->bulk_out_buffers[j] = NULL;
}
port->write_urbs_free = 0;
}
/*
* All write data is sent over the first bulk out endpoint,
* with an added header to indicate the port. Allocate URBs
* for each port to the first bulk out endpoint.
*/
for (i = 1; i < serial->num_ports; ++i) {
port = serial->port[i];
port->bulk_out_size = port0->bulk_out_size;
port->bulk_out_endpointAddress =
port0->bulk_out_endpointAddress;
err = mxuport_alloc_write_urbs(serial, port, port0);
if (err)
return err;
port->write_urb = port->write_urbs[0];
port->bulk_out_buffer = port->bulk_out_buffers[0];
/*
* Ensure each port has a fifo. The framework only
* allocates a fifo to ports with a bulk out endpoint,
* where as we need one for every port.
*/
if (!kfifo_initialized(&port->write_fifo)) {
err = kfifo_alloc(&port->write_fifo, PAGE_SIZE,
GFP_KERNEL);
if (err)
return err;
}
}
/* /*
* All data from the ports is received on the first bulk in * All data from the ports is received on the first bulk in
...@@ -1366,7 +1294,8 @@ static struct usb_serial_driver mxuport_device = { ...@@ -1366,7 +1294,8 @@ static struct usb_serial_driver mxuport_device = {
}, },
.description = "MOXA UPort", .description = "MOXA UPort",
.id_table = mxuport_idtable, .id_table = mxuport_idtable,
.num_ports = 0, .num_bulk_in = 2,
.num_bulk_out = 1,
.probe = mxuport_probe, .probe = mxuport_probe,
.port_probe = mxuport_port_probe, .port_probe = mxuport_port_probe,
.attach = mxuport_attach, .attach = mxuport_attach,
......
/* /*
* USB ZyXEL omni.net LCD PLUS driver * USB ZyXEL omni.net LCD PLUS driver
* *
* Copyright (C) 2013,2017 Johan Hovold <johan@kernel.org>
*
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version * modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation. * 2 as published by the Free Software Foundation.
...@@ -32,12 +34,10 @@ ...@@ -32,12 +34,10 @@
/* function prototypes */ /* function prototypes */
static void omninet_process_read_urb(struct urb *urb); static void omninet_process_read_urb(struct urb *urb);
static void omninet_write_bulk_callback(struct urb *urb); static int omninet_prepare_write_buffer(struct usb_serial_port *port,
static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port, void *buf, size_t count);
const unsigned char *buf, int count); static int omninet_calc_num_ports(struct usb_serial *serial,
static int omninet_write_room(struct tty_struct *tty); struct usb_serial_endpoints *epds);
static void omninet_disconnect(struct usb_serial *serial);
static int omninet_attach(struct usb_serial *serial);
static int omninet_port_probe(struct usb_serial_port *port); static int omninet_port_probe(struct usb_serial_port *port);
static int omninet_port_remove(struct usb_serial_port *port); static int omninet_port_remove(struct usb_serial_port *port);
...@@ -55,15 +55,12 @@ static struct usb_serial_driver zyxel_omninet_device = { ...@@ -55,15 +55,12 @@ static struct usb_serial_driver zyxel_omninet_device = {
}, },
.description = "ZyXEL - omni.net lcd plus usb", .description = "ZyXEL - omni.net lcd plus usb",
.id_table = id_table, .id_table = id_table,
.num_ports = 1, .num_bulk_out = 2,
.attach = omninet_attach, .calc_num_ports = omninet_calc_num_ports,
.port_probe = omninet_port_probe, .port_probe = omninet_port_probe,
.port_remove = omninet_port_remove, .port_remove = omninet_port_remove,
.write = omninet_write,
.write_room = omninet_write_room,
.write_bulk_callback = omninet_write_bulk_callback,
.process_read_urb = omninet_process_read_urb, .process_read_urb = omninet_process_read_urb,
.disconnect = omninet_disconnect, .prepare_write_buffer = omninet_prepare_write_buffer,
}; };
static struct usb_serial_driver * const serial_drivers[] = { static struct usb_serial_driver * const serial_drivers[] = {
...@@ -104,15 +101,14 @@ struct omninet_data { ...@@ -104,15 +101,14 @@ struct omninet_data {
__u8 od_outseq; /* Sequence number for bulk_out URBs */ __u8 od_outseq; /* Sequence number for bulk_out URBs */
}; };
static int omninet_attach(struct usb_serial *serial) static int omninet_calc_num_ports(struct usb_serial *serial,
struct usb_serial_endpoints *epds)
{ {
/* The second bulk-out endpoint is used for writing. */ /* We need only the second bulk-out for our single-port device. */
if (serial->num_bulk_out < 2) { epds->bulk_out[0] = epds->bulk_out[1];
dev_err(&serial->interface->dev, "missing endpoints\n"); epds->num_bulk_out = 1;
return -ENODEV;
}
return 0; return 1;
} }
static int omninet_port_probe(struct usb_serial_port *port) static int omninet_port_probe(struct usb_serial_port *port)
...@@ -159,96 +155,24 @@ static void omninet_process_read_urb(struct urb *urb) ...@@ -159,96 +155,24 @@ static void omninet_process_read_urb(struct urb *urb)
tty_flip_buffer_push(&port->port); tty_flip_buffer_push(&port->port);
} }
static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port, static int omninet_prepare_write_buffer(struct usb_serial_port *port,
const unsigned char *buf, int count) void *buf, size_t count)
{ {
struct usb_serial *serial = port->serial;
struct usb_serial_port *wport = serial->port[1];
struct omninet_data *od = usb_get_serial_port_data(port); struct omninet_data *od = usb_get_serial_port_data(port);
struct omninet_header *header = (struct omninet_header *) struct omninet_header *header = buf;
wport->write_urb->transfer_buffer;
int result;
if (count == 0) {
dev_dbg(&port->dev, "%s - write request of 0 bytes\n", __func__);
return 0;
}
if (!test_and_clear_bit(0, &port->write_urbs_free)) {
dev_dbg(&port->dev, "%s - already writing\n", __func__);
return 0;
}
count = (count > OMNINET_PAYLOADSIZE) ? OMNINET_PAYLOADSIZE : count;
memcpy(wport->write_urb->transfer_buffer + OMNINET_HEADERLEN,
buf, count);
usb_serial_debug_data(&port->dev, __func__, count,
wport->write_urb->transfer_buffer);
header->oh_seq = od->od_outseq++;
header->oh_len = count;
header->oh_xxx = 0x03;
header->oh_pad = 0x00;
/* send the data out the bulk port, always 64 bytes */
wport->write_urb->transfer_buffer_length = OMNINET_BULKOUTSIZE;
result = usb_submit_urb(wport->write_urb, GFP_ATOMIC);
if (result) {
set_bit(0, &wport->write_urbs_free);
dev_err_console(port,
"%s - failed submitting write urb, error %d\n",
__func__, result);
} else
result = count;
return result;
}
count = min_t(size_t, count, OMNINET_PAYLOADSIZE);
static int omninet_write_room(struct tty_struct *tty) count = kfifo_out_locked(&port->write_fifo, buf + OMNINET_HEADERLEN,
{ count, &port->lock);
struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial;
struct usb_serial_port *wport = serial->port[1];
int room = 0; /* Default: no room */
if (test_bit(0, &wport->write_urbs_free))
room = wport->bulk_out_size - OMNINET_HEADERLEN;
dev_dbg(&port->dev, "%s - returns %d\n", __func__, room);
return room;
}
static void omninet_write_bulk_callback(struct urb *urb)
{
/* struct omninet_header *header = (struct omninet_header *)
urb->transfer_buffer; */
struct usb_serial_port *port = urb->context;
int status = urb->status;
set_bit(0, &port->write_urbs_free);
if (status) {
dev_dbg(&port->dev, "%s - nonzero write bulk status received: %d\n",
__func__, status);
return;
}
usb_serial_port_softint(port); header->oh_seq = od->od_outseq++;
} header->oh_len = count;
header->oh_xxx = 0x03;
header->oh_pad = 0x00;
static void omninet_disconnect(struct usb_serial *serial)
{
struct usb_serial_port *wport = serial->port[1];
usb_kill_urb(wport->write_urb); /* always 64 bytes */
return OMNINET_BULKOUTSIZE;
} }
module_usb_serial_driver(serial_drivers, id_table); module_usb_serial_driver(serial_drivers, id_table);
......
...@@ -367,16 +367,6 @@ static int opticon_ioctl(struct tty_struct *tty, ...@@ -367,16 +367,6 @@ static int opticon_ioctl(struct tty_struct *tty,
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
} }
static int opticon_startup(struct usb_serial *serial)
{
if (!serial->num_bulk_in) {
dev_err(&serial->dev->dev, "no bulk in endpoint\n");
return -ENODEV;
}
return 0;
}
static int opticon_port_probe(struct usb_serial_port *port) static int opticon_port_probe(struct usb_serial_port *port)
{ {
struct opticon_private *priv; struct opticon_private *priv;
...@@ -408,8 +398,8 @@ static struct usb_serial_driver opticon_device = { ...@@ -408,8 +398,8 @@ static struct usb_serial_driver opticon_device = {
}, },
.id_table = id_table, .id_table = id_table,
.num_ports = 1, .num_ports = 1,
.num_bulk_in = 1,
.bulk_in_size = 256, .bulk_in_size = 256,
.attach = opticon_startup,
.port_probe = opticon_port_probe, .port_probe = opticon_port_probe,
.port_remove = opticon_port_remove, .port_remove = opticon_port_remove,
.open = opticon_open, .open = opticon_open,
......
...@@ -134,7 +134,6 @@ static int oti6858_chars_in_buffer(struct tty_struct *tty); ...@@ -134,7 +134,6 @@ static int oti6858_chars_in_buffer(struct tty_struct *tty);
static int oti6858_tiocmget(struct tty_struct *tty); static int oti6858_tiocmget(struct tty_struct *tty);
static int oti6858_tiocmset(struct tty_struct *tty, static int oti6858_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear); unsigned int set, unsigned int clear);
static int oti6858_attach(struct usb_serial *serial);
static int oti6858_port_probe(struct usb_serial_port *port); static int oti6858_port_probe(struct usb_serial_port *port);
static int oti6858_port_remove(struct usb_serial_port *port); static int oti6858_port_remove(struct usb_serial_port *port);
...@@ -146,6 +145,9 @@ static struct usb_serial_driver oti6858_device = { ...@@ -146,6 +145,9 @@ static struct usb_serial_driver oti6858_device = {
}, },
.id_table = id_table, .id_table = id_table,
.num_ports = 1, .num_ports = 1,
.num_bulk_in = 1,
.num_bulk_out = 1,
.num_interrupt_in = 1,
.open = oti6858_open, .open = oti6858_open,
.close = oti6858_close, .close = oti6858_close,
.write = oti6858_write, .write = oti6858_write,
...@@ -159,7 +161,6 @@ static struct usb_serial_driver oti6858_device = { ...@@ -159,7 +161,6 @@ static struct usb_serial_driver oti6858_device = {
.write_bulk_callback = oti6858_write_bulk_callback, .write_bulk_callback = oti6858_write_bulk_callback,
.write_room = oti6858_write_room, .write_room = oti6858_write_room,
.chars_in_buffer = oti6858_chars_in_buffer, .chars_in_buffer = oti6858_chars_in_buffer,
.attach = oti6858_attach,
.port_probe = oti6858_port_probe, .port_probe = oti6858_port_probe,
.port_remove = oti6858_port_remove, .port_remove = oti6858_port_remove,
}; };
...@@ -326,20 +327,6 @@ static void send_data(struct work_struct *work) ...@@ -326,20 +327,6 @@ static void send_data(struct work_struct *work)
usb_serial_port_softint(port); usb_serial_port_softint(port);
} }
static int oti6858_attach(struct usb_serial *serial)
{
unsigned char num_ports = serial->num_ports;
if (serial->num_bulk_in < num_ports ||
serial->num_bulk_out < num_ports ||
serial->num_interrupt_in < num_ports) {
dev_err(&serial->interface->dev, "missing endpoints\n");
return -ENODEV;
}
return 0;
}
static int oti6858_port_probe(struct usb_serial_port *port) static int oti6858_port_probe(struct usb_serial_port *port)
{ {
struct oti6858_private *priv; struct oti6858_private *priv;
......
...@@ -33,9 +33,11 @@ ...@@ -33,9 +33,11 @@
#define PL2303_QUIRK_UART_STATE_IDX0 BIT(0) #define PL2303_QUIRK_UART_STATE_IDX0 BIT(0)
#define PL2303_QUIRK_LEGACY BIT(1) #define PL2303_QUIRK_LEGACY BIT(1)
#define PL2303_QUIRK_ENDPOINT_HACK BIT(2)
static const struct usb_device_id id_table[] = { static const struct usb_device_id id_table[] = {
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID) }, { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID),
.driver_info = PL2303_QUIRK_ENDPOINT_HACK },
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ2) }, { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ2) },
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_DCU11) }, { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_DCU11) },
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ3) }, { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ3) },
...@@ -48,7 +50,8 @@ static const struct usb_device_id id_table[] = { ...@@ -48,7 +50,8 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ZTEK) }, { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ZTEK) },
{ USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) }, { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) },
{ USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) }, { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) },
{ USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) }, { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID),
.driver_info = PL2303_QUIRK_ENDPOINT_HACK },
{ USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID2) }, { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID2) },
{ USB_DEVICE(ATEN_VENDOR_ID2, ATEN_PRODUCT_ID) }, { USB_DEVICE(ATEN_VENDOR_ID2, ATEN_PRODUCT_ID) },
{ USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) }, { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) },
...@@ -68,7 +71,8 @@ static const struct usb_device_id id_table[] = { ...@@ -68,7 +71,8 @@ static const struct usb_device_id id_table[] = {
.driver_info = PL2303_QUIRK_UART_STATE_IDX0 }, .driver_info = PL2303_QUIRK_UART_STATE_IDX0 },
{ USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X75), { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X75),
.driver_info = PL2303_QUIRK_UART_STATE_IDX0 }, .driver_info = PL2303_QUIRK_UART_STATE_IDX0 },
{ USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_EF81) }, { USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_EF81),
.driver_info = PL2303_QUIRK_ENDPOINT_HACK },
{ USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_ID_S81) }, /* Benq/Siemens S81 */ { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_ID_S81) }, /* Benq/Siemens S81 */
{ USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) }, { USB_DEVICE(SYNTECH_VENDOR_ID, SYNTECH_PRODUCT_ID) },
{ USB_DEVICE(NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID) }, { USB_DEVICE(NOKIA_CA42_VENDOR_ID, NOKIA_CA42_PRODUCT_ID) },
...@@ -78,7 +82,8 @@ static const struct usb_device_id id_table[] = { ...@@ -78,7 +82,8 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(SPEEDDRAGON_VENDOR_ID, SPEEDDRAGON_PRODUCT_ID) }, { USB_DEVICE(SPEEDDRAGON_VENDOR_ID, SPEEDDRAGON_PRODUCT_ID) },
{ USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID) }, { USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID) },
{ USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) }, { USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) },
{ USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) }, { USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID),
.driver_info = PL2303_QUIRK_ENDPOINT_HACK },
{ USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) }, { USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) },
{ USB_DEVICE(COREGA_VENDOR_ID, COREGA_PRODUCT_ID) }, { USB_DEVICE(COREGA_VENDOR_ID, COREGA_PRODUCT_ID) },
{ USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) }, { USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) },
...@@ -218,20 +223,68 @@ static int pl2303_probe(struct usb_serial *serial, ...@@ -218,20 +223,68 @@ static int pl2303_probe(struct usb_serial *serial,
return 0; return 0;
} }
/*
* Use interrupt endpoint from first interface if available.
*
* This is needed due to the looney way its endpoints are set up.
*/
static int pl2303_endpoint_hack(struct usb_serial *serial,
struct usb_serial_endpoints *epds)
{
struct usb_interface *interface = serial->interface;
struct usb_device *dev = serial->dev;
struct device *ddev = &interface->dev;
struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *endpoint;
unsigned int i;
if (interface == dev->actconfig->interface[0])
return 0;
/* check out the endpoints of the other interface */
iface_desc = dev->actconfig->interface[0]->cur_altsetting;
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
endpoint = &iface_desc->endpoint[i].desc;
if (!usb_endpoint_is_int_in(endpoint))
continue;
dev_dbg(ddev, "found interrupt in on separate interface\n");
if (epds->num_interrupt_in < ARRAY_SIZE(epds->interrupt_in))
epds->interrupt_in[epds->num_interrupt_in++] = endpoint;
}
return 0;
}
static int pl2303_calc_num_ports(struct usb_serial *serial,
struct usb_serial_endpoints *epds)
{
unsigned long quirks = (unsigned long)usb_get_serial_data(serial);
struct device *dev = &serial->interface->dev;
int ret;
if (quirks & PL2303_QUIRK_ENDPOINT_HACK) {
ret = pl2303_endpoint_hack(serial, epds);
if (ret)
return ret;
}
if (epds->num_interrupt_in < 1) {
dev_err(dev, "required interrupt-in endpoint missing\n");
return -ENODEV;
}
return 1;
}
static int pl2303_startup(struct usb_serial *serial) static int pl2303_startup(struct usb_serial *serial)
{ {
struct pl2303_serial_private *spriv; struct pl2303_serial_private *spriv;
unsigned char num_ports = serial->num_ports;
enum pl2303_type type = TYPE_01; enum pl2303_type type = TYPE_01;
unsigned char *buf; unsigned char *buf;
if (serial->num_bulk_in < num_ports ||
serial->num_bulk_out < num_ports ||
serial->num_interrupt_in < num_ports) {
dev_err(&serial->interface->dev, "missing endpoints\n");
return -ENODEV;
}
spriv = kzalloc(sizeof(*spriv), GFP_KERNEL); spriv = kzalloc(sizeof(*spriv), GFP_KERNEL);
if (!spriv) if (!spriv)
return -ENOMEM; return -ENOMEM;
...@@ -938,7 +991,9 @@ static struct usb_serial_driver pl2303_device = { ...@@ -938,7 +991,9 @@ static struct usb_serial_driver pl2303_device = {
.name = "pl2303", .name = "pl2303",
}, },
.id_table = id_table, .id_table = id_table,
.num_ports = 1, .num_bulk_in = 1,
.num_bulk_out = 1,
.num_interrupt_in = 0, /* see pl2303_calc_num_ports */
.bulk_in_size = 256, .bulk_in_size = 256,
.bulk_out_size = 256, .bulk_out_size = 256,
.open = pl2303_open, .open = pl2303_open,
...@@ -954,6 +1009,7 @@ static struct usb_serial_driver pl2303_device = { ...@@ -954,6 +1009,7 @@ static struct usb_serial_driver pl2303_device = {
.process_read_urb = pl2303_process_read_urb, .process_read_urb = pl2303_process_read_urb,
.read_int_callback = pl2303_read_int_callback, .read_int_callback = pl2303_read_int_callback,
.probe = pl2303_probe, .probe = pl2303_probe,
.calc_num_ports = pl2303_calc_num_ports,
.attach = pl2303_startup, .attach = pl2303_startup,
.release = pl2303_release, .release = pl2303_release,
.port_probe = pl2303_port_probe, .port_probe = pl2303_port_probe,
......
...@@ -246,7 +246,8 @@ static inline int update_mctrl(struct qt2_port_private *port_priv, ...@@ -246,7 +246,8 @@ static inline int update_mctrl(struct qt2_port_private *port_priv,
return status; return status;
} }
static int qt2_calc_num_ports(struct usb_serial *serial) static int qt2_calc_num_ports(struct usb_serial *serial,
struct usb_serial_endpoints *epds)
{ {
struct qt2_device_detail d; struct qt2_device_detail d;
int i; int i;
...@@ -600,7 +601,6 @@ static void qt2_process_read_urb(struct urb *urb) ...@@ -600,7 +601,6 @@ static void qt2_process_read_urb(struct urb *urb)
escapeflag = true; escapeflag = true;
break; break;
case QT2_CONTROL_ESCAPE: case QT2_CONTROL_ESCAPE:
tty_buffer_request_room(&port->port, 2);
tty_insert_flip_string(&port->port, ch, 2); tty_insert_flip_string(&port->port, ch, 2);
i += 2; i += 2;
escapeflag = true; escapeflag = true;
...@@ -615,8 +615,7 @@ static void qt2_process_read_urb(struct urb *urb) ...@@ -615,8 +615,7 @@ static void qt2_process_read_urb(struct urb *urb)
continue; continue;
} }
tty_buffer_request_room(&port->port, 1); tty_insert_flip_char(&port->port, *ch, TTY_NORMAL);
tty_insert_flip_string(&port->port, ch, 1);
} }
tty_flip_buffer_push(&port->port); tty_flip_buffer_push(&port->port);
......
...@@ -85,7 +85,8 @@ static int sierra_vsc_set_nmea(struct usb_device *udev, __u16 enable) ...@@ -85,7 +85,8 @@ static int sierra_vsc_set_nmea(struct usb_device *udev, __u16 enable)
USB_CTRL_SET_TIMEOUT); /* int timeout */ USB_CTRL_SET_TIMEOUT); /* int timeout */
} }
static int sierra_calc_num_ports(struct usb_serial *serial) static int sierra_calc_num_ports(struct usb_serial *serial,
struct usb_serial_endpoints *epds)
{ {
int num_ports = 0; int num_ports = 0;
u8 ifnum, numendpoints; u8 ifnum, numendpoints;
......
...@@ -154,19 +154,6 @@ static int spcp8x5_probe(struct usb_serial *serial, ...@@ -154,19 +154,6 @@ static int spcp8x5_probe(struct usb_serial *serial,
return 0; return 0;
} }
static int spcp8x5_attach(struct usb_serial *serial)
{
unsigned char num_ports = serial->num_ports;
if (serial->num_bulk_in < num_ports ||
serial->num_bulk_out < num_ports) {
dev_err(&serial->interface->dev, "missing endpoints\n");
return -ENODEV;
}
return 0;
}
static int spcp8x5_port_probe(struct usb_serial_port *port) static int spcp8x5_port_probe(struct usb_serial_port *port)
{ {
const struct usb_device_id *id = usb_get_serial_data(port->serial); const struct usb_device_id *id = usb_get_serial_data(port->serial);
...@@ -488,6 +475,8 @@ static struct usb_serial_driver spcp8x5_device = { ...@@ -488,6 +475,8 @@ static struct usb_serial_driver spcp8x5_device = {
}, },
.id_table = id_table, .id_table = id_table,
.num_ports = 1, .num_ports = 1,
.num_bulk_in = 1,
.num_bulk_out = 1,
.open = spcp8x5_open, .open = spcp8x5_open,
.dtr_rts = spcp8x5_dtr_rts, .dtr_rts = spcp8x5_dtr_rts,
.carrier_raised = spcp8x5_carrier_raised, .carrier_raised = spcp8x5_carrier_raised,
...@@ -496,7 +485,6 @@ static struct usb_serial_driver spcp8x5_device = { ...@@ -496,7 +485,6 @@ static struct usb_serial_driver spcp8x5_device = {
.tiocmget = spcp8x5_tiocmget, .tiocmget = spcp8x5_tiocmget,
.tiocmset = spcp8x5_tiocmset, .tiocmset = spcp8x5_tiocmset,
.probe = spcp8x5_probe, .probe = spcp8x5_probe,
.attach = spcp8x5_attach,
.port_probe = spcp8x5_port_probe, .port_probe = spcp8x5_port_probe,
.port_remove = spcp8x5_port_remove, .port_remove = spcp8x5_port_remove,
}; };
......
...@@ -147,16 +147,6 @@ static void symbol_unthrottle(struct tty_struct *tty) ...@@ -147,16 +147,6 @@ static void symbol_unthrottle(struct tty_struct *tty)
} }
} }
static int symbol_startup(struct usb_serial *serial)
{
if (!serial->num_interrupt_in) {
dev_err(&serial->dev->dev, "no interrupt-in endpoint\n");
return -ENODEV;
}
return 0;
}
static int symbol_port_probe(struct usb_serial_port *port) static int symbol_port_probe(struct usb_serial_port *port)
{ {
struct symbol_private *priv; struct symbol_private *priv;
...@@ -188,7 +178,7 @@ static struct usb_serial_driver symbol_device = { ...@@ -188,7 +178,7 @@ static struct usb_serial_driver symbol_device = {
}, },
.id_table = id_table, .id_table = id_table,
.num_ports = 1, .num_ports = 1,
.attach = symbol_startup, .num_interrupt_in = 1,
.port_probe = symbol_port_probe, .port_probe = symbol_port_probe,
.port_remove = symbol_port_remove, .port_remove = symbol_port_remove,
.open = symbol_open, .open = symbol_open,
......
...@@ -427,6 +427,7 @@ static struct usb_serial_driver ti_1port_device = { ...@@ -427,6 +427,7 @@ static struct usb_serial_driver ti_1port_device = {
.description = "TI USB 3410 1 port adapter", .description = "TI USB 3410 1 port adapter",
.id_table = ti_id_table_3410, .id_table = ti_id_table_3410,
.num_ports = 1, .num_ports = 1,
.num_bulk_out = 1,
.attach = ti_startup, .attach = ti_startup,
.release = ti_release, .release = ti_release,
.port_probe = ti_port_probe, .port_probe = ti_port_probe,
...@@ -459,6 +460,7 @@ static struct usb_serial_driver ti_2port_device = { ...@@ -459,6 +460,7 @@ static struct usb_serial_driver ti_2port_device = {
.description = "TI USB 5052 2 port adapter", .description = "TI USB 5052 2 port adapter",
.id_table = ti_id_table_5052, .id_table = ti_id_table_5052,
.num_ports = 2, .num_ports = 2,
.num_bulk_out = 1,
.attach = ti_startup, .attach = ti_startup,
.release = ti_release, .release = ti_release,
.port_probe = ti_port_probe, .port_probe = ti_port_probe,
...@@ -927,7 +929,6 @@ static void ti_set_termios(struct tty_struct *tty, ...@@ -927,7 +929,6 @@ static void ti_set_termios(struct tty_struct *tty,
{ {
struct ti_port *tport = usb_get_serial_port_data(port); struct ti_port *tport = usb_get_serial_port_data(port);
struct ti_uart_config *config; struct ti_uart_config *config;
tcflag_t cflag, iflag;
int baud; int baud;
int status; int status;
int port_number = port->port_number; int port_number = port->port_number;
...@@ -935,13 +936,6 @@ static void ti_set_termios(struct tty_struct *tty, ...@@ -935,13 +936,6 @@ static void ti_set_termios(struct tty_struct *tty,
u16 wbaudrate; u16 wbaudrate;
u16 wflags = 0; u16 wflags = 0;
cflag = tty->termios.c_cflag;
iflag = tty->termios.c_iflag;
dev_dbg(&port->dev, "%s - cflag %08x, iflag %08x\n", __func__, cflag, iflag);
dev_dbg(&port->dev, "%s - old clfag %08x, old iflag %08x\n", __func__,
old_termios->c_cflag, old_termios->c_iflag);
config = kmalloc(sizeof(*config), GFP_KERNEL); config = kmalloc(sizeof(*config), GFP_KERNEL);
if (!config) if (!config)
return; return;
......
...@@ -38,7 +38,6 @@ ...@@ -38,7 +38,6 @@
#include <linux/usb/serial.h> #include <linux/usb/serial.h>
#include <linux/kfifo.h> #include <linux/kfifo.h>
#include <linux/idr.h> #include <linux/idr.h>
#include "pl2303.h"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <gregkh@linuxfoundation.org>" #define DRIVER_AUTHOR "Greg Kroah-Hartman <gregkh@linuxfoundation.org>"
#define DRIVER_DESC "USB Serial Driver core" #define DRIVER_DESC "USB Serial Driver core"
...@@ -710,6 +709,39 @@ static const struct tty_port_operations serial_port_ops = { ...@@ -710,6 +709,39 @@ static const struct tty_port_operations serial_port_ops = {
.shutdown = serial_port_shutdown, .shutdown = serial_port_shutdown,
}; };
static void find_endpoints(struct usb_serial *serial,
struct usb_serial_endpoints *epds)
{
struct device *dev = &serial->interface->dev;
struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *epd;
unsigned int i;
BUILD_BUG_ON(ARRAY_SIZE(epds->bulk_in) < USB_MAXENDPOINTS / 2);
BUILD_BUG_ON(ARRAY_SIZE(epds->bulk_out) < USB_MAXENDPOINTS / 2);
BUILD_BUG_ON(ARRAY_SIZE(epds->interrupt_in) < USB_MAXENDPOINTS / 2);
BUILD_BUG_ON(ARRAY_SIZE(epds->interrupt_out) < USB_MAXENDPOINTS / 2);
iface_desc = serial->interface->cur_altsetting;
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
epd = &iface_desc->endpoint[i].desc;
if (usb_endpoint_is_bulk_in(epd)) {
dev_dbg(dev, "found bulk in on endpoint %u\n", i);
epds->bulk_in[epds->num_bulk_in++] = epd;
} else if (usb_endpoint_is_bulk_out(epd)) {
dev_dbg(dev, "found bulk out on endpoint %u\n", i);
epds->bulk_out[epds->num_bulk_out++] = epd;
} else if (usb_endpoint_is_int_in(epd)) {
dev_dbg(dev, "found interrupt in on endpoint %u\n", i);
epds->interrupt_in[epds->num_interrupt_in++] = epd;
} else if (usb_endpoint_is_int_out(epd)) {
dev_dbg(dev, "found interrupt out on endpoint %u\n", i);
epds->interrupt_out[epds->num_interrupt_out++] = epd;
}
}
}
static int usb_serial_probe(struct usb_interface *interface, static int usb_serial_probe(struct usb_interface *interface,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
...@@ -717,23 +749,15 @@ static int usb_serial_probe(struct usb_interface *interface, ...@@ -717,23 +749,15 @@ static int usb_serial_probe(struct usb_interface *interface,
struct usb_device *dev = interface_to_usbdev(interface); struct usb_device *dev = interface_to_usbdev(interface);
struct usb_serial *serial = NULL; struct usb_serial *serial = NULL;
struct usb_serial_port *port; struct usb_serial_port *port;
struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *endpoint; struct usb_endpoint_descriptor *endpoint;
struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS]; struct usb_serial_endpoints *epds;
struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS];
struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];
struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
struct usb_serial_driver *type = NULL; struct usb_serial_driver *type = NULL;
int retval; int retval;
int buffer_size; int buffer_size;
int i; int i;
int j; int j;
int num_interrupt_in = 0;
int num_interrupt_out = 0;
int num_bulk_in = 0;
int num_bulk_out = 0;
int num_ports = 0; int num_ports = 0;
int max_endpoints; unsigned char max_endpoints;
mutex_lock(&table_lock); mutex_lock(&table_lock);
type = search_serial_device(interface); type = search_serial_device(interface);
...@@ -752,8 +776,8 @@ static int usb_serial_probe(struct usb_interface *interface, ...@@ -752,8 +776,8 @@ static int usb_serial_probe(struct usb_interface *interface,
serial = create_serial(dev, interface, type); serial = create_serial(dev, interface, type);
if (!serial) { if (!serial) {
module_put(type->driver.owner); retval = -ENOMEM;
return -ENOMEM; goto err_put_module;
} }
/* if this device type has a probe function, call it */ /* if this device type has a probe function, call it */
...@@ -765,129 +789,48 @@ static int usb_serial_probe(struct usb_interface *interface, ...@@ -765,129 +789,48 @@ static int usb_serial_probe(struct usb_interface *interface,
if (retval) { if (retval) {
dev_dbg(ddev, "sub driver rejected device\n"); dev_dbg(ddev, "sub driver rejected device\n");
usb_serial_put(serial); goto err_put_serial;
module_put(type->driver.owner);
return retval;
} }
} }
/* descriptor matches, let's find the endpoints needed */ /* descriptor matches, let's find the endpoints needed */
/* check out the endpoints */ epds = kzalloc(sizeof(*epds), GFP_KERNEL);
iface_desc = interface->cur_altsetting; if (!epds) {
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { retval = -ENOMEM;
endpoint = &iface_desc->endpoint[i].desc; goto err_put_serial;
if (usb_endpoint_is_bulk_in(endpoint)) {
/* we found a bulk in endpoint */
dev_dbg(ddev, "found bulk in on endpoint %d\n", i);
if (num_bulk_in < MAX_NUM_PORTS) {
bulk_in_endpoint[num_bulk_in] = endpoint;
++num_bulk_in;
}
}
if (usb_endpoint_is_bulk_out(endpoint)) {
/* we found a bulk out endpoint */
dev_dbg(ddev, "found bulk out on endpoint %d\n", i);
if (num_bulk_out < MAX_NUM_PORTS) {
bulk_out_endpoint[num_bulk_out] = endpoint;
++num_bulk_out;
}
}
if (usb_endpoint_is_int_in(endpoint)) {
/* we found a interrupt in endpoint */
dev_dbg(ddev, "found interrupt in on endpoint %d\n", i);
if (num_interrupt_in < MAX_NUM_PORTS) {
interrupt_in_endpoint[num_interrupt_in] =
endpoint;
++num_interrupt_in;
}
}
if (usb_endpoint_is_int_out(endpoint)) {
/* we found an interrupt out endpoint */
dev_dbg(ddev, "found interrupt out on endpoint %d\n", i);
if (num_interrupt_out < MAX_NUM_PORTS) {
interrupt_out_endpoint[num_interrupt_out] =
endpoint;
++num_interrupt_out;
}
}
} }
#if IS_ENABLED(CONFIG_USB_SERIAL_PL2303) find_endpoints(serial, epds);
/* BEGIN HORRIBLE HACK FOR PL2303 */
/* this is needed due to the looney way its endpoints are set up */
if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&
(le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||
((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) &&
(le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) ||
((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) &&
(le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID)) ||
((le16_to_cpu(dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) &&
(le16_to_cpu(dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_EF81))) {
if (interface != dev->actconfig->interface[0]) {
/* check out the endpoints of the other interface*/
iface_desc = dev->actconfig->interface[0]->cur_altsetting;
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
endpoint = &iface_desc->endpoint[i].desc;
if (usb_endpoint_is_int_in(endpoint)) {
/* we found a interrupt in endpoint */
dev_dbg(ddev, "found interrupt in for Prolific device on separate interface\n");
if (num_interrupt_in < MAX_NUM_PORTS) {
interrupt_in_endpoint[num_interrupt_in] = endpoint;
++num_interrupt_in;
}
}
}
}
/* Now make sure the PL-2303 is configured correctly. if (epds->num_bulk_in < type->num_bulk_in ||
* If not, give up now and hope this hack will work epds->num_bulk_out < type->num_bulk_out ||
* properly during a later invocation of usb_serial_probe epds->num_interrupt_in < type->num_interrupt_in ||
*/ epds->num_interrupt_out < type->num_interrupt_out) {
if (num_bulk_in == 0 || num_bulk_out == 0) { dev_err(ddev, "required endpoints missing\n");
dev_info(ddev, "PL-2303 hack: descriptors matched but endpoints did not\n"); retval = -ENODEV;
usb_serial_put(serial); goto err_free_epds;
module_put(type->driver.owner);
return -ENODEV;
}
}
/* END HORRIBLE HACK FOR PL2303 */
#endif
#ifdef CONFIG_USB_SERIAL_GENERIC
if (type == &usb_serial_generic_device) {
num_ports = num_bulk_out;
if (num_ports == 0) {
dev_err(ddev, "Generic device with no bulk out, not allowed.\n");
usb_serial_put(serial);
module_put(type->driver.owner);
return -EIO;
}
dev_info(ddev, "The \"generic\" usb-serial driver is only for testing and one-off prototypes.\n");
dev_info(ddev, "Tell linux-usb@vger.kernel.org to add your device to a proper driver.\n");
} }
#endif
if (!num_ports) { if (type->calc_num_ports) {
/* if this device type has a calc_num_ports function, call it */ retval = type->calc_num_ports(serial, epds);
if (type->calc_num_ports) if (retval < 0)
num_ports = type->calc_num_ports(serial); goto err_free_epds;
if (!num_ports) num_ports = retval;
num_ports = type->num_ports;
} }
if (!num_ports)
num_ports = type->num_ports;
if (num_ports > MAX_NUM_PORTS) { if (num_ports > MAX_NUM_PORTS) {
dev_warn(ddev, "too many ports requested: %d\n", num_ports); dev_warn(ddev, "too many ports requested: %d\n", num_ports);
num_ports = MAX_NUM_PORTS; num_ports = MAX_NUM_PORTS;
} }
serial->num_ports = num_ports; serial->num_ports = (unsigned char)num_ports;
serial->num_bulk_in = num_bulk_in; serial->num_bulk_in = epds->num_bulk_in;
serial->num_bulk_out = num_bulk_out; serial->num_bulk_out = epds->num_bulk_out;
serial->num_interrupt_in = num_interrupt_in; serial->num_interrupt_in = epds->num_interrupt_in;
serial->num_interrupt_out = num_interrupt_out; serial->num_interrupt_out = epds->num_interrupt_out;
/* found all that we need */ /* found all that we need */
dev_info(ddev, "%s converter detected\n", type->description); dev_info(ddev, "%s converter detected\n", type->description);
...@@ -895,10 +838,10 @@ static int usb_serial_probe(struct usb_interface *interface, ...@@ -895,10 +838,10 @@ static int usb_serial_probe(struct usb_interface *interface,
/* create our ports, we need as many as the max endpoints */ /* create our ports, we need as many as the max endpoints */
/* we don't use num_ports here because some devices have more /* we don't use num_ports here because some devices have more
endpoint pairs than ports */ endpoint pairs than ports */
max_endpoints = max(num_bulk_in, num_bulk_out); max_endpoints = max(epds->num_bulk_in, epds->num_bulk_out);
max_endpoints = max(max_endpoints, num_interrupt_in); max_endpoints = max(max_endpoints, epds->num_interrupt_in);
max_endpoints = max(max_endpoints, num_interrupt_out); max_endpoints = max(max_endpoints, epds->num_interrupt_out);
max_endpoints = max(max_endpoints, (int)serial->num_ports); max_endpoints = max(max_endpoints, serial->num_ports);
serial->num_port_pointers = max_endpoints; serial->num_port_pointers = max_endpoints;
dev_dbg(ddev, "setting up %d port structure(s)\n", max_endpoints); dev_dbg(ddev, "setting up %d port structure(s)\n", max_endpoints);
...@@ -923,8 +866,8 @@ static int usb_serial_probe(struct usb_interface *interface, ...@@ -923,8 +866,8 @@ static int usb_serial_probe(struct usb_interface *interface,
} }
/* set up the endpoint information */ /* set up the endpoint information */
for (i = 0; i < num_bulk_in; ++i) { for (i = 0; i < epds->num_bulk_in; ++i) {
endpoint = bulk_in_endpoint[i]; endpoint = epds->bulk_in[i];
port = serial->port[i]; port = serial->port[i];
buffer_size = max_t(int, serial->type->bulk_in_size, buffer_size = max_t(int, serial->type->bulk_in_size,
usb_endpoint_maxp(endpoint)); usb_endpoint_maxp(endpoint));
...@@ -952,8 +895,8 @@ static int usb_serial_probe(struct usb_interface *interface, ...@@ -952,8 +895,8 @@ static int usb_serial_probe(struct usb_interface *interface,
port->bulk_in_buffer = port->bulk_in_buffers[0]; port->bulk_in_buffer = port->bulk_in_buffers[0];
} }
for (i = 0; i < num_bulk_out; ++i) { for (i = 0; i < epds->num_bulk_out; ++i) {
endpoint = bulk_out_endpoint[i]; endpoint = epds->bulk_out[i];
port = serial->port[i]; port = serial->port[i];
if (kfifo_alloc(&port->write_fifo, PAGE_SIZE, GFP_KERNEL)) if (kfifo_alloc(&port->write_fifo, PAGE_SIZE, GFP_KERNEL))
goto probe_error; goto probe_error;
...@@ -985,8 +928,8 @@ static int usb_serial_probe(struct usb_interface *interface, ...@@ -985,8 +928,8 @@ static int usb_serial_probe(struct usb_interface *interface,
} }
if (serial->type->read_int_callback) { if (serial->type->read_int_callback) {
for (i = 0; i < num_interrupt_in; ++i) { for (i = 0; i < epds->num_interrupt_in; ++i) {
endpoint = interrupt_in_endpoint[i]; endpoint = epds->interrupt_in[i];
port = serial->port[i]; port = serial->port[i];
port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL); port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!port->interrupt_in_urb) if (!port->interrupt_in_urb)
...@@ -1005,13 +948,13 @@ static int usb_serial_probe(struct usb_interface *interface, ...@@ -1005,13 +948,13 @@ static int usb_serial_probe(struct usb_interface *interface,
serial->type->read_int_callback, port, serial->type->read_int_callback, port,
endpoint->bInterval); endpoint->bInterval);
} }
} else if (num_interrupt_in) { } else if (epds->num_interrupt_in) {
dev_dbg(ddev, "The device claims to support interrupt in transfers, but read_int_callback is not defined\n"); dev_dbg(ddev, "The device claims to support interrupt in transfers, but read_int_callback is not defined\n");
} }
if (serial->type->write_int_callback) { if (serial->type->write_int_callback) {
for (i = 0; i < num_interrupt_out; ++i) { for (i = 0; i < epds->num_interrupt_out; ++i) {
endpoint = interrupt_out_endpoint[i]; endpoint = epds->interrupt_out[i];
port = serial->port[i]; port = serial->port[i];
port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL); port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!port->interrupt_out_urb) if (!port->interrupt_out_urb)
...@@ -1031,7 +974,7 @@ static int usb_serial_probe(struct usb_interface *interface, ...@@ -1031,7 +974,7 @@ static int usb_serial_probe(struct usb_interface *interface,
serial->type->write_int_callback, port, serial->type->write_int_callback, port,
endpoint->bInterval); endpoint->bInterval);
} }
} else if (num_interrupt_out) { } else if (epds->num_interrupt_out) {
dev_dbg(ddev, "The device claims to support interrupt out transfers, but write_int_callback is not defined\n"); dev_dbg(ddev, "The device claims to support interrupt out transfers, but write_int_callback is not defined\n");
} }
...@@ -1053,12 +996,6 @@ static int usb_serial_probe(struct usb_interface *interface, ...@@ -1053,12 +996,6 @@ static int usb_serial_probe(struct usb_interface *interface,
serial->attached = 1; serial->attached = 1;
} }
/* Avoid race with tty_open and serial_install by setting the
* disconnected flag and not clearing it until all ports have been
* registered.
*/
serial->disconnected = 1;
if (allocate_minors(serial, num_ports)) { if (allocate_minors(serial, num_ports)) {
dev_err(ddev, "No more free serial minor numbers\n"); dev_err(ddev, "No more free serial minor numbers\n");
goto probe_error; goto probe_error;
...@@ -1076,18 +1013,23 @@ static int usb_serial_probe(struct usb_interface *interface, ...@@ -1076,18 +1013,23 @@ static int usb_serial_probe(struct usb_interface *interface,
dev_err(ddev, "Error registering port device, continuing\n"); dev_err(ddev, "Error registering port device, continuing\n");
} }
serial->disconnected = 0;
if (num_ports > 0) if (num_ports > 0)
usb_serial_console_init(serial->port[0]->minor); usb_serial_console_init(serial->port[0]->minor);
exit: exit:
kfree(epds);
module_put(type->driver.owner); module_put(type->driver.owner);
return 0; return 0;
probe_error: probe_error:
retval = -EIO;
err_free_epds:
kfree(epds);
err_put_serial:
usb_serial_put(serial); usb_serial_put(serial);
err_put_module:
module_put(type->driver.owner); module_put(type->driver.owner);
return -EIO;
return retval;
} }
static void usb_serial_disconnect(struct usb_interface *interface) static void usb_serial_disconnect(struct usb_interface *interface)
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
#define USB_DEBUG_MAX_PACKET_SIZE 8 #define USB_DEBUG_MAX_PACKET_SIZE 8
#define USB_DEBUG_BRK_SIZE 8 #define USB_DEBUG_BRK_SIZE 8
static char USB_DEBUG_BRK[USB_DEBUG_BRK_SIZE] = { static const char USB_DEBUG_BRK[USB_DEBUG_BRK_SIZE] = {
0x00, 0x00,
0xff, 0xff,
0x01, 0x01,
......
...@@ -40,11 +40,12 @@ static int visor_open(struct tty_struct *tty, struct usb_serial_port *port); ...@@ -40,11 +40,12 @@ static int visor_open(struct tty_struct *tty, struct usb_serial_port *port);
static void visor_close(struct usb_serial_port *port); static void visor_close(struct usb_serial_port *port);
static int visor_probe(struct usb_serial *serial, static int visor_probe(struct usb_serial *serial,
const struct usb_device_id *id); const struct usb_device_id *id);
static int visor_calc_num_ports(struct usb_serial *serial); static int visor_calc_num_ports(struct usb_serial *serial,
struct usb_serial_endpoints *epds);
static int clie_5_calc_num_ports(struct usb_serial *serial,
struct usb_serial_endpoints *epds);
static void visor_read_int_callback(struct urb *urb); static void visor_read_int_callback(struct urb *urb);
static int clie_3_5_startup(struct usb_serial *serial); static int clie_3_5_startup(struct usb_serial *serial);
static int treo_attach(struct usb_serial *serial);
static int clie_5_attach(struct usb_serial *serial);
static int palm_os_3_probe(struct usb_serial *serial, static int palm_os_3_probe(struct usb_serial *serial,
const struct usb_device_id *id); const struct usb_device_id *id);
static int palm_os_4_probe(struct usb_serial *serial, static int palm_os_4_probe(struct usb_serial *serial,
...@@ -174,7 +175,6 @@ static struct usb_serial_driver handspring_device = { ...@@ -174,7 +175,6 @@ static struct usb_serial_driver handspring_device = {
.close = visor_close, .close = visor_close,
.throttle = usb_serial_generic_throttle, .throttle = usb_serial_generic_throttle,
.unthrottle = usb_serial_generic_unthrottle, .unthrottle = usb_serial_generic_unthrottle,
.attach = treo_attach,
.probe = visor_probe, .probe = visor_probe,
.calc_num_ports = visor_calc_num_ports, .calc_num_ports = visor_calc_num_ports,
.read_int_callback = visor_read_int_callback, .read_int_callback = visor_read_int_callback,
...@@ -189,14 +189,14 @@ static struct usb_serial_driver clie_5_device = { ...@@ -189,14 +189,14 @@ static struct usb_serial_driver clie_5_device = {
.description = "Sony Clie 5.0", .description = "Sony Clie 5.0",
.id_table = clie_id_5_table, .id_table = clie_id_5_table,
.num_ports = 2, .num_ports = 2,
.num_bulk_out = 2,
.bulk_out_size = 256, .bulk_out_size = 256,
.open = visor_open, .open = visor_open,
.close = visor_close, .close = visor_close,
.throttle = usb_serial_generic_throttle, .throttle = usb_serial_generic_throttle,
.unthrottle = usb_serial_generic_unthrottle, .unthrottle = usb_serial_generic_unthrottle,
.attach = clie_5_attach,
.probe = visor_probe, .probe = visor_probe,
.calc_num_ports = visor_calc_num_ports, .calc_num_ports = clie_5_calc_num_ports,
.read_int_callback = visor_read_int_callback, .read_int_callback = visor_read_int_callback,
}; };
...@@ -466,16 +466,60 @@ static int visor_probe(struct usb_serial *serial, ...@@ -466,16 +466,60 @@ static int visor_probe(struct usb_serial *serial,
return retval; return retval;
} }
static int visor_calc_num_ports(struct usb_serial *serial) static int visor_calc_num_ports(struct usb_serial *serial,
struct usb_serial_endpoints *epds)
{ {
unsigned int vid = le16_to_cpu(serial->dev->descriptor.idVendor);
int num_ports = (int)(long)(usb_get_serial_data(serial)); int num_ports = (int)(long)(usb_get_serial_data(serial));
if (num_ports) if (num_ports)
usb_set_serial_data(serial, NULL); usb_set_serial_data(serial, NULL);
/*
* Only swap the bulk endpoints for the Handspring devices with
* interrupt in endpoints, which for now are the Treo devices.
*/
if (!(vid == HANDSPRING_VENDOR_ID || vid == KYOCERA_VENDOR_ID) ||
epds->num_interrupt_in == 0)
goto out;
if (epds->num_bulk_in < 2 || epds->num_interrupt_in < 2) {
dev_err(&serial->interface->dev, "missing endpoints\n");
return -ENODEV;
}
/*
* It appears that Treos and Kyoceras want to use the
* 1st bulk in endpoint to communicate with the 2nd bulk out endpoint,
* so let's swap the 1st and 2nd bulk in and interrupt endpoints.
* Note that swapping the bulk out endpoints would break lots of
* apps that want to communicate on the second port.
*/
swap(epds->bulk_in[0], epds->bulk_in[1]);
swap(epds->interrupt_in[0], epds->interrupt_in[1]);
out:
return num_ports; return num_ports;
} }
static int clie_5_calc_num_ports(struct usb_serial *serial,
struct usb_serial_endpoints *epds)
{
/*
* TH55 registers 2 ports.
* Communication in from the UX50/TH55 uses the first bulk-in
* endpoint, while communication out to the UX50/TH55 uses the second
* bulk-out endpoint.
*/
/*
* FIXME: Should we swap the descriptors instead of using the same
* bulk-out endpoint for both ports?
*/
epds->bulk_out[0] = epds->bulk_out[1];
return serial->type->num_ports;
}
static int clie_3_5_startup(struct usb_serial *serial) static int clie_3_5_startup(struct usb_serial *serial)
{ {
struct device *dev = &serial->dev->dev; struct device *dev = &serial->dev->dev;
...@@ -531,94 +575,6 @@ static int clie_3_5_startup(struct usb_serial *serial) ...@@ -531,94 +575,6 @@ static int clie_3_5_startup(struct usb_serial *serial)
return result; return result;
} }
static int treo_attach(struct usb_serial *serial)
{
struct usb_serial_port *swap_port;
/* Only do this endpoint hack for the Handspring devices with
* interrupt in endpoints, which for now are the Treo devices. */
if (!((le16_to_cpu(serial->dev->descriptor.idVendor)
== HANDSPRING_VENDOR_ID) ||
(le16_to_cpu(serial->dev->descriptor.idVendor)
== KYOCERA_VENDOR_ID)) ||
(serial->num_interrupt_in == 0))
return 0;
if (serial->num_bulk_in < 2 || serial->num_interrupt_in < 2) {
dev_err(&serial->interface->dev, "missing endpoints\n");
return -ENODEV;
}
/*
* It appears that Treos and Kyoceras want to use the
* 1st bulk in endpoint to communicate with the 2nd bulk out endpoint,
* so let's swap the 1st and 2nd bulk in and interrupt endpoints.
* Note that swapping the bulk out endpoints would break lots of
* apps that want to communicate on the second port.
*/
#define COPY_PORT(dest, src) \
do { \
int i; \
\
for (i = 0; i < ARRAY_SIZE(src->read_urbs); ++i) { \
dest->read_urbs[i] = src->read_urbs[i]; \
dest->read_urbs[i]->context = dest; \
dest->bulk_in_buffers[i] = src->bulk_in_buffers[i]; \
} \
dest->read_urb = src->read_urb; \
dest->bulk_in_endpointAddress = src->bulk_in_endpointAddress;\
dest->bulk_in_buffer = src->bulk_in_buffer; \
dest->bulk_in_size = src->bulk_in_size; \
dest->interrupt_in_urb = src->interrupt_in_urb; \
dest->interrupt_in_urb->context = dest; \
dest->interrupt_in_endpointAddress = \
src->interrupt_in_endpointAddress;\
dest->interrupt_in_buffer = src->interrupt_in_buffer; \
} while (0);
swap_port = kmalloc(sizeof(*swap_port), GFP_KERNEL);
if (!swap_port)
return -ENOMEM;
COPY_PORT(swap_port, serial->port[0]);
COPY_PORT(serial->port[0], serial->port[1]);
COPY_PORT(serial->port[1], swap_port);
kfree(swap_port);
return 0;
}
static int clie_5_attach(struct usb_serial *serial)
{
struct usb_serial_port *port;
unsigned int pipe;
int j;
/* TH55 registers 2 ports.
Communication in from the UX50/TH55 uses bulk_in_endpointAddress
from port 0. Communication out to the UX50/TH55 uses
bulk_out_endpointAddress from port 1
Lets do a quick and dirty mapping
*/
/* some sanity check */
if (serial->num_bulk_out < 2) {
dev_err(&serial->interface->dev, "missing bulk out endpoints\n");
return -ENODEV;
}
/* port 0 now uses the modified endpoint Address */
port = serial->port[0];
port->bulk_out_endpointAddress =
serial->port[1]->bulk_out_endpointAddress;
pipe = usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress);
for (j = 0; j < ARRAY_SIZE(port->write_urbs); ++j)
port->write_urbs[j]->pipe = pipe;
return 0;
}
module_usb_serial_driver(serial_drivers, id_table_combined); module_usb_serial_driver(serial_drivers, id_table_combined);
MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_AUTHOR(DRIVER_AUTHOR);
......
...@@ -80,8 +80,6 @@ static int whiteheat_firmware_download(struct usb_serial *serial, ...@@ -80,8 +80,6 @@ static int whiteheat_firmware_download(struct usb_serial *serial,
static int whiteheat_firmware_attach(struct usb_serial *serial); static int whiteheat_firmware_attach(struct usb_serial *serial);
/* function prototypes for the Connect Tech WhiteHEAT serial converter */ /* function prototypes for the Connect Tech WhiteHEAT serial converter */
static int whiteheat_probe(struct usb_serial *serial,
const struct usb_device_id *id);
static int whiteheat_attach(struct usb_serial *serial); static int whiteheat_attach(struct usb_serial *serial);
static void whiteheat_release(struct usb_serial *serial); static void whiteheat_release(struct usb_serial *serial);
static int whiteheat_port_probe(struct usb_serial_port *port); static int whiteheat_port_probe(struct usb_serial_port *port);
...@@ -118,7 +116,8 @@ static struct usb_serial_driver whiteheat_device = { ...@@ -118,7 +116,8 @@ static struct usb_serial_driver whiteheat_device = {
.description = "Connect Tech - WhiteHEAT", .description = "Connect Tech - WhiteHEAT",
.id_table = id_table_std, .id_table = id_table_std,
.num_ports = 4, .num_ports = 4,
.probe = whiteheat_probe, .num_bulk_in = 5,
.num_bulk_out = 5,
.attach = whiteheat_attach, .attach = whiteheat_attach,
.release = whiteheat_release, .release = whiteheat_release,
.port_probe = whiteheat_port_probe, .port_probe = whiteheat_port_probe,
...@@ -221,33 +220,6 @@ static int whiteheat_firmware_attach(struct usb_serial *serial) ...@@ -221,33 +220,6 @@ static int whiteheat_firmware_attach(struct usb_serial *serial)
* Connect Tech's White Heat serial driver functions * Connect Tech's White Heat serial driver functions
*****************************************************************************/ *****************************************************************************/
static int whiteheat_probe(struct usb_serial *serial,
const struct usb_device_id *id)
{
struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *endpoint;
size_t num_bulk_in = 0;
size_t num_bulk_out = 0;
size_t min_num_bulk;
unsigned int i;
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;
if (usb_endpoint_is_bulk_out(endpoint))
++num_bulk_out;
}
min_num_bulk = COMMAND_PORT + 1;
if (num_bulk_in < min_num_bulk || num_bulk_out < min_num_bulk)
return -ENODEV;
return 0;
}
static int whiteheat_attach(struct usb_serial *serial) static int whiteheat_attach(struct usb_serial *serial)
{ {
struct usb_serial_port *command_port; struct usb_serial_port *command_port;
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#include <linux/kfifo.h> #include <linux/kfifo.h>
/* The maximum number of ports one device can grab at once */ /* The maximum number of ports one device can grab at once */
#define MAX_NUM_PORTS 8 #define MAX_NUM_PORTS 16
/* parity check flag */ /* parity check flag */
#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
...@@ -159,10 +159,10 @@ struct usb_serial { ...@@ -159,10 +159,10 @@ struct usb_serial {
unsigned char minors_reserved:1; unsigned char minors_reserved:1;
unsigned char num_ports; unsigned char num_ports;
unsigned char num_port_pointers; unsigned char num_port_pointers;
char num_interrupt_in; unsigned char num_interrupt_in;
char num_interrupt_out; unsigned char num_interrupt_out;
char num_bulk_in; unsigned char num_bulk_in;
char num_bulk_out; unsigned char num_bulk_out;
struct usb_serial_port *port[MAX_NUM_PORTS]; struct usb_serial_port *port[MAX_NUM_PORTS];
struct kref kref; struct kref kref;
struct mutex disc_mutex; struct mutex disc_mutex;
...@@ -181,6 +181,17 @@ static inline void usb_set_serial_data(struct usb_serial *serial, void *data) ...@@ -181,6 +181,17 @@ static inline void usb_set_serial_data(struct usb_serial *serial, void *data)
serial->private = data; serial->private = data;
} }
struct usb_serial_endpoints {
unsigned char num_bulk_in;
unsigned char num_bulk_out;
unsigned char num_interrupt_in;
unsigned char num_interrupt_out;
struct usb_endpoint_descriptor *bulk_in[MAX_NUM_PORTS];
struct usb_endpoint_descriptor *bulk_out[MAX_NUM_PORTS];
struct usb_endpoint_descriptor *interrupt_in[MAX_NUM_PORTS];
struct usb_endpoint_descriptor *interrupt_out[MAX_NUM_PORTS];
};
/** /**
* usb_serial_driver - describes a usb serial driver * usb_serial_driver - describes a usb serial driver
* @description: pointer to a string that describes this driver. This string * @description: pointer to a string that describes this driver. This string
...@@ -188,12 +199,17 @@ static inline void usb_set_serial_data(struct usb_serial *serial, void *data) ...@@ -188,12 +199,17 @@ static inline void usb_set_serial_data(struct usb_serial *serial, void *data)
* @id_table: pointer to a list of usb_device_id structures that define all * @id_table: pointer to a list of usb_device_id structures that define all
* of the devices this structure can support. * of the devices this structure can support.
* @num_ports: the number of different ports this device will have. * @num_ports: the number of different ports this device will have.
* @num_bulk_in: minimum number of bulk-in endpoints
* @num_bulk_out: minimum number of bulk-out endpoints
* @num_interrupt_in: minimum number of interrupt-in endpoints
* @num_interrupt_out: minimum number of interrupt-out endpoints
* @bulk_in_size: minimum number of bytes to allocate for bulk-in buffer * @bulk_in_size: minimum number of bytes to allocate for bulk-in buffer
* (0 = end-point size) * (0 = end-point size)
* @bulk_out_size: bytes to allocate for bulk-out buffer (0 = end-point size) * @bulk_out_size: bytes to allocate for bulk-out buffer (0 = end-point size)
* @calc_num_ports: pointer to a function to determine how many ports this * @calc_num_ports: pointer to a function to determine how many ports this
* device has dynamically. It will be called after the probe() * device has dynamically. It can also be used to verify the number of
* callback is called, but before attach() * endpoints or to modify the port-endpoint mapping. It will be called
* after the probe() callback is called, but before attach().
* @probe: pointer to the driver's probe function. * @probe: pointer to the driver's probe function.
* This will be called when the device is inserted into the system, * This will be called when the device is inserted into the system,
* but before the device has been fully initialized by the usb_serial * but before the device has been fully initialized by the usb_serial
...@@ -227,19 +243,26 @@ static inline void usb_set_serial_data(struct usb_serial *serial, void *data) ...@@ -227,19 +243,26 @@ static inline void usb_set_serial_data(struct usb_serial *serial, void *data)
struct usb_serial_driver { struct usb_serial_driver {
const char *description; const char *description;
const struct usb_device_id *id_table; const struct usb_device_id *id_table;
char num_ports;
struct list_head driver_list; struct list_head driver_list;
struct device_driver driver; struct device_driver driver;
struct usb_driver *usb_driver; struct usb_driver *usb_driver;
struct usb_dynids dynids; struct usb_dynids dynids;
unsigned char num_ports;
unsigned char num_bulk_in;
unsigned char num_bulk_out;
unsigned char num_interrupt_in;
unsigned char num_interrupt_out;
size_t bulk_in_size; size_t bulk_in_size;
size_t bulk_out_size; size_t bulk_out_size;
int (*probe)(struct usb_serial *serial, const struct usb_device_id *id); int (*probe)(struct usb_serial *serial, const struct usb_device_id *id);
int (*attach)(struct usb_serial *serial); int (*attach)(struct usb_serial *serial);
int (*calc_num_ports) (struct usb_serial *serial); int (*calc_num_ports)(struct usb_serial *serial,
struct usb_serial_endpoints *epds);
void (*disconnect)(struct usb_serial *serial); void (*disconnect)(struct usb_serial *serial);
void (*release)(struct usb_serial *serial); void (*release)(struct usb_serial *serial);
...@@ -356,7 +379,6 @@ extern void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port, ...@@ -356,7 +379,6 @@ extern void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port,
extern int usb_serial_bus_register(struct usb_serial_driver *device); extern int usb_serial_bus_register(struct usb_serial_driver *device);
extern void usb_serial_bus_deregister(struct usb_serial_driver *device); extern void usb_serial_bus_deregister(struct usb_serial_driver *device);
extern struct usb_serial_driver usb_serial_generic_device;
extern struct bus_type usb_serial_bus_type; extern struct bus_type usb_serial_bus_type;
extern struct tty_driver *usb_serial_tty_driver; extern struct tty_driver *usb_serial_tty_driver;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment