Commit eaa51998 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

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

Merge tag 'usb-serial-5.6-rc1' of https://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial into usb-next

Johan writes:

Here are the USB-serial updates for 5.6-rc1, including:

 - a missing ir-usb endpoint sanity check
 - fixes for two long-standing regressions in ir-usb
 - opticon chars_in_buffer support

Included are also various clean ups.

All have been in linux-next with no reported issues.
Signed-off-by: default avatarJohan Hovold <johan@kernel.org>

* tag 'usb-serial-5.6-rc1' of https://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial:
  USB: serial: cyberjack: fix spelling mistake "To" -> "Too"
  USB: serial: ir-usb: simplify endpoint check
  USB: serial: ir-usb: make set_termios synchronous
  USB: serial: ir-usb: fix IrLAP framing
  USB: serial: ir-usb: fix link-speed handling
  USB: serial: ir-usb: add missing endpoint sanity check
  USB: serial: garmin_gps: Use flexible-array member
  USB: serial: opticon: stop all I/O on close()
  USB: serial: opticon: add chars_in_buffer() implementation
parents 88008266 19c64e73
...@@ -276,7 +276,7 @@ static void cyberjack_read_int_callback(struct urb *urb) ...@@ -276,7 +276,7 @@ static void cyberjack_read_int_callback(struct urb *urb)
old_rdtodo = priv->rdtodo; old_rdtodo = priv->rdtodo;
if (old_rdtodo > SHRT_MAX - size) { if (old_rdtodo > SHRT_MAX - size) {
dev_dbg(dev, "To many bulk_in urbs to do.\n"); dev_dbg(dev, "Too many bulk_in urbs to do.\n");
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
goto resubmit; goto resubmit;
} }
......
...@@ -104,7 +104,7 @@ struct garmin_packet { ...@@ -104,7 +104,7 @@ struct garmin_packet {
int seq; int seq;
/* the real size of the data array, always > 0 */ /* the real size of the data array, always > 0 */
int size; int size;
__u8 data[1]; __u8 data[];
}; };
/* structure used to keep the current state of the driver */ /* structure used to keep the current state of the driver */
......
...@@ -45,9 +45,10 @@ static int buffer_size; ...@@ -45,9 +45,10 @@ static int buffer_size;
static int xbof = -1; static int xbof = -1;
static int ir_startup (struct usb_serial *serial); static int ir_startup (struct usb_serial *serial);
static int ir_open(struct tty_struct *tty, struct usb_serial_port *port); static int ir_write(struct tty_struct *tty, struct usb_serial_port *port,
static int ir_prepare_write_buffer(struct usb_serial_port *port, const unsigned char *buf, int count);
void *dest, size_t size); static int ir_write_room(struct tty_struct *tty);
static void ir_write_bulk_callback(struct urb *urb);
static void ir_process_read_urb(struct urb *urb); static void ir_process_read_urb(struct urb *urb);
static void ir_set_termios(struct tty_struct *tty, static void ir_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios); struct usb_serial_port *port, struct ktermios *old_termios);
...@@ -75,10 +76,13 @@ static struct usb_serial_driver ir_device = { ...@@ -75,10 +76,13 @@ static struct usb_serial_driver ir_device = {
.description = "IR Dongle", .description = "IR Dongle",
.id_table = ir_id_table, .id_table = ir_id_table,
.num_ports = 1, .num_ports = 1,
.num_bulk_in = 1,
.num_bulk_out = 1,
.set_termios = ir_set_termios, .set_termios = ir_set_termios,
.attach = ir_startup, .attach = ir_startup,
.open = ir_open, .write = ir_write,
.prepare_write_buffer = ir_prepare_write_buffer, .write_room = ir_write_room,
.write_bulk_callback = ir_write_bulk_callback,
.process_read_urb = ir_process_read_urb, .process_read_urb = ir_process_read_urb,
}; };
...@@ -251,35 +255,102 @@ static int ir_startup(struct usb_serial *serial) ...@@ -251,35 +255,102 @@ static int ir_startup(struct usb_serial *serial)
return 0; return 0;
} }
static int ir_open(struct tty_struct *tty, struct usb_serial_port *port) static int ir_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count)
{ {
int i; struct urb *urb = NULL;
unsigned long flags;
int ret;
for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) if (port->bulk_out_size == 0)
port->write_urbs[i]->transfer_flags = URB_ZERO_PACKET; return -EINVAL;
/* Start reading from the device */ if (count == 0)
return usb_serial_generic_open(tty, port); return 0;
}
static int ir_prepare_write_buffer(struct usb_serial_port *port, count = min(count, port->bulk_out_size - 1);
void *dest, size_t size)
{ spin_lock_irqsave(&port->lock, flags);
unsigned char *buf = dest; if (__test_and_clear_bit(0, &port->write_urbs_free)) {
int count; urb = port->write_urbs[0];
port->tx_bytes += count;
}
spin_unlock_irqrestore(&port->lock, flags);
if (!urb)
return 0;
/* /*
* The first byte of the packet we send to the device contains an * The first byte of the packet we send to the device contains an
* inbound header which indicates an additional number of BOFs and * outbound header which indicates an additional number of BOFs and
* a baud rate change. * a baud rate change.
* *
* See section 5.4.2.2 of the USB IrDA spec. * See section 5.4.2.2 of the USB IrDA spec.
*/ */
*buf = ir_xbof | ir_baud; *(u8 *)urb->transfer_buffer = ir_xbof | ir_baud;
memcpy(urb->transfer_buffer + 1, buf, count);
urb->transfer_buffer_length = count + 1;
urb->transfer_flags = URB_ZERO_PACKET;
ret = usb_submit_urb(urb, GFP_ATOMIC);
if (ret) {
dev_err(&port->dev, "failed to submit write urb: %d\n", ret);
spin_lock_irqsave(&port->lock, flags);
__set_bit(0, &port->write_urbs_free);
port->tx_bytes -= count;
spin_unlock_irqrestore(&port->lock, flags);
return ret;
}
return count;
}
static void ir_write_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
int status = urb->status;
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
__set_bit(0, &port->write_urbs_free);
port->tx_bytes -= urb->transfer_buffer_length - 1;
spin_unlock_irqrestore(&port->lock, flags);
switch (status) {
case 0:
break;
case -ENOENT:
case -ECONNRESET:
case -ESHUTDOWN:
dev_dbg(&port->dev, "write urb stopped: %d\n", status);
return;
case -EPIPE:
dev_err(&port->dev, "write urb stopped: %d\n", status);
return;
default:
dev_err(&port->dev, "nonzero write-urb status: %d\n", status);
break;
}
usb_serial_port_softint(port);
}
count = kfifo_out_locked(&port->write_fifo, buf + 1, size - 1, static int ir_write_room(struct tty_struct *tty)
&port->lock); {
return count + 1; struct usb_serial_port *port = tty->driver_data;
int count = 0;
if (port->bulk_out_size == 0)
return 0;
if (test_bit(0, &port->write_urbs_free))
count = port->bulk_out_size - 1;
return count;
} }
static void ir_process_read_urb(struct urb *urb) static void ir_process_read_urb(struct urb *urb)
...@@ -304,23 +375,15 @@ static void ir_process_read_urb(struct urb *urb) ...@@ -304,23 +375,15 @@ static void ir_process_read_urb(struct urb *urb)
tty_flip_buffer_push(&port->port); tty_flip_buffer_push(&port->port);
} }
static void ir_set_termios_callback(struct urb *urb)
{
kfree(urb->transfer_buffer);
if (urb->status)
dev_dbg(&urb->dev->dev, "%s - non-zero urb status: %d\n",
__func__, urb->status);
}
static void ir_set_termios(struct tty_struct *tty, static void ir_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 urb *urb; struct usb_device *udev = port->serial->dev;
unsigned char *transfer_buffer; unsigned char *transfer_buffer;
int result; int actual_length;
speed_t baud; speed_t baud;
int ir_baud; int ir_baud;
int ret;
baud = tty_get_baud_rate(tty); baud = tty_get_baud_rate(tty);
...@@ -332,34 +395,34 @@ static void ir_set_termios(struct tty_struct *tty, ...@@ -332,34 +395,34 @@ static void ir_set_termios(struct tty_struct *tty,
switch (baud) { switch (baud) {
case 2400: case 2400:
ir_baud = USB_IRDA_BR_2400; ir_baud = USB_IRDA_LS_2400;
break; break;
case 9600: case 9600:
ir_baud = USB_IRDA_BR_9600; ir_baud = USB_IRDA_LS_9600;
break; break;
case 19200: case 19200:
ir_baud = USB_IRDA_BR_19200; ir_baud = USB_IRDA_LS_19200;
break; break;
case 38400: case 38400:
ir_baud = USB_IRDA_BR_38400; ir_baud = USB_IRDA_LS_38400;
break; break;
case 57600: case 57600:
ir_baud = USB_IRDA_BR_57600; ir_baud = USB_IRDA_LS_57600;
break; break;
case 115200: case 115200:
ir_baud = USB_IRDA_BR_115200; ir_baud = USB_IRDA_LS_115200;
break; break;
case 576000: case 576000:
ir_baud = USB_IRDA_BR_576000; ir_baud = USB_IRDA_LS_576000;
break; break;
case 1152000: case 1152000:
ir_baud = USB_IRDA_BR_1152000; ir_baud = USB_IRDA_LS_1152000;
break; break;
case 4000000: case 4000000:
ir_baud = USB_IRDA_BR_4000000; ir_baud = USB_IRDA_LS_4000000;
break; break;
default: default:
ir_baud = USB_IRDA_BR_9600; ir_baud = USB_IRDA_LS_9600;
baud = 9600; baud = 9600;
} }
...@@ -375,42 +438,22 @@ static void ir_set_termios(struct tty_struct *tty, ...@@ -375,42 +438,22 @@ static void ir_set_termios(struct tty_struct *tty,
/* /*
* send the baud change out on an "empty" data packet * send the baud change out on an "empty" data packet
*/ */
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb)
return;
transfer_buffer = kmalloc(1, GFP_KERNEL); transfer_buffer = kmalloc(1, GFP_KERNEL);
if (!transfer_buffer) if (!transfer_buffer)
goto err_buf; return;
*transfer_buffer = ir_xbof | ir_baud; *transfer_buffer = ir_xbof | ir_baud;
usb_fill_bulk_urb( ret = usb_bulk_msg(udev,
urb, usb_sndbulkpipe(udev, port->bulk_out_endpointAddress),
port->serial->dev, transfer_buffer, 1, &actual_length, 5000);
usb_sndbulkpipe(port->serial->dev, if (ret || actual_length != 1) {
port->bulk_out_endpointAddress), if (actual_length != 1)
transfer_buffer, ret = -EIO;
1, dev_err(&port->dev, "failed to change line speed: %d\n", ret);
ir_set_termios_callback,
port);
urb->transfer_flags = URB_ZERO_PACKET;
result = usb_submit_urb(urb, GFP_KERNEL);
if (result) {
dev_err(&port->dev, "%s - failed to submit urb: %d\n",
__func__, result);
goto err_subm;
} }
usb_free_urb(urb);
return;
err_subm:
kfree(transfer_buffer); kfree(transfer_buffer);
err_buf:
usb_free_urb(urb);
} }
static int __init ir_init(void) static int __init ir_init(void)
......
...@@ -41,6 +41,9 @@ struct opticon_private { ...@@ -41,6 +41,9 @@ struct opticon_private {
bool rts; bool rts;
bool cts; bool cts;
int outstanding_urbs; int outstanding_urbs;
int outstanding_bytes;
struct usb_anchor anchor;
}; };
...@@ -149,6 +152,15 @@ static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port) ...@@ -149,6 +152,15 @@ static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port)
return res; return res;
} }
static void opticon_close(struct usb_serial_port *port)
{
struct opticon_private *priv = usb_get_serial_port_data(port);
usb_kill_anchored_urbs(&priv->anchor);
usb_serial_generic_close(port);
}
static void opticon_write_control_callback(struct urb *urb) static void opticon_write_control_callback(struct urb *urb)
{ {
struct usb_serial_port *port = urb->context; struct usb_serial_port *port = urb->context;
...@@ -169,6 +181,7 @@ static void opticon_write_control_callback(struct urb *urb) ...@@ -169,6 +181,7 @@ static void opticon_write_control_callback(struct urb *urb)
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
--priv->outstanding_urbs; --priv->outstanding_urbs;
priv->outstanding_bytes -= urb->transfer_buffer_length;
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
usb_serial_port_softint(port); usb_serial_port_softint(port);
...@@ -182,8 +195,8 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, ...@@ -182,8 +195,8 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
struct urb *urb; struct urb *urb;
unsigned char *buffer; unsigned char *buffer;
unsigned long flags; unsigned long flags;
int status;
struct usb_ctrlrequest *dr; struct usb_ctrlrequest *dr;
int ret = -ENOMEM;
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
if (priv->outstanding_urbs > URB_UPPER_LIMIT) { if (priv->outstanding_urbs > URB_UPPER_LIMIT) {
...@@ -192,19 +205,16 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, ...@@ -192,19 +205,16 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
return 0; return 0;
} }
priv->outstanding_urbs++; priv->outstanding_urbs++;
priv->outstanding_bytes += count;
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
buffer = kmalloc(count, GFP_ATOMIC); buffer = kmalloc(count, GFP_ATOMIC);
if (!buffer) { if (!buffer)
count = -ENOMEM;
goto error_no_buffer; goto error_no_buffer;
}
urb = usb_alloc_urb(0, GFP_ATOMIC); urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb) { if (!urb)
count = -ENOMEM;
goto error_no_urb; goto error_no_urb;
}
memcpy(buffer, buf, count); memcpy(buffer, buf, count);
...@@ -213,10 +223,8 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, ...@@ -213,10 +223,8 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
/* The connected devices do not have a bulk write endpoint, /* The connected devices do not have a bulk write endpoint,
* to transmit data to de barcode device the control endpoint is used */ * to transmit data to de barcode device the control endpoint is used */
dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC); dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
if (!dr) { if (!dr)
count = -ENOMEM;
goto error_no_dr; goto error_no_dr;
}
dr->bRequestType = USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT; dr->bRequestType = USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT;
dr->bRequest = 0x01; dr->bRequest = 0x01;
...@@ -229,13 +237,13 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, ...@@ -229,13 +237,13 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
(unsigned char *)dr, buffer, count, (unsigned char *)dr, buffer, count,
opticon_write_control_callback, port); opticon_write_control_callback, port);
usb_anchor_urb(urb, &priv->anchor);
/* send it down the pipe */ /* send it down the pipe */
status = usb_submit_urb(urb, GFP_ATOMIC); ret = usb_submit_urb(urb, GFP_ATOMIC);
if (status) { if (ret) {
dev_err(&port->dev, dev_err(&port->dev, "failed to submit write urb: %d\n", ret);
"%s - usb_submit_urb(write endpoint) failed status = %d\n", usb_unanchor_urb(urb);
__func__, status);
count = status;
goto error; goto error;
} }
...@@ -253,8 +261,10 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, ...@@ -253,8 +261,10 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
error_no_buffer: error_no_buffer:
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
--priv->outstanding_urbs; --priv->outstanding_urbs;
priv->outstanding_bytes -= count;
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
return count;
return ret;
} }
static int opticon_write_room(struct tty_struct *tty) static int opticon_write_room(struct tty_struct *tty)
...@@ -279,6 +289,20 @@ static int opticon_write_room(struct tty_struct *tty) ...@@ -279,6 +289,20 @@ static int opticon_write_room(struct tty_struct *tty)
return 2048; return 2048;
} }
static int opticon_chars_in_buffer(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
struct opticon_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
int count;
spin_lock_irqsave(&priv->lock, flags);
count = priv->outstanding_bytes;
spin_unlock_irqrestore(&priv->lock, flags);
return count;
}
static int opticon_tiocmget(struct tty_struct *tty) static int opticon_tiocmget(struct tty_struct *tty)
{ {
struct usb_serial_port *port = tty->driver_data; struct usb_serial_port *port = tty->driver_data;
...@@ -354,6 +378,7 @@ static int opticon_port_probe(struct usb_serial_port *port) ...@@ -354,6 +378,7 @@ static int opticon_port_probe(struct usb_serial_port *port)
return -ENOMEM; return -ENOMEM;
spin_lock_init(&priv->lock); spin_lock_init(&priv->lock);
init_usb_anchor(&priv->anchor);
usb_set_serial_port_data(port, priv); usb_set_serial_port_data(port, priv);
...@@ -381,8 +406,10 @@ static struct usb_serial_driver opticon_device = { ...@@ -381,8 +406,10 @@ static struct usb_serial_driver opticon_device = {
.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,
.close = opticon_close,
.write = opticon_write, .write = opticon_write,
.write_room = opticon_write_room, .write_room = opticon_write_room,
.chars_in_buffer = opticon_chars_in_buffer,
.throttle = usb_serial_generic_throttle, .throttle = usb_serial_generic_throttle,
.unthrottle = usb_serial_generic_unthrottle, .unthrottle = usb_serial_generic_unthrottle,
.get_serial = get_serial_info, .get_serial = get_serial_info,
......
...@@ -119,11 +119,22 @@ struct usb_irda_cs_descriptor { ...@@ -119,11 +119,22 @@ struct usb_irda_cs_descriptor {
* 6 - 115200 bps * 6 - 115200 bps
* 7 - 576000 bps * 7 - 576000 bps
* 8 - 1.152 Mbps * 8 - 1.152 Mbps
* 9 - 5 mbps * 9 - 4 Mbps
* 10..15 - Reserved * 10..15 - Reserved
*/ */
#define USB_IRDA_STATUS_LINK_SPEED 0x0f #define USB_IRDA_STATUS_LINK_SPEED 0x0f
#define USB_IRDA_LS_NO_CHANGE 0
#define USB_IRDA_LS_2400 1
#define USB_IRDA_LS_9600 2
#define USB_IRDA_LS_19200 3
#define USB_IRDA_LS_38400 4
#define USB_IRDA_LS_57600 5
#define USB_IRDA_LS_115200 6
#define USB_IRDA_LS_576000 7
#define USB_IRDA_LS_1152000 8
#define USB_IRDA_LS_4000000 9
/* The following is a 4-bit value used only for /* The following is a 4-bit value used only for
* outbound header: * outbound header:
* *
......
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