Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+8 −28
Original line number Diff line number Diff line
@@ -29,12 +29,6 @@
 * is any other control code, I will simply check for the first
 * 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:
 * http://www.linuxjournal.com/article/6573
 * 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,
	return count + HCI_HEADER_LENGTH;
}

static int aircable_probe(struct usb_serial *serial,
			  const struct usb_device_id *id)
static int aircable_calc_num_ports(struct usb_serial *serial,
					struct usb_serial_endpoints *epds)
{
	struct usb_host_interface *iface_desc = serial->interface->
								cur_altsetting;
	struct usb_endpoint_descriptor *endpoint;
	int num_bulk_out = 0;
	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");
	/* Ignore the first interface, which has no bulk endpoints. */
	if (epds->num_bulk_out == 0) {
		dev_dbg(&serial->interface->dev,
			"ignoring interface with no bulk-out endpoints\n");
		return -ENODEV;
	}

	return 0;
	return 1;
}

static int aircable_process_packet(struct usb_serial_port *port,
@@ -164,9 +145,8 @@ static struct usb_serial_driver aircable_device = {
		.name =		"aircable",
	},
	.id_table = 		id_table,
	.num_ports =		1,
	.bulk_out_size =	HCI_COMPLETE_FRAME,
	.probe =		aircable_probe,
	.calc_num_ports =	aircable_calc_num_ports,
	.process_read_urb =	aircable_process_read_urb,
	.prepare_write_buffer =	aircable_prepare_write_buffer,
	.throttle =		usb_serial_generic_throttle,
+3 −14
Original line number Diff line number Diff line
@@ -122,19 +122,6 @@ static inline int calc_divisor(int 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)
{
	struct usb_serial *serial = port->serial;
@@ -671,7 +658,9 @@ static struct usb_serial_driver ark3116_device = {
	},
	.id_table =		id_table,
	.num_ports =		1,
	.attach =		ark3116_attach,
	.num_bulk_in =		1,
	.num_bulk_out =		1,
	.num_interrupt_in =	1,
	.port_probe =		ark3116_port_probe,
	.port_remove =		ark3116_port_remove,
	.set_termios =		ark3116_set_termios,
+1 −10
Original line number Diff line number Diff line
@@ -50,7 +50,6 @@
#define CYBERJACK_PRODUCT_ID	0x0100

/* Function prototypes */
static int cyberjack_attach(struct usb_serial *serial);
static int cyberjack_port_probe(struct usb_serial_port *port);
static int cyberjack_port_remove(struct usb_serial_port *port);
static int  cyberjack_open(struct tty_struct *tty,
@@ -78,7 +77,7 @@ static struct usb_serial_driver cyberjack_device = {
	.description =		"Reiner SCT Cyberjack USB card reader",
	.id_table =		id_table,
	.num_ports =		1,
	.attach =		cyberjack_attach,
	.num_bulk_out =		1,
	.port_probe =		cyberjack_port_probe,
	.port_remove =		cyberjack_port_remove,
	.open =			cyberjack_open,
@@ -102,14 +101,6 @@ struct cyberjack_private {
	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)
{
	struct cyberjack_private *priv;
+4 −19
Original line number Diff line number Diff line
@@ -273,6 +273,8 @@ static struct usb_serial_driver digi_acceleport_2_device = {
	.description =			"Digi 2 port USB adapter",
	.id_table =			id_table_2,
	.num_ports =			3,
	.num_bulk_in =			4,
	.num_bulk_out =			4,
	.open =				digi_open,
	.close =			digi_close,
	.dtr_rts =			digi_dtr_rts,
@@ -302,6 +304,8 @@ static struct usb_serial_driver digi_acceleport_4_device = {
	.description =			"Digi 4 port USB adapter",
	.id_table =			id_table_4,
	.num_ports =			4,
	.num_bulk_in =			5,
	.num_bulk_out =			5,
	.open =				digi_open,
	.close =			digi_close,
	.write =			digi_write,
@@ -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)
{
	struct device *dev = &serial->interface->dev;
	struct digi_serial *serial_priv;
	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);
	if (!serial_priv)
+33 −104
Original line number Diff line number Diff line
@@ -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
 * 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_idx;
	u8 num_port = 0;
	int status;
	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 */
	status = f81534_find_config_idx(serial, &setting_idx);
	if (status) {
		dev_err(&serial->interface->dev, "%s: find idx failed: %d\n",
				__func__, status);
		return 0;
		return status;
	}

	/*
@@ -640,7 +650,7 @@ static int f81534_calc_num_ports(struct usb_serial *serial)
			dev_err(&serial->interface->dev,
					"%s: get custom data failed: %d\n",
					__func__, status);
			return 0;
			return status;
		}

		dev_dbg(&serial->interface->dev,
@@ -656,7 +666,7 @@ static int f81534_calc_num_ports(struct usb_serial *serial)
			dev_err(&serial->interface->dev,
					"%s: read failed: %d\n", __func__,
					status);
			return 0;
			return status;
		}

		dev_dbg(&serial->interface->dev, "%s: read default config\n",
@@ -671,12 +681,24 @@ static int f81534_calc_num_ports(struct usb_serial *serial)
		++num_port;
	}

	if (num_port)
		return num_port;
	if (!num_port) {
		dev_warn(&serial->interface->dev,
			"no config found, assuming 4 ports\n");
		num_port = 4;		/* Nothing found, oldest version IC */
	}

	dev_warn(&serial->interface->dev, "%s: Read Failed. default 4 ports\n",
			__func__);
	return 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];

	epds->num_bulk_out = num_port;

	return num_port;
}

static void f81534_set_termios(struct tty_struct *tty,
@@ -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)
{
	struct f81534_serial_private *serial_priv;
@@ -1173,10 +1105,6 @@ static int f81534_attach(struct usb_serial *serial)

	mutex_init(&serial_priv->urb_mutex);

	status = f81534_setup_ports(serial);
	if (status)
		return status;

	/* Check had custom setting */
	status = f81534_find_config_idx(serial, &serial_priv->setting_idx);
	if (status) {
@@ -1380,12 +1308,13 @@ static struct usb_serial_driver f81534_device = {
	},
	.description =		DRIVER_DESC,
	.id_table =		f81534_id_table,
	.num_bulk_in =		1,
	.num_bulk_out =		1,
	.open =			f81534_open,
	.close =		f81534_close,
	.write =		f81534_write,
	.tx_empty =		f81534_tx_empty,
	.calc_num_ports =	f81534_calc_num_ports,
	.probe =		f81534_probe,
	.attach =		f81534_attach,
	.port_probe =		f81534_port_probe,
	.dtr_rts =		f81534_dtr_rts,
Loading