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

Commit ea3c6ebd authored by Johan Hovold's avatar Johan Hovold
Browse files

USB: serial: visor: clean up treo endpoint hack



Use the new endpoint-remap functionality to configure the ports for
treo devices instead of poking around in the port structures after the
ports have been setup.

Signed-off-by: default avatarJohan Hovold <johan@kernel.org>
parent da2befa6
Loading
Loading
Loading
Loading
+24 −58
Original line number Diff line number Diff line
@@ -46,7 +46,6 @@ static int clie_5_calc_num_ports(struct usb_serial *serial,
					struct usb_serial_endpoints *epds);
static void visor_read_int_callback(struct urb *urb);
static int  clie_3_5_startup(struct usb_serial *serial);
static int  treo_attach(struct usb_serial *serial);
static int palm_os_3_probe(struct usb_serial *serial,
					const struct usb_device_id *id);
static int palm_os_4_probe(struct usb_serial *serial,
@@ -176,7 +175,6 @@ static struct usb_serial_driver handspring_device = {
	.close =		visor_close,
	.throttle =		usb_serial_generic_throttle,
	.unthrottle =		usb_serial_generic_unthrottle,
	.attach =		treo_attach,
	.probe =		visor_probe,
	.calc_num_ports =	visor_calc_num_ports,
	.read_int_callback =	visor_read_int_callback,
@@ -471,11 +469,35 @@ static int visor_probe(struct usb_serial *serial,
static int visor_calc_num_ports(struct usb_serial *serial,
					struct usb_serial_endpoints *epds)
{
	unsigned int vid = le16_to_cpu(serial->dev->descriptor.idVendor);
	int num_ports = (int)(long)(usb_get_serial_data(serial));

	if (num_ports)
		usb_set_serial_data(serial, NULL);

	/*
	 * Only swap the bulk endpoints for the Handspring devices with
	 * interrupt in endpoints, which for now are the Treo devices.
	 */
	if (!(vid == HANDSPRING_VENDOR_ID || vid == KYOCERA_VENDOR_ID) ||
			epds->num_interrupt_in == 0)
		goto out;

	if (epds->num_bulk_in < 2 || epds->num_interrupt_in < 2) {
		dev_err(&serial->interface->dev, "missing endpoints\n");
		return -ENODEV;
	}

	/*
	 * It appears that Treos and Kyoceras want to use the
	 * 1st bulk in endpoint to communicate with the 2nd bulk out endpoint,
	 * so let's swap the 1st and 2nd bulk in and interrupt endpoints.
	 * Note that swapping the bulk out endpoints would break lots of
	 * apps that want to communicate on the second port.
	 */
	swap(epds->bulk_in[0], epds->bulk_in[1]);
	swap(epds->interrupt_in[0], epds->interrupt_in[1]);
out:
	return num_ports;
}

@@ -553,62 +575,6 @@ static int clie_3_5_startup(struct usb_serial *serial)
	return result;
}

static int treo_attach(struct usb_serial *serial)
{
	struct usb_serial_port *swap_port;

	/* Only do this endpoint hack for the Handspring devices with
	 * interrupt in endpoints, which for now are the Treo devices. */
	if (!((le16_to_cpu(serial->dev->descriptor.idVendor)
						== HANDSPRING_VENDOR_ID) ||
		(le16_to_cpu(serial->dev->descriptor.idVendor)
						== KYOCERA_VENDOR_ID)) ||
		(serial->num_interrupt_in == 0))
		return 0;

	if (serial->num_bulk_in < 2 || serial->num_interrupt_in < 2) {
		dev_err(&serial->interface->dev, "missing endpoints\n");
		return -ENODEV;
	}

	/*
	* It appears that Treos and Kyoceras want to use the
	* 1st bulk in endpoint to communicate with the 2nd bulk out endpoint,
	* so let's swap the 1st and 2nd bulk in and interrupt endpoints.
	* Note that swapping the bulk out endpoints would break lots of
	* apps that want to communicate on the second port.
	*/
#define COPY_PORT(dest, src)						\
	do { \
		int i;							\
									\
		for (i = 0; i < ARRAY_SIZE(src->read_urbs); ++i) {	\
			dest->read_urbs[i] = src->read_urbs[i];		\
			dest->read_urbs[i]->context = dest;		\
			dest->bulk_in_buffers[i] = src->bulk_in_buffers[i]; \
		}							\
		dest->read_urb = src->read_urb;				\
		dest->bulk_in_endpointAddress = src->bulk_in_endpointAddress;\
		dest->bulk_in_buffer = src->bulk_in_buffer;		\
		dest->bulk_in_size = src->bulk_in_size;			\
		dest->interrupt_in_urb = src->interrupt_in_urb;		\
		dest->interrupt_in_urb->context = dest;			\
		dest->interrupt_in_endpointAddress = \
					src->interrupt_in_endpointAddress;\
		dest->interrupt_in_buffer = src->interrupt_in_buffer;	\
	} while (0);

	swap_port = kmalloc(sizeof(*swap_port), GFP_KERNEL);
	if (!swap_port)
		return -ENOMEM;
	COPY_PORT(swap_port, serial->port[0]);
	COPY_PORT(serial->port[0], serial->port[1]);
	COPY_PORT(serial->port[1], swap_port);
	kfree(swap_port);

	return 0;
}

module_usb_serial_driver(serial_drivers, id_table_combined);

MODULE_AUTHOR(DRIVER_AUTHOR);