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: Johan Hovold <johan@kernel.org>
This commit is contained in:
Johan Hovold 2017-03-16 17:13:53 +01:00
Родитель da2befa6d5
Коммит ea3c6ebdcb
1 изменённых файлов: 24 добавлений и 58 удалений

Просмотреть файл

@ -46,7 +46,6 @@ static int clie_5_calc_num_ports(struct usb_serial *serial,
struct usb_serial_endpoints *epds); struct usb_serial_endpoints *epds);
static void visor_read_int_callback(struct urb *urb); static void visor_read_int_callback(struct urb *urb);
static int clie_3_5_startup(struct usb_serial *serial); 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, static int palm_os_3_probe(struct usb_serial *serial,
const struct usb_device_id *id); const struct usb_device_id *id);
static int palm_os_4_probe(struct usb_serial *serial, static int palm_os_4_probe(struct usb_serial *serial,
@ -176,7 +175,6 @@ static struct usb_serial_driver handspring_device = {
.close = visor_close, .close = visor_close,
.throttle = usb_serial_generic_throttle, .throttle = usb_serial_generic_throttle,
.unthrottle = usb_serial_generic_unthrottle, .unthrottle = usb_serial_generic_unthrottle,
.attach = treo_attach,
.probe = visor_probe, .probe = visor_probe,
.calc_num_ports = visor_calc_num_ports, .calc_num_ports = visor_calc_num_ports,
.read_int_callback = visor_read_int_callback, .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, static int visor_calc_num_ports(struct usb_serial *serial,
struct usb_serial_endpoints *epds) 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)); int num_ports = (int)(long)(usb_get_serial_data(serial));
if (num_ports) if (num_ports)
usb_set_serial_data(serial, NULL); 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; return num_ports;
} }
@ -553,62 +575,6 @@ out:
return result; 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_usb_serial_driver(serial_drivers, id_table_combined);
MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_AUTHOR(DRIVER_AUTHOR);