Hello,
This patch adds support for interrupt_out to match the existing
interrupt_in support in usb-serial. I thought that it would be cleaner in
the long run to have the support here as to reproducing similar
functionality in (possibly many) other places.
It also adds a few more debugging messages, and makes a few existing ones
more specific. (I needed them for writing a driver, it is likely someone
else might need them under similar conditions.)
Thank you,
-Neil-
diff -ur ../linux-2.6.0-test9.dist/drivers/usb/serial/usb-serial.c
./drivers/usb/serial/usb-serial.c
--- ../linux-2.6.0-test9.dist/drivers/usb/serial/usb-serial.c Sat Oct 25 11:43:28
2003
+++ ./drivers/usb/serial/usb-serial.c Mon Nov 3 05:04:38 2003
@@ -14,6 +14,11 @@
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
+ * (09/25/2003) nw
+ * Added support interrupt_out to match the existing interrupt_in support.
+ * Added a few more debugging messages, made a few existing ones more
+ * specific.
+ *
* (12/10/2002) gkh
* Split the ports off into their own struct device, and added a
* usb-serial bus driver.
@@ -896,9 +901,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);
}
}
@@ -929,9 +939,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);
}
@@ -969,6 +984,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;
@@ -979,6 +995,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;
@@ -1029,13 +1046,14 @@
/* descriptor matches, let's find the endpoints needed */
/* check out the endpoints */
iface_desc = &interface->altsetting[0];
+ dbg("this device claims to have %d endpoints", iface_desc->desc.bNumEndpoints);
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
endpoint = &iface_desc->endpoint[i].desc;
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;
}
@@ -1043,7 +1061,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;
}
@@ -1051,12 +1069,22 @@
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 a interrupt out endpoint */
+ dbg("found interrupt out on endpoint %d",i);
+ interrupt_out_endpoint[num_interrupt_out] = endpoint;
+ ++num_interrupt_out;
+ }
}
+ dbg("found %d bulk_in, %d bulk_out, %d interrupt_in %d interrupt_out",
+ num_bulk_in, num_bulk_out, num_interrupt_in, num_interrupt_out);
+
#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
/* BEGIN HORRIBLE HACK FOR PL2303 */
/* this is needed due to the looney way its endpoints are set up */
@@ -1131,11 +1159,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);
@@ -1199,27 +1229,60 @@
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 */
@@ -1283,6 +1346,14 @@
if (port->interrupt_in_urb)
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 */
diff -ur ../linux-2.6.0-test9.dist/drivers/usb/serial/usb-serial.h
./drivers/usb/serial/usb-serial.h
--- ../linux-2.6.0-test9.dist/drivers/usb/serial/usb-serial.h Sat Oct 25 11:45:07
2003
+++ ./drivers/usb/serial/usb-serial.h Mon Nov 3 04:47:03 2003
@@ -77,6 +77,8 @@
* @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_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
@@ -103,6 +105,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;
@@ -139,6 +146,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
@@ -158,6 +166,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;
@@ -191,8 +200,6 @@
* to describe the driver.
* @id_table: pointer to a list of usb_device_id structures that define all
* of the devices this structure can support.
- * @num_interrupt_in: the number of interrupt in 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.
@@ -224,7 +231,6 @@
char *name;
char *short_name;
const struct usb_device_id *id_table;
- char num_interrupt_in;
char num_bulk_in;
char num_bulk_out;
char num_ports;
@@ -256,6 +262,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);
};
-------------------------------------------------------
This SF.net email is sponsored by: SF.net Giveback Program.
Does SourceForge.net help you be more productive? Does it
help you create better code? SHARE THE LOVE, and help us help
YOU! Click Here: http://sourceforge.net/donate/
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel