|
@@ -742,6 +742,124 @@ static void find_endpoints(struct usb_serial *serial,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static int setup_port_bulk_in(struct usb_serial_port *port,
|
|
|
+ struct usb_endpoint_descriptor *epd)
|
|
|
+{
|
|
|
+ struct usb_serial_driver *type = port->serial->type;
|
|
|
+ struct usb_device *udev = port->serial->dev;
|
|
|
+ int buffer_size;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ buffer_size = max_t(int, type->bulk_in_size, usb_endpoint_maxp(epd));
|
|
|
+ port->bulk_in_size = buffer_size;
|
|
|
+ port->bulk_in_endpointAddress = epd->bEndpointAddress;
|
|
|
+
|
|
|
+ for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) {
|
|
|
+ set_bit(i, &port->read_urbs_free);
|
|
|
+ port->read_urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
|
|
|
+ if (!port->read_urbs[i])
|
|
|
+ return -ENOMEM;
|
|
|
+ port->bulk_in_buffers[i] = kmalloc(buffer_size, GFP_KERNEL);
|
|
|
+ if (!port->bulk_in_buffers[i])
|
|
|
+ return -ENOMEM;
|
|
|
+ usb_fill_bulk_urb(port->read_urbs[i], udev,
|
|
|
+ usb_rcvbulkpipe(udev, epd->bEndpointAddress),
|
|
|
+ port->bulk_in_buffers[i], buffer_size,
|
|
|
+ type->read_bulk_callback, port);
|
|
|
+ }
|
|
|
+
|
|
|
+ port->read_urb = port->read_urbs[0];
|
|
|
+ port->bulk_in_buffer = port->bulk_in_buffers[0];
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int setup_port_bulk_out(struct usb_serial_port *port,
|
|
|
+ struct usb_endpoint_descriptor *epd)
|
|
|
+{
|
|
|
+ struct usb_serial_driver *type = port->serial->type;
|
|
|
+ struct usb_device *udev = port->serial->dev;
|
|
|
+ int buffer_size;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ if (kfifo_alloc(&port->write_fifo, PAGE_SIZE, GFP_KERNEL))
|
|
|
+ return -ENOMEM;
|
|
|
+ if (type->bulk_out_size)
|
|
|
+ buffer_size = type->bulk_out_size;
|
|
|
+ else
|
|
|
+ buffer_size = usb_endpoint_maxp(epd);
|
|
|
+ port->bulk_out_size = buffer_size;
|
|
|
+ port->bulk_out_endpointAddress = epd->bEndpointAddress;
|
|
|
+
|
|
|
+ for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) {
|
|
|
+ set_bit(i, &port->write_urbs_free);
|
|
|
+ port->write_urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
|
|
|
+ if (!port->write_urbs[i])
|
|
|
+ return -ENOMEM;
|
|
|
+ port->bulk_out_buffers[i] = kmalloc(buffer_size, GFP_KERNEL);
|
|
|
+ if (!port->bulk_out_buffers[i])
|
|
|
+ return -ENOMEM;
|
|
|
+ usb_fill_bulk_urb(port->write_urbs[i], udev,
|
|
|
+ usb_sndbulkpipe(udev, epd->bEndpointAddress),
|
|
|
+ port->bulk_out_buffers[i], buffer_size,
|
|
|
+ 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 setup_port_interrupt_in(struct usb_serial_port *port,
|
|
|
+ struct usb_endpoint_descriptor *epd)
|
|
|
+{
|
|
|
+ struct usb_serial_driver *type = port->serial->type;
|
|
|
+ struct usb_device *udev = port->serial->dev;
|
|
|
+ int buffer_size;
|
|
|
+
|
|
|
+ port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
|
|
|
+ if (!port->interrupt_in_urb)
|
|
|
+ return -ENOMEM;
|
|
|
+ buffer_size = usb_endpoint_maxp(epd);
|
|
|
+ port->interrupt_in_endpointAddress = epd->bEndpointAddress;
|
|
|
+ port->interrupt_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
|
|
|
+ if (!port->interrupt_in_buffer)
|
|
|
+ return -ENOMEM;
|
|
|
+ usb_fill_int_urb(port->interrupt_in_urb, udev,
|
|
|
+ usb_rcvintpipe(udev, epd->bEndpointAddress),
|
|
|
+ port->interrupt_in_buffer, buffer_size,
|
|
|
+ type->read_int_callback, port,
|
|
|
+ epd->bInterval);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int setup_port_interrupt_out(struct usb_serial_port *port,
|
|
|
+ struct usb_endpoint_descriptor *epd)
|
|
|
+{
|
|
|
+ struct usb_serial_driver *type = port->serial->type;
|
|
|
+ struct usb_device *udev = port->serial->dev;
|
|
|
+ int buffer_size;
|
|
|
+
|
|
|
+ port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
|
|
|
+ if (!port->interrupt_out_urb)
|
|
|
+ return -ENOMEM;
|
|
|
+ buffer_size = usb_endpoint_maxp(epd);
|
|
|
+ port->interrupt_out_size = buffer_size;
|
|
|
+ port->interrupt_out_endpointAddress = epd->bEndpointAddress;
|
|
|
+ port->interrupt_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
|
|
|
+ if (!port->interrupt_out_buffer)
|
|
|
+ return -ENOMEM;
|
|
|
+ usb_fill_int_urb(port->interrupt_out_urb, udev,
|
|
|
+ usb_sndintpipe(udev, epd->bEndpointAddress),
|
|
|
+ port->interrupt_out_buffer, buffer_size,
|
|
|
+ type->write_int_callback, port,
|
|
|
+ epd->bInterval);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static int usb_serial_probe(struct usb_interface *interface,
|
|
|
const struct usb_device_id *id)
|
|
|
{
|
|
@@ -749,13 +867,10 @@ static int usb_serial_probe(struct usb_interface *interface,
|
|
|
struct usb_device *dev = interface_to_usbdev(interface);
|
|
|
struct usb_serial *serial = NULL;
|
|
|
struct usb_serial_port *port;
|
|
|
- struct usb_endpoint_descriptor *endpoint;
|
|
|
struct usb_serial_endpoints *epds;
|
|
|
struct usb_serial_driver *type = NULL;
|
|
|
int retval;
|
|
|
- int buffer_size;
|
|
|
int i;
|
|
|
- int j;
|
|
|
int num_ports = 0;
|
|
|
unsigned char max_endpoints;
|
|
|
|
|
@@ -867,86 +982,24 @@ static int usb_serial_probe(struct usb_interface *interface,
|
|
|
|
|
|
/* set up the endpoint information */
|
|
|
for (i = 0; i < epds->num_bulk_in; ++i) {
|
|
|
- endpoint = epds->bulk_in[i];
|
|
|
- port = serial->port[i];
|
|
|
- buffer_size = max_t(int, serial->type->bulk_in_size,
|
|
|
- usb_endpoint_maxp(endpoint));
|
|
|
- port->bulk_in_size = buffer_size;
|
|
|
- port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
|
|
|
-
|
|
|
- for (j = 0; j < ARRAY_SIZE(port->read_urbs); ++j) {
|
|
|
- set_bit(j, &port->read_urbs_free);
|
|
|
- port->read_urbs[j] = usb_alloc_urb(0, GFP_KERNEL);
|
|
|
- if (!port->read_urbs[j])
|
|
|
- goto probe_error;
|
|
|
- port->bulk_in_buffers[j] = kmalloc(buffer_size,
|
|
|
- GFP_KERNEL);
|
|
|
- if (!port->bulk_in_buffers[j])
|
|
|
- goto probe_error;
|
|
|
- usb_fill_bulk_urb(port->read_urbs[j], dev,
|
|
|
- usb_rcvbulkpipe(dev,
|
|
|
- endpoint->bEndpointAddress),
|
|
|
- port->bulk_in_buffers[j], buffer_size,
|
|
|
- serial->type->read_bulk_callback,
|
|
|
- port);
|
|
|
- }
|
|
|
-
|
|
|
- port->read_urb = port->read_urbs[0];
|
|
|
- port->bulk_in_buffer = port->bulk_in_buffers[0];
|
|
|
+ retval = setup_port_bulk_in(serial->port[i], epds->bulk_in[i]);
|
|
|
+ if (retval)
|
|
|
+ goto probe_error;
|
|
|
}
|
|
|
|
|
|
for (i = 0; i < epds->num_bulk_out; ++i) {
|
|
|
- endpoint = epds->bulk_out[i];
|
|
|
- port = serial->port[i];
|
|
|
- if (kfifo_alloc(&port->write_fifo, PAGE_SIZE, GFP_KERNEL))
|
|
|
+ retval = setup_port_bulk_out(serial->port[i],
|
|
|
+ epds->bulk_out[i]);
|
|
|
+ if (retval)
|
|
|
goto probe_error;
|
|
|
- buffer_size = serial->type->bulk_out_size;
|
|
|
- if (!buffer_size)
|
|
|
- buffer_size = usb_endpoint_maxp(endpoint);
|
|
|
- port->bulk_out_size = buffer_size;
|
|
|
- port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
|
|
|
-
|
|
|
- for (j = 0; j < ARRAY_SIZE(port->write_urbs); ++j) {
|
|
|
- set_bit(j, &port->write_urbs_free);
|
|
|
- port->write_urbs[j] = usb_alloc_urb(0, GFP_KERNEL);
|
|
|
- if (!port->write_urbs[j])
|
|
|
- goto probe_error;
|
|
|
- port->bulk_out_buffers[j] = kmalloc(buffer_size,
|
|
|
- GFP_KERNEL);
|
|
|
- if (!port->bulk_out_buffers[j])
|
|
|
- goto probe_error;
|
|
|
- usb_fill_bulk_urb(port->write_urbs[j], dev,
|
|
|
- usb_sndbulkpipe(dev,
|
|
|
- endpoint->bEndpointAddress),
|
|
|
- port->bulk_out_buffers[j], buffer_size,
|
|
|
- serial->type->write_bulk_callback,
|
|
|
- port);
|
|
|
- }
|
|
|
-
|
|
|
- port->write_urb = port->write_urbs[0];
|
|
|
- port->bulk_out_buffer = port->bulk_out_buffers[0];
|
|
|
}
|
|
|
|
|
|
if (serial->type->read_int_callback) {
|
|
|
for (i = 0; i < epds->num_interrupt_in; ++i) {
|
|
|
- endpoint = epds->interrupt_in[i];
|
|
|
- port = serial->port[i];
|
|
|
- port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
|
|
|
- if (!port->interrupt_in_urb)
|
|
|
- goto probe_error;
|
|
|
- buffer_size = usb_endpoint_maxp(endpoint);
|
|
|
- port->interrupt_in_endpointAddress =
|
|
|
- endpoint->bEndpointAddress;
|
|
|
- port->interrupt_in_buffer = kmalloc(buffer_size,
|
|
|
- GFP_KERNEL);
|
|
|
- if (!port->interrupt_in_buffer)
|
|
|
+ retval = setup_port_interrupt_in(serial->port[i],
|
|
|
+ epds->interrupt_in[i]);
|
|
|
+ if (retval)
|
|
|
goto probe_error;
|
|
|
- usb_fill_int_urb(port->interrupt_in_urb, dev,
|
|
|
- usb_rcvintpipe(dev,
|
|
|
- endpoint->bEndpointAddress),
|
|
|
- port->interrupt_in_buffer, buffer_size,
|
|
|
- serial->type->read_int_callback, port,
|
|
|
- endpoint->bInterval);
|
|
|
}
|
|
|
} else if (epds->num_interrupt_in) {
|
|
|
dev_dbg(ddev, "The device claims to support interrupt in transfers, but read_int_callback is not defined\n");
|
|
@@ -954,25 +1007,10 @@ static int usb_serial_probe(struct usb_interface *interface,
|
|
|
|
|
|
if (serial->type->write_int_callback) {
|
|
|
for (i = 0; i < epds->num_interrupt_out; ++i) {
|
|
|
- endpoint = epds->interrupt_out[i];
|
|
|
- port = serial->port[i];
|
|
|
- port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
|
|
|
- if (!port->interrupt_out_urb)
|
|
|
- goto probe_error;
|
|
|
- buffer_size = usb_endpoint_maxp(endpoint);
|
|
|
- port->interrupt_out_size = buffer_size;
|
|
|
- port->interrupt_out_endpointAddress =
|
|
|
- endpoint->bEndpointAddress;
|
|
|
- port->interrupt_out_buffer = kmalloc(buffer_size,
|
|
|
- GFP_KERNEL);
|
|
|
- if (!port->interrupt_out_buffer)
|
|
|
+ retval = setup_port_interrupt_out(serial->port[i],
|
|
|
+ epds->interrupt_out[i]);
|
|
|
+ if (retval)
|
|
|
goto probe_error;
|
|
|
- usb_fill_int_urb(port->interrupt_out_urb, dev,
|
|
|
- usb_sndintpipe(dev,
|
|
|
- endpoint->bEndpointAddress),
|
|
|
- port->interrupt_out_buffer, buffer_size,
|
|
|
- serial->type->write_int_callback, port,
|
|
|
- endpoint->bInterval);
|
|
|
}
|
|
|
} else if (epds->num_interrupt_out) {
|
|
|
dev_dbg(ddev, "The device claims to support interrupt out transfers, but write_int_callback is not defined\n");
|