- /* Ok, this is pretty ugly, but these devices want to use the
- * interrupt endpoint as paired up with a bulk endpoint for a
- * "virtual serial port". So let's force the endpoints to be
- * where we want them to be. */
- for (i = serial->num_bulk_in; i < serial->num_ports; ++i) {
- port = serial->port[i];
- port->read_urb = serial->port[0]->read_urb;
- port->bulk_in_endpointAddress = serial->port[0]->bulk_in_endpointAddress;
- port->bulk_in_buffer = serial->port[0]->bulk_in_buffer;
- }
-
- for (i = serial->num_bulk_out; i < serial->num_ports; ++i) {
- port = serial->port[i];
- port->write_urb = serial->port[0]->write_urb;
- port->bulk_out_size = serial->port[0]->bulk_out_size;
- port->bulk_out_endpointAddress = serial->port[0]->bulk_out_endpointAddress;
- port->bulk_out_buffer = serial->port[0]->bulk_out_buffer;
- }
-
- for (i = serial->num_interrupt_in; i < serial->num_ports; ++i) {
- port = serial->port[i];
- port->interrupt_in_urb = serial->port[0]->interrupt_in_urb;
- port->interrupt_in_endpointAddress = serial->port[0]->interrupt_in_endpointAddress;
- port->interrupt_in_buffer = serial->port[0]->interrupt_in_buffer;
- }
+ /*
+ * 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) \
+ dest->read_urb = src->read_urb; \
+ dest->bulk_in_endpointAddress = src->bulk_in_endpointAddress; \
+ dest->bulk_in_buffer = src->bulk_in_buffer; \
+ dest->interrupt_in_urb = src->interrupt_in_urb; \
+ dest->interrupt_in_endpointAddress = src->interrupt_in_endpointAddress; \
+ dest->interrupt_in_buffer = src->interrupt_in_buffer;
+
+ 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);