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