Skip to content

Commit

Permalink
USB: serial: visor: clean up treo endpoint hack
Browse files Browse the repository at this point in the history
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: Johan Hovold <johan@kernel.org>
  • Loading branch information
Johan Hovold committed Mar 28, 2017
1 parent da2befa commit ea3c6eb
Showing 1 changed file with 24 additions and 58 deletions.
82 changes: 24 additions & 58 deletions drivers/usb/serial/visor.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit ea3c6eb

Please sign in to comment.