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: Johan Hovold <johan@kernel.org> -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQQHbPq+cpGvN/peuzMLxc3C7H1lCAUCXi6evgAKCRALxc3C7H1l CJs8AP4ubaKYyH5cLMthwhLAdGqp2UdfVqdUu25Kb2bnyXbStAEAsvhOHWbdrQKn cRLLJqYO4M3nPH2YF1Is4qSJZmUxXQk= =Aof1 -----END PGP SIGNATURE----- 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: Johan 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
This commit is contained in:
Коммит
eaa519983f
|
@ -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;
|
||||
|
||||
count = kfifo_out_locked(&port->write_fifo, buf + 1, size - 1,
|
||||
&port->lock);
|
||||
return count + 1;
|
||||
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);
|
||||
}
|
||||
|
||||
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 @@ error_no_urb:
|
|||
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:
|
||||
*
|
||||
|
|
Загрузка…
Ссылка в новой задаче