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

Reply via email to