diff options
-rw-r--r-- | drivers/usb/gadget/composite.c | 64 | ||||
-rw-r--r-- | include/linux/usb/composite.h | 11 |
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 | */ | ||
149 | int 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 | */ | ||
175 | int 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 | ||
131 | int usb_add_function(struct usb_configuration *, struct usb_function *); | 131 | int usb_add_function(struct usb_configuration *, struct usb_function *); |
132 | 132 | ||
133 | int usb_function_deactivate(struct usb_function *); | ||
134 | int usb_function_activate(struct usb_function *); | ||
135 | |||
133 | int usb_interface_id(struct usb_configuration *, struct usb_function *); | 136 | int 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 | ||
324 | extern int usb_string_id(struct usb_composite_dev *c); | 331 | extern int usb_string_id(struct usb_composite_dev *c); |