aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Brownell <dbrownell@users.sourceforge.net>2008-08-18 20:38:22 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2008-10-17 17:40:53 -0400
commit60beed95e38793c0baff7f94433c1f639d8d5efd (patch)
treef35e277cdd32267772854b481843299564e4f3e8
parent8066134ff8140ae9d8d15cdad3fc6c60c2a8a4e5 (diff)
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>
-rw-r--r--drivers/usb/gadget/composite.c64
-rw-r--r--include/linux/usb/composite.h11
2 files changed, 73 insertions, 2 deletions
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 85c876c1f150..f79fdb839cb8 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -128,6 +128,70 @@ done:
128} 128}
129 129
130/** 130/**
131 * usb_function_deactivate - prevent function and gadget enumeration
132 * @function: the function that isn't yet ready to respond
133 *
134 * Blocks response of the gadget driver to host enumeration by
135 * preventing the data line pullup from being activated. This is
136 * normally called during @bind() processing to change from the
137 * initial "ready to respond" state, or when a required resource
138 * becomes available.
139 *
140 * For example, drivers that serve as a passthrough to a userspace
141 * daemon can block enumeration unless that daemon (such as an OBEX,
142 * MTP, or print server) is ready to handle host requests.
143 *
144 * Not all systems support software control of their USB peripheral
145 * data pullups.
146 *
147 * Returns zero on success, else negative errno.
148 */
149int usb_function_deactivate(struct usb_function *function)
150{
151 struct usb_composite_dev *cdev = function->config->cdev;
152 int status = 0;
153
154 spin_lock(&cdev->lock);
155
156 if (cdev->deactivations == 0)
157 status = usb_gadget_disconnect(cdev->gadget);
158 if (status == 0)
159 cdev->deactivations++;
160
161 spin_unlock(&cdev->lock);
162 return status;
163}
164
165/**
166 * usb_function_activate - allow function and gadget enumeration
167 * @function: function on which usb_function_activate() was called
168 *
169 * Reverses effect of usb_function_deactivate(). If no more functions
170 * are delaying their activation, the gadget driver will respond to
171 * host enumeration procedures.
172 *
173 * Returns zero on success, else negative errno.
174 */
175int usb_function_activate(struct usb_function *function)
176{
177 struct usb_composite_dev *cdev = function->config->cdev;
178 int status = 0;
179
180 spin_lock(&cdev->lock);
181
182 if (WARN_ON(cdev->deactivations == 0))
183 status = -EINVAL;
184 else {
185 cdev->deactivations--;
186 if (cdev->deactivations == 0)
187 status = usb_gadget_connect(cdev->gadget);
188 }
189
190 spin_unlock(&cdev->lock);
191 return status;
192}
193
194/**
131 * usb_interface_id() - allocate an unused interface ID 195 * usb_interface_id() - allocate an unused interface ID
132 * @config: configuration associated with the interface 196 * @config: configuration associated with the interface
133 * @function: function handling the interface 197 * @function: function handling the interface
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
index c932390c6da0..935c380ffe47 100644
--- a/include/linux/usb/composite.h
+++ b/include/linux/usb/composite.h
@@ -130,6 +130,9 @@ struct usb_function {
130 130
131int usb_add_function(struct usb_configuration *, struct usb_function *); 131int usb_add_function(struct usb_configuration *, struct usb_function *);
132 132
133int usb_function_deactivate(struct usb_function *);
134int usb_function_activate(struct usb_function *);
135
133int usb_interface_id(struct usb_configuration *, struct usb_function *); 136int usb_interface_id(struct usb_configuration *, struct usb_function *);
134 137
135/** 138/**
@@ -316,9 +319,13 @@ struct usb_composite_dev {
316 struct usb_composite_driver *driver; 319 struct usb_composite_driver *driver;
317 u8 next_string_id; 320 u8 next_string_id;
318 321
319 spinlock_t lock; 322 /* the gadget driver won't enable the data pullup
323 * while the deactivation count is nonzero.
324 */
325 unsigned deactivations;
320 326
321 /* REVISIT use and existence of lock ... */ 327 /* protects at least deactivation count */
328 spinlock_t lock;
322}; 329};
323 330
324extern int usb_string_id(struct usb_composite_dev *c); 331extern int usb_string_id(struct usb_composite_dev *c);