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)
old_rdtodo = priv->rdtodo;
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);
goto resubmit;
}
......
......@@ -104,7 +104,7 @@ struct garmin_packet {
int seq;
/* the real size of the data array, always > 0 */
int size;
__u8 data[1];
__u8 data[];
};
/* structure used to keep the current state of the driver */
......
......@@ -45,9 +45,10 @@ static int buffer_size;
static int xbof = -1;
static int ir_startup (struct usb_serial *serial);
static int ir_open(struct tty_struct *tty, struct usb_serial_port *port);
static int ir_prepare_write_buffer(struct usb_serial_port *port,
void *dest, size_t size);
static int ir_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count);
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_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios);
......@@ -75,10 +76,13 @@ static struct usb_serial_driver ir_device = {
.description = "IR Dongle",
.id_table = ir_id_table,
.num_ports = 1,
.num_bulk_in = 1,
.num_bulk_out = 1,
.set_termios = ir_set_termios,
.attach = ir_startup,
.open = ir_open,
.prepare_write_buffer = ir_prepare_write_buffer,
.write = ir_write,
.write_room = ir_write_room,
.write_bulk_callback = ir_write_bulk_callback,
.process_read_urb = ir_process_read_urb,
};
......@@ -251,35 +255,102 @@ static int ir_startup(struct usb_serial *serial)
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)
port->write_urbs[i]->transfer_flags = URB_ZERO_PACKET;
if (port->bulk_out_size == 0)
return -EINVAL;
/* Start reading from the device */
return usb_serial_generic_open(tty, port);
}
if (count == 0)
return 0;
static int ir_prepare_write_buffer(struct usb_serial_port *port,
void *dest, size_t size)
{
unsigned char *buf = dest;
int count;
count = min(count, port->bulk_out_size - 1);
spin_lock_irqsave(&port->lock, flags);
if (__test_and_clear_bit(0, &port->write_urbs_free)) {
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
* inbound header which indicates an additional number of BOFs and
* outbound header which indicates an additional number of BOFs and
* a baud rate change.
*
* 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);
count = kfifo_out_locked(&port->write_fifo, buf + 1, size - 1,
&port->lock);
return count + 1;
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);
}
static int ir_write_room(struct tty_struct *tty)
{
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)
......@@ -304,23 +375,15 @@ static void ir_process_read_urb(struct urb *urb)
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,
struct usb_serial_port *port, struct ktermios *old_termios)
{
struct urb *urb;
struct usb_device *udev = port->serial->dev;
unsigned char *transfer_buffer;
int result;
int actual_length;
speed_t baud;
int ir_baud;
int ret;
baud = tty_get_baud_rate(tty);
......@@ -332,34 +395,34 @@ static void ir_set_termios(struct tty_struct *tty,
switch (baud) {
case 2400:
ir_baud = USB_IRDA_BR_2400;
ir_baud = USB_IRDA_LS_2400;
break;
case 9600:
ir_baud = USB_IRDA_BR_9600;
ir_baud = USB_IRDA_LS_9600;
break;
case 19200:
ir_baud = USB_IRDA_BR_19200;
ir_baud = USB_IRDA_LS_19200;
break;
case 38400:
ir_baud = USB_IRDA_BR_38400;
ir_baud = USB_IRDA_LS_38400;
break;
case 57600:
ir_baud = USB_IRDA_BR_57600;
ir_baud = USB_IRDA_LS_57600;
break;
case 115200:
ir_baud = USB_IRDA_BR_115200;
ir_baud = USB_IRDA_LS_115200;
break;
case 576000:
ir_baud = USB_IRDA_BR_576000;
ir_baud = USB_IRDA_LS_576000;
break;
case 1152000:
ir_baud = USB_IRDA_BR_1152000;
ir_baud = USB_IRDA_LS_1152000;
break;
case 4000000:
ir_baud = USB_IRDA_BR_4000000;
ir_baud = USB_IRDA_LS_4000000;
break;
default:
ir_baud = USB_IRDA_BR_9600;
ir_baud = USB_IRDA_LS_9600;
baud = 9600;
}
......@@ -375,42 +438,22 @@ static void ir_set_termios(struct tty_struct *tty,
/*
* 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);
if (!transfer_buffer)
goto err_buf;
return;
*transfer_buffer = ir_xbof | ir_baud;
usb_fill_bulk_urb(
urb,
port->serial->dev,
usb_sndbulkpipe(port->serial->dev,
port->bulk_out_endpointAddress),
transfer_buffer,
1,
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;
ret = usb_bulk_msg(udev,
usb_sndbulkpipe(udev, port->bulk_out_endpointAddress),
transfer_buffer, 1, &actual_length, 5000);
if (ret || actual_length != 1) {
if (actual_length != 1)
ret = -EIO;
dev_err(&port->dev, "failed to change line speed: %d\n", ret);
}
usb_free_urb(urb);
return;
err_subm:
kfree(transfer_buffer);
err_buf:
usb_free_urb(urb);
}
static int __init ir_init(void)
......
......@@ -41,6 +41,9 @@ struct opticon_private {
bool rts;
bool cts;
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)
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)
{
struct usb_serial_port *port = urb->context;
......@@ -169,6 +181,7 @@ static void opticon_write_control_callback(struct urb *urb)
spin_lock_irqsave(&priv->lock, flags);
--priv->outstanding_urbs;
priv->outstanding_bytes -= urb->transfer_buffer_length;
spin_unlock_irqrestore(&priv->lock, flags);
usb_serial_port_softint(port);
......@@ -182,8 +195,8 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
struct urb *urb;
unsigned char *buffer;
unsigned long flags;
int status;
struct usb_ctrlrequest *dr;
int ret = -ENOMEM;
spin_lock_irqsave(&priv->lock, flags);
if (priv->outstanding_urbs > URB_UPPER_LIMIT) {
......@@ -192,19 +205,16 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
return 0;
}
priv->outstanding_urbs++;
priv->outstanding_bytes += count;
spin_unlock_irqrestore(&priv->lock, flags);
buffer = kmalloc(count, GFP_ATOMIC);
if (!buffer) {
count = -ENOMEM;
if (!buffer)
goto error_no_buffer;
}
urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb) {
count = -ENOMEM;
if (!urb)
goto error_no_urb;
}
memcpy(buffer, buf, count);
......@@ -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,
* to transmit data to de barcode device the control endpoint is used */
dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
if (!dr) {
count = -ENOMEM;
if (!dr)
goto error_no_dr;
}
dr->bRequestType = USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT;
dr->bRequest = 0x01;
......@@ -229,13 +237,13 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
(unsigned char *)dr, buffer, count,
opticon_write_control_callback, port);
usb_anchor_urb(urb, &priv->anchor);
/* send it down the pipe */
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
dev_err(&port->dev,
"%s - usb_submit_urb(write endpoint) failed status = %d\n",
__func__, status);
count = status;
ret = usb_submit_urb(urb, GFP_ATOMIC);
if (ret) {
dev_err(&port->dev, "failed to submit write urb: %d\n", ret);
usb_unanchor_urb(urb);
goto error;
}
......@@ -253,8 +261,10 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
error_no_buffer:
spin_lock_irqsave(&priv->lock, flags);
--priv->outstanding_urbs;
priv->outstanding_bytes -= count;
spin_unlock_irqrestore(&priv->lock, flags);
return count;
return ret;
}
static int opticon_write_room(struct tty_struct *tty)
......@@ -279,6 +289,20 @@ static int opticon_write_room(struct tty_struct *tty)
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)
{
struct usb_serial_port *port = tty->driver_data;
......@@ -354,6 +378,7 @@ static int opticon_port_probe(struct usb_serial_port *port)
return -ENOMEM;
spin_lock_init(&priv->lock);
init_usb_anchor(&priv->anchor);
usb_set_serial_port_data(port, priv);
......@@ -381,8 +406,10 @@ static struct usb_serial_driver opticon_device = {
.port_probe = opticon_port_probe,
.port_remove = opticon_port_remove,
.open = opticon_open,
.close = opticon_close,
.write = opticon_write,
.write_room = opticon_write_room,
.chars_in_buffer = opticon_chars_in_buffer,
.throttle = usb_serial_generic_throttle,
.unthrottle = usb_serial_generic_unthrottle,
.get_serial = get_serial_info,
......
......@@ -119,11 +119,22 @@ struct usb_irda_cs_descriptor {
* 6 - 115200 bps
* 7 - 576000 bps
* 8 - 1.152 Mbps
* 9 - 5 mbps
* 9 - 4 Mbps
* 10..15 - Reserved
*/
#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
* 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