aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/udc-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget/udc-core.c')
-rw-r--r--drivers/usb/gadget/udc-core.c90
1 files changed, 80 insertions, 10 deletions
diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c
index f8f62c3ed65e..ffd8fa541101 100644
--- a/drivers/usb/gadget/udc-core.c
+++ b/drivers/usb/gadget/udc-core.c
@@ -101,6 +101,16 @@ EXPORT_SYMBOL_GPL(usb_gadget_unmap_request);
101 101
102/* ------------------------------------------------------------------------- */ 102/* ------------------------------------------------------------------------- */
103 103
104void usb_gadget_set_state(struct usb_gadget *gadget,
105 enum usb_device_state state)
106{
107 gadget->state = state;
108 sysfs_notify(&gadget->dev.kobj, NULL, "status");
109}
110EXPORT_SYMBOL_GPL(usb_gadget_set_state);
111
112/* ------------------------------------------------------------------------- */
113
104/** 114/**
105 * usb_gadget_udc_start - tells usb device controller to start up 115 * usb_gadget_udc_start - tells usb device controller to start up
106 * @gadget: The gadget we want to get started 116 * @gadget: The gadget we want to get started
@@ -156,15 +166,23 @@ static void usb_udc_release(struct device *dev)
156} 166}
157 167
158static const struct attribute_group *usb_udc_attr_groups[]; 168static const struct attribute_group *usb_udc_attr_groups[];
169
170static void usb_udc_nop_release(struct device *dev)
171{
172 dev_vdbg(dev, "%s\n", __func__);
173}
174
159/** 175/**
160 * usb_add_gadget_udc - adds a new gadget to the udc class driver list 176 * usb_add_gadget_udc_release - adds a new gadget to the udc class driver list
161 * @parent: the parent device to this udc. Usually the controller 177 * @parent: the parent device to this udc. Usually the controller driver's
162 * driver's device. 178 * device.
163 * @gadget: the gadget to be added to the list 179 * @gadget: the gadget to be added to the list.
180 * @release: a gadget release function.
164 * 181 *
165 * Returns zero on success, negative errno otherwise. 182 * Returns zero on success, negative errno otherwise.
166 */ 183 */
167int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget) 184int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
185 void (*release)(struct device *dev))
168{ 186{
169 struct usb_udc *udc; 187 struct usb_udc *udc;
170 int ret = -ENOMEM; 188 int ret = -ENOMEM;
@@ -173,6 +191,22 @@ int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
173 if (!udc) 191 if (!udc)
174 goto err1; 192 goto err1;
175 193
194 dev_set_name(&gadget->dev, "gadget");
195 gadget->dev.parent = parent;
196
197 dma_set_coherent_mask(&gadget->dev, parent->coherent_dma_mask);
198 gadget->dev.dma_parms = parent->dma_parms;
199 gadget->dev.dma_mask = parent->dma_mask;
200
201 if (release)
202 gadget->dev.release = release;
203 else
204 gadget->dev.release = usb_udc_nop_release;
205
206 ret = device_register(&gadget->dev);
207 if (ret)
208 goto err2;
209
176 device_initialize(&udc->dev); 210 device_initialize(&udc->dev);
177 udc->dev.release = usb_udc_release; 211 udc->dev.release = usb_udc_release;
178 udc->dev.class = udc_class; 212 udc->dev.class = udc_class;
@@ -180,7 +214,7 @@ int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
180 udc->dev.parent = parent; 214 udc->dev.parent = parent;
181 ret = dev_set_name(&udc->dev, "%s", kobject_name(&parent->kobj)); 215 ret = dev_set_name(&udc->dev, "%s", kobject_name(&parent->kobj));
182 if (ret) 216 if (ret)
183 goto err2; 217 goto err3;
184 218
185 udc->gadget = gadget; 219 udc->gadget = gadget;
186 220
@@ -189,21 +223,42 @@ int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
189 223
190 ret = device_add(&udc->dev); 224 ret = device_add(&udc->dev);
191 if (ret) 225 if (ret)
192 goto err3; 226 goto err4;
227
228 usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);
193 229
194 mutex_unlock(&udc_lock); 230 mutex_unlock(&udc_lock);
195 231
196 return 0; 232 return 0;
197err3: 233
234err4:
198 list_del(&udc->list); 235 list_del(&udc->list);
199 mutex_unlock(&udc_lock); 236 mutex_unlock(&udc_lock);
200 237
201err2: 238err3:
202 put_device(&udc->dev); 239 put_device(&udc->dev);
203 240
241err2:
242 put_device(&gadget->dev);
243 kfree(udc);
244
204err1: 245err1:
205 return ret; 246 return ret;
206} 247}
248EXPORT_SYMBOL_GPL(usb_add_gadget_udc_release);
249
250/**
251 * usb_add_gadget_udc - adds a new gadget to the udc class driver list
252 * @parent: the parent device to this udc. Usually the controller
253 * driver's device.
254 * @gadget: the gadget to be added to the list
255 *
256 * Returns zero on success, negative errno otherwise.
257 */
258int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
259{
260 return usb_add_gadget_udc_release(parent, gadget, NULL);
261}
207EXPORT_SYMBOL_GPL(usb_add_gadget_udc); 262EXPORT_SYMBOL_GPL(usb_add_gadget_udc);
208 263
209static void usb_gadget_remove_driver(struct usb_udc *udc) 264static void usb_gadget_remove_driver(struct usb_udc *udc)
@@ -220,6 +275,7 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
220 275
221 udc->driver = NULL; 276 udc->driver = NULL;
222 udc->dev.driver = NULL; 277 udc->dev.driver = NULL;
278 udc->gadget->dev.driver = NULL;
223} 279}
224 280
225/** 281/**
@@ -254,6 +310,7 @@ found:
254 310
255 kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE); 311 kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
256 device_unregister(&udc->dev); 312 device_unregister(&udc->dev);
313 device_unregister(&gadget->dev);
257} 314}
258EXPORT_SYMBOL_GPL(usb_del_gadget_udc); 315EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
259 316
@@ -268,6 +325,7 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri
268 325
269 udc->driver = driver; 326 udc->driver = driver;
270 udc->dev.driver = &driver->driver; 327 udc->dev.driver = &driver->driver;
328 udc->gadget->dev.driver = &driver->driver;
271 329
272 ret = driver->bind(udc->gadget, driver); 330 ret = driver->bind(udc->gadget, driver);
273 if (ret) 331 if (ret)
@@ -286,6 +344,7 @@ err1:
286 udc->driver->function, ret); 344 udc->driver->function, ret);
287 udc->driver = NULL; 345 udc->driver = NULL;
288 udc->dev.driver = NULL; 346 udc->dev.driver = NULL;
347 udc->gadget->dev.driver = NULL;
289 return ret; 348 return ret;
290} 349}
291 350
@@ -395,6 +454,16 @@ static ssize_t usb_udc_softconn_store(struct device *dev,
395} 454}
396static DEVICE_ATTR(soft_connect, S_IWUSR, NULL, usb_udc_softconn_store); 455static DEVICE_ATTR(soft_connect, S_IWUSR, NULL, usb_udc_softconn_store);
397 456
457static ssize_t usb_gadget_state_show(struct device *dev,
458 struct device_attribute *attr, char *buf)
459{
460 struct usb_udc *udc = container_of(dev, struct usb_udc, dev);
461 struct usb_gadget *gadget = udc->gadget;
462
463 return sprintf(buf, "%s\n", usb_state_string(gadget->state));
464}
465static DEVICE_ATTR(state, S_IRUGO, usb_gadget_state_show, NULL);
466
398#define USB_UDC_SPEED_ATTR(name, param) \ 467#define USB_UDC_SPEED_ATTR(name, param) \
399ssize_t usb_udc_##param##_show(struct device *dev, \ 468ssize_t usb_udc_##param##_show(struct device *dev, \
400 struct device_attribute *attr, char *buf) \ 469 struct device_attribute *attr, char *buf) \
@@ -403,7 +472,7 @@ ssize_t usb_udc_##param##_show(struct device *dev, \
403 return snprintf(buf, PAGE_SIZE, "%s\n", \ 472 return snprintf(buf, PAGE_SIZE, "%s\n", \
404 usb_speed_string(udc->gadget->param)); \ 473 usb_speed_string(udc->gadget->param)); \
405} \ 474} \
406static DEVICE_ATTR(name, S_IRUSR, usb_udc_##param##_show, NULL) 475static DEVICE_ATTR(name, S_IRUGO, usb_udc_##param##_show, NULL)
407 476
408static USB_UDC_SPEED_ATTR(current_speed, speed); 477static USB_UDC_SPEED_ATTR(current_speed, speed);
409static USB_UDC_SPEED_ATTR(maximum_speed, max_speed); 478static USB_UDC_SPEED_ATTR(maximum_speed, max_speed);
@@ -428,6 +497,7 @@ static USB_UDC_ATTR(a_alt_hnp_support);
428static struct attribute *usb_udc_attrs[] = { 497static struct attribute *usb_udc_attrs[] = {
429 &dev_attr_srp.attr, 498 &dev_attr_srp.attr,
430 &dev_attr_soft_connect.attr, 499 &dev_attr_soft_connect.attr,
500 &dev_attr_state.attr,
431 &dev_attr_current_speed.attr, 501 &dev_attr_current_speed.attr,
432 &dev_attr_maximum_speed.attr, 502 &dev_attr_maximum_speed.attr,
433 503