This patch adds equal support for interrupt out transfers to the usb-serial core to
match the current interrupt in support. It also improves a few debug messages,
nothing major. This is necessary for the cypress_m8 driver being released 9/30/04.
Signed-off-by: Lonnie Mendez <[EMAIL PROTECTED]>
--- a/drivers/usb/serial/usb-serial.c 2004-09-30 16:18:43.146802216 -0500
+++ b/drivers/usb/serial/usb-serial.c 2004-09-30 16:19:50.229604080 -0500
@@ -466,9 +466,14 @@
usb_unlink_urb(port->interrupt_in_urb);
usb_free_urb(port->interrupt_in_urb);
}
+ if (port->interrupt_out_urb) {
+ usb_unlink_urb(port->interrupt_out_urb);
+ usb_free_urb(port->interrupt_out_urb);
+ }
kfree(port->bulk_in_buffer);
kfree(port->bulk_out_buffer);
kfree(port->interrupt_in_buffer);
+ kfree(port->interrupt_out_buffer);
}
}
@@ -825,9 +830,14 @@
usb_unlink_urb(port->interrupt_in_urb);
usb_free_urb(port->interrupt_in_urb);
}
+ if (port->interrupt_out_urb) {
+ usb_unlink_urb(port->interrupt_out_urb);
+ usb_free_urb(port->interrupt_out_urb);
+ }
kfree(port->bulk_in_buffer);
kfree(port->bulk_out_buffer);
kfree(port->interrupt_in_buffer);
+ kfree(port->interrupt_out_buffer);
kfree(port);
}
@@ -862,6 +872,7 @@
struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *endpoint;
struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS];
+ struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS];
struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];
struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
struct usb_serial_device_type *type = NULL;
@@ -872,6 +883,7 @@
int buffer_size;
int i;
int num_interrupt_in = 0;
+ int num_interrupt_out = 0;
int num_bulk_in = 0;
int num_bulk_out = 0;
int num_ports = 0;
@@ -928,7 +940,7 @@
if ((endpoint->bEndpointAddress & 0x80) &&
((endpoint->bmAttributes & 3) == 0x02)) {
/* we found a bulk in endpoint */
- dbg("found bulk in");
+ dbg("found bulk in on endpoint %d", i);
bulk_in_endpoint[num_bulk_in] = endpoint;
++num_bulk_in;
}
@@ -936,7 +948,7 @@
if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
((endpoint->bmAttributes & 3) == 0x02)) {
/* we found a bulk out endpoint */
- dbg("found bulk out");
+ dbg("found bulk out on endpoint %d", i);
bulk_out_endpoint[num_bulk_out] = endpoint;
++num_bulk_out;
}
@@ -944,10 +956,18 @@
if ((endpoint->bEndpointAddress & 0x80) &&
((endpoint->bmAttributes & 3) == 0x03)) {
/* we found a interrupt in endpoint */
- dbg("found interrupt in");
+ dbg("found interrupt in on endpoint %d", i);
interrupt_in_endpoint[num_interrupt_in] = endpoint;
++num_interrupt_in;
}
+
+ if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
+ ((endpoint->bmAttributes & 3) == 0x03)) {
+ /* we found an interrupt out endpoint */
+ dbg("found interrupt out on endpoint %d", i);
+ interrupt_out_endpoint[num_interrupt_out] = endpoint;
+ ++num_interrupt_out;
+ }
}
#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
@@ -1024,11 +1044,13 @@
serial->num_bulk_in = num_bulk_in;
serial->num_bulk_out = num_bulk_out;
serial->num_interrupt_in = num_interrupt_in;
+ serial->num_interrupt_out = num_interrupt_out;
/* create our ports, we need as many as the max endpoints */
/* we don't use num_ports here cauz some devices have more endpoint pairs than ports */
max_endpoints = max(num_bulk_in, num_bulk_out);
max_endpoints = max(max_endpoints, num_interrupt_in);
+ max_endpoints = max(max_endpoints, num_interrupt_out);
max_endpoints = max(max_endpoints, (int)serial->num_ports);
serial->num_port_pointers = max_endpoints;
dbg("%s - setting up %d port structures for this device", __FUNCTION__, max_endpoints);
@@ -1091,29 +1113,61 @@
port);
}
- for (i = 0; i < num_interrupt_in; ++i) {
- endpoint = interrupt_in_endpoint[i];
- port = serial->port[i];
- port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!port->interrupt_in_urb) {
- dev_err(&interface->dev, "No free urbs available\n");
- goto probe_error;
+ if (serial->type->read_int_callback) {
+ for (i = 0; i < num_interrupt_in; ++i) {
+ endpoint = interrupt_in_endpoint[i];
+ port = serial->port[i];
+ port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!port->interrupt_in_urb) {
+ dev_err(&interface->dev, "No free urbs available\n");
+ goto probe_error;
+ }
+ buffer_size = endpoint->wMaxPacketSize;
+ port->interrupt_in_endpointAddress = endpoint->bEndpointAddress;
+ port->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
+ if (!port->interrupt_in_buffer) {
+ dev_err(&interface->dev, "Couldn't allocate interrupt_in_buffer\n");
+ 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);
}
- buffer_size = endpoint->wMaxPacketSize;
- port->interrupt_in_endpointAddress = endpoint->bEndpointAddress;
- port->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
- if (!port->interrupt_in_buffer) {
- dev_err(&interface->dev, "Couldn't allocate interrupt_in_buffer\n");
- goto probe_error;
+ } else if (num_interrupt_in) {
+ dbg("the device claims to support interrupt in transfers, but read_int_callback is not defined");
+ }
+
+ if (serial->type->write_int_callback) {
+ for (i = 0; i < num_interrupt_out; ++i) {
+ endpoint = interrupt_out_endpoint[i];
+ port = serial->port[i];
+ port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!port->interrupt_out_urb) {
+ dev_err(&interface->dev, "No free urbs available\n");
+ goto probe_error;
+ }
+ buffer_size = endpoint->wMaxPacketSize;
+ 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) {
+ dev_err(&interface->dev, "Couldn't allocate interrupt_out_buffer\n");
+ 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);
}
- 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 (num_interrupt_out) {
+ dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined");
}
-
+
/* if this device type has an attach function, call it */
if (type->attach) {
if (!try_module_get(type->owner)) {
@@ -1176,6 +1230,14 @@
usb_free_urb (port->interrupt_in_urb);
kfree(port->interrupt_in_buffer);
}
+ for (i = 0; i < num_interrupt_out; ++i) {
+ port = serial->port[i];
+ if (!port)
+ continue;
+ if (port->interrupt_out_urb)
+ usb_free_urb (port->interrupt_out_urb);
+ kfree(port->interrupt_out_buffer);
+ }
/* return the minor range that this device had */
return_serial (serial);
--- a/drivers/usb/serial/usb-serial.h 2004-08-14 05:56:25.000000000 -0500
+++ b/drivers/usb/serial/usb-serial.h 2004-09-30 16:19:50.242602104 -0500
@@ -74,6 +74,11 @@
* @interrupt_in_urb: pointer to the interrupt in struct urb for this port.
* @interrupt_in_endpointAddress: endpoint address for the interrupt in pipe
* for this port.
+ * @interrupt_out_buffer: pointer to the interrupt out buffer for this port.
+ * @interrupt_out_size: the size of the interrupt_out_buffer, in bytes.
+ * @interrupt_out_urb: pointer to the interrupt out struct urb for this port.
+ * @interrupt_out_endpointAddress: endpoint address for the interrupt out pipe
+ * for this port.
* @bulk_in_buffer: pointer to the bulk in buffer for this port.
* @read_urb: pointer to the bulk in struct urb for this port.
* @bulk_in_endpointAddress: endpoint address for the bulk in pipe for this
@@ -99,6 +104,11 @@
struct urb * interrupt_in_urb;
__u8 interrupt_in_endpointAddress;
+ unsigned char * interrupt_out_buffer;
+ int interrupt_out_size;
+ struct urb * interrupt_out_urb;
+ __u8 interrupt_out_endpointAddress;
+
unsigned char * bulk_in_buffer;
struct urb * read_urb;
__u8 bulk_in_endpointAddress;
@@ -134,6 +144,7 @@
* @minor: the starting minor number for this device
* @num_ports: the number of ports this device has
* @num_interrupt_in: number of interrupt in endpoints we have
+ * @num_interrupt_out: number of interrupt out endpoints we have
* @num_bulk_in: number of bulk in endpoints we have
* @num_bulk_out: number of bulk out endpoints we have
* @vendor: vendor id of this device
@@ -152,6 +163,7 @@
unsigned char num_ports;
unsigned char num_port_pointers;
char num_interrupt_in;
+ char num_interrupt_out;
char num_bulk_in;
char num_bulk_out;
__u16 vendor;
@@ -187,6 +199,8 @@
* of the devices this structure can support.
* @num_interrupt_in: the number of interrupt in endpoints this device will
* have.
+ * @num_interrupt_out: the number of interrupt out endpoints this device will
+ * have.
* @num_bulk_in: the number of bulk in endpoints this device will have.
* @num_bulk_out: the number of bulk out endpoints this device will have.
* @num_ports: the number of different ports this device will have.
@@ -219,6 +233,7 @@
char *short_name;
const struct usb_device_id *id_table;
char num_interrupt_in;
+ char num_interrupt_out;
char num_bulk_in;
char num_bulk_out;
char num_ports;
@@ -250,6 +265,7 @@
int (*tiocmset) (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
void (*read_int_callback)(struct urb *urb, struct pt_regs *regs);
+ void (*write_int_callback)(struct urb *urb, struct pt_regs *regs);
void (*read_bulk_callback)(struct urb *urb, struct pt_regs *regs);
void (*write_bulk_callback)(struct urb *urb, struct pt_regs *regs);
};