mirror of
https://github.com/adulau/aha.git
synced 2024-12-27 19:26:25 +00:00
usb gadget: function activation/deactivation
Add a new mechanism to the composite gadget framework, letting functions deactivate (and reactivate) themselves. Think of it as a refcounted wrapper for the software pullup control. A key example of why to use this mechanism involves functions that require a userspace daemon. Those functions shuld use this new mechanism to prevent the gadget from enumerating until those daemons are activated. Without this mechanism, hosts would see devices that malfunction until the relevant daemons start. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
8066134ff8
commit
60beed95e3
2 changed files with 73 additions and 2 deletions
|
@ -127,6 +127,70 @@ done:
|
|||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_function_deactivate - prevent function and gadget enumeration
|
||||
* @function: the function that isn't yet ready to respond
|
||||
*
|
||||
* Blocks response of the gadget driver to host enumeration by
|
||||
* preventing the data line pullup from being activated. This is
|
||||
* normally called during @bind() processing to change from the
|
||||
* initial "ready to respond" state, or when a required resource
|
||||
* becomes available.
|
||||
*
|
||||
* For example, drivers that serve as a passthrough to a userspace
|
||||
* daemon can block enumeration unless that daemon (such as an OBEX,
|
||||
* MTP, or print server) is ready to handle host requests.
|
||||
*
|
||||
* Not all systems support software control of their USB peripheral
|
||||
* data pullups.
|
||||
*
|
||||
* Returns zero on success, else negative errno.
|
||||
*/
|
||||
int usb_function_deactivate(struct usb_function *function)
|
||||
{
|
||||
struct usb_composite_dev *cdev = function->config->cdev;
|
||||
int status = 0;
|
||||
|
||||
spin_lock(&cdev->lock);
|
||||
|
||||
if (cdev->deactivations == 0)
|
||||
status = usb_gadget_disconnect(cdev->gadget);
|
||||
if (status == 0)
|
||||
cdev->deactivations++;
|
||||
|
||||
spin_unlock(&cdev->lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_function_activate - allow function and gadget enumeration
|
||||
* @function: function on which usb_function_activate() was called
|
||||
*
|
||||
* Reverses effect of usb_function_deactivate(). If no more functions
|
||||
* are delaying their activation, the gadget driver will respond to
|
||||
* host enumeration procedures.
|
||||
*
|
||||
* Returns zero on success, else negative errno.
|
||||
*/
|
||||
int usb_function_activate(struct usb_function *function)
|
||||
{
|
||||
struct usb_composite_dev *cdev = function->config->cdev;
|
||||
int status = 0;
|
||||
|
||||
spin_lock(&cdev->lock);
|
||||
|
||||
if (WARN_ON(cdev->deactivations == 0))
|
||||
status = -EINVAL;
|
||||
else {
|
||||
cdev->deactivations--;
|
||||
if (cdev->deactivations == 0)
|
||||
status = usb_gadget_connect(cdev->gadget);
|
||||
}
|
||||
|
||||
spin_unlock(&cdev->lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_interface_id() - allocate an unused interface ID
|
||||
* @config: configuration associated with the interface
|
||||
|
|
|
@ -130,6 +130,9 @@ struct usb_function {
|
|||
|
||||
int usb_add_function(struct usb_configuration *, struct usb_function *);
|
||||
|
||||
int usb_function_deactivate(struct usb_function *);
|
||||
int usb_function_activate(struct usb_function *);
|
||||
|
||||
int usb_interface_id(struct usb_configuration *, struct usb_function *);
|
||||
|
||||
/**
|
||||
|
@ -316,9 +319,13 @@ struct usb_composite_dev {
|
|||
struct usb_composite_driver *driver;
|
||||
u8 next_string_id;
|
||||
|
||||
spinlock_t lock;
|
||||
/* the gadget driver won't enable the data pullup
|
||||
* while the deactivation count is nonzero.
|
||||
*/
|
||||
unsigned deactivations;
|
||||
|
||||
/* REVISIT use and existence of lock ... */
|
||||
/* protects at least deactivation count */
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
extern int usb_string_id(struct usb_composite_dev *c);
|
||||
|
|
Loading…
Reference in a new issue