ChangeSet 1.1595.7.30, 2003/07/31 22:49:50-07:00, stern@rowland.harvard.edu [PATCH] USB: Add functions to enable/disable endpoints, interfaces This is the second part of what used to be as66c. It fixes the initialization of the debugging macros in core/message.c and adds routines to enable/disable endpoints, interfaces, and entire devices. The code that _uses_ these routines will come in the next patch. # Initialize the debugging macros properly in message.c. # # Add usb_disable_endpoint(), usb_disable_interface(), usb_disable_device(), # usb_enable_endpoint(), and usb_enable_interface(). drivers/usb/core/message.c | 127 +++++++++++++++++++++++++++++++++++++++++++++ drivers/usb/core/usb.h | 10 +++ 2 files changed, 137 insertions(+) diff -Nru a/drivers/usb/core/message.c b/drivers/usb/core/message.c --- a/drivers/usb/core/message.c Fri Aug 1 10:54:03 2003 +++ b/drivers/usb/core/message.c Fri Aug 1 10:54:03 2003 @@ -2,6 +2,14 @@ * message.c - synchronous message handling */ +#include + +#ifdef CONFIG_USB_DEBUG + #define DEBUG +#else + #undef DEBUG +#endif + #include /* for scatterlist macros */ #include #include @@ -11,6 +19,7 @@ #include #include "hcd.h" /* for usbcore internals */ +#include "usb.h" struct usb_api_data { wait_queue_head_t wqh; @@ -757,6 +766,124 @@ usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); return 0; +} + +/** + * usb_disable_endpoint -- Disable an endpoint by address + * @dev: the device whose endpoint is being disabled + * @epaddr: the endpoint's address. Endpoint number for output, + * endpoint number + USB_DIR_IN for input + * + * Deallocates hcd/hardware state for this endpoint ... and nukes all + * pending urbs. + * + * If the HCD hasn't registered a disable() function, this marks the + * endpoint as halted and sets its maxpacket size to 0 to prevent + * further submissions. + */ +void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr) +{ + if (dev && dev->bus && dev->bus->op && dev->bus->op->disable) + dev->bus->op->disable(dev, epaddr); + else { + unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK; + + if (usb_endpoint_out(epaddr)) { + usb_endpoint_halt(dev, epnum, 1); + dev->epmaxpacketout[epnum] = 0; + } else { + usb_endpoint_halt(dev, epnum, 0); + dev->epmaxpacketin[epnum] = 0; + } + } +} + +/** + * usb_disable_interface -- Disable all endpoints for an interface + * @dev: the device whose interface is being disabled + * @intf: pointer to the interface descriptor + * + * Disables all the endpoints for the interface's current altsetting. + */ +void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf) +{ + struct usb_host_interface *hintf = + &intf->altsetting[intf->act_altsetting]; + int i; + + for (i = 0; i < hintf->desc.bNumEndpoints; ++i) { + usb_disable_endpoint(dev, + hintf->endpoint[i].desc.bEndpointAddress); + } +} + +/* + * usb_disable_device - Disable all the endpoints for a USB device + * @dev: the device whose endpoints are being disabled + * @skip_ep0: 0 to disable endpoint 0, 1 to skip it. + * + * Disables all the device's endpoints, potentially including endpoint 0. + * Deallocates hcd/hardware state for the endpoints ... and nukes all + * pending urbs. + */ +void usb_disable_device(struct usb_device *dev, int skip_ep0) +{ + int i; + + dbg("nuking URBs for device %s", dev->dev.bus_id); + for (i = skip_ep0; i < 16; ++i) { + usb_disable_endpoint(dev, i); + usb_disable_endpoint(dev, i + USB_DIR_IN); + } +} + + +/* + * usb_enable_endpoint - Enable an endpoint for USB communications + * @dev: the device whose interface is being enabled + * @epd: pointer to the endpoint descriptor + * + * Marks the endpoint as running, resets its toggle, and stores + * its maxpacket value. For control endpoints, both the input + * and output sides are handled. + */ +void usb_enable_endpoint(struct usb_device *dev, + struct usb_endpoint_descriptor *epd) +{ + int maxsize = epd->wMaxPacketSize; + unsigned int epaddr = epd->bEndpointAddress; + unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK; + int is_control = ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_CONTROL); + + if (usb_endpoint_out(epaddr) || is_control) { + usb_endpoint_running(dev, epnum, 1); + usb_settoggle(dev, epnum, 1, 0); + dev->epmaxpacketout[epnum] = maxsize; + } + if (!usb_endpoint_out(epaddr) || is_control) { + usb_endpoint_running(dev, epnum, 0); + usb_settoggle(dev, epnum, 0, 0); + dev->epmaxpacketin[epnum] = maxsize; + } +} + +/* + * usb_enable_interface - Enable all the endpoints for an interface + * @dev: the device whose interface is being enabled + * @intf: pointer to the interface descriptor + * + * Enables all the endpoints for the interface's current altsetting. + */ +void usb_enable_interface(struct usb_device *dev, + struct usb_interface *intf) +{ + struct usb_host_interface *hintf = + &intf->altsetting[intf->act_altsetting]; + int i; + + for (i = 0; i < hintf->desc.bNumEndpoints; ++i) + usb_enable_endpoint(dev, &hintf->endpoint[i].desc); } /** diff -Nru a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h --- a/drivers/usb/core/usb.h Fri Aug 1 10:54:03 2003 +++ b/drivers/usb/core/usb.h Fri Aug 1 10:54:03 2003 @@ -4,3 +4,13 @@ extern void usb_create_driverfs_intf_files (struct usb_interface *intf); extern int usb_probe_interface (struct device *dev); extern int usb_unbind_interface (struct device *dev); + +extern void usb_disable_endpoint (struct usb_device *dev, unsigned int epaddr); +extern void usb_disable_interface (struct usb_device *dev, + struct usb_interface *intf); +extern void usb_disable_device (struct usb_device *dev, int skip_ep0); + +extern void usb_enable_endpoint (struct usb_device *dev, + struct usb_endpoint_descriptor *epd); +extern void usb_enable_interface (struct usb_device *dev, + struct usb_interface *intf);