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

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
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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;
		}
+1 −1
Original line number Diff line number Diff line
@@ -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 */
+114 −71
Original line number Diff line number Diff line
@@ -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;

	if (port->bulk_out_size == 0)
		return -EINVAL;

	if (count == 0)
		return 0;

	for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
		port->write_urbs[i]->transfer_flags = URB_ZERO_PACKET;
	count = min(count, port->bulk_out_size - 1);

	/* Start reading from the device */
	return usb_serial_generic_open(tty, port);
	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);

static int ir_prepare_write_buffer(struct usb_serial_port *port,
						void *dest, size_t size)
{
	unsigned char *buf = dest;
	int count;
	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)
+44 −17
Original line number Diff line number Diff line
@@ -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,
+12 −1
Original line number Diff line number Diff line
@@ -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:
 *