aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/g_ffs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget/g_ffs.c')
-rw-r--r--drivers/usb/gadget/g_ffs.c200
1 files changed, 176 insertions, 24 deletions
diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c
index a85eaf40b948..d3ace9002a6a 100644
--- a/drivers/usb/gadget/g_ffs.c
+++ b/drivers/usb/gadget/g_ffs.c
@@ -67,6 +67,15 @@ MODULE_LICENSE("GPL");
67#define GFS_VENDOR_ID 0x1d6b /* Linux Foundation */ 67#define GFS_VENDOR_ID 0x1d6b /* Linux Foundation */
68#define GFS_PRODUCT_ID 0x0105 /* FunctionFS Gadget */ 68#define GFS_PRODUCT_ID 0x0105 /* FunctionFS Gadget */
69 69
70#define GFS_MAX_DEVS 10
71
72struct gfs_ffs_obj {
73 const char *name;
74 bool mounted;
75 bool desc_ready;
76 struct ffs_data *ffs_data;
77};
78
70static struct usb_device_descriptor gfs_dev_desc = { 79static struct usb_device_descriptor gfs_dev_desc = {
71 .bLength = sizeof gfs_dev_desc, 80 .bLength = sizeof gfs_dev_desc,
72 .bDescriptorType = USB_DT_DEVICE, 81 .bDescriptorType = USB_DT_DEVICE,
@@ -78,12 +87,17 @@ static struct usb_device_descriptor gfs_dev_desc = {
78 .idProduct = cpu_to_le16(GFS_PRODUCT_ID), 87 .idProduct = cpu_to_le16(GFS_PRODUCT_ID),
79}; 88};
80 89
90static char *func_names[GFS_MAX_DEVS];
91static unsigned int func_num;
92
81module_param_named(bDeviceClass, gfs_dev_desc.bDeviceClass, byte, 0644); 93module_param_named(bDeviceClass, gfs_dev_desc.bDeviceClass, byte, 0644);
82MODULE_PARM_DESC(bDeviceClass, "USB Device class"); 94MODULE_PARM_DESC(bDeviceClass, "USB Device class");
83module_param_named(bDeviceSubClass, gfs_dev_desc.bDeviceSubClass, byte, 0644); 95module_param_named(bDeviceSubClass, gfs_dev_desc.bDeviceSubClass, byte, 0644);
84MODULE_PARM_DESC(bDeviceSubClass, "USB Device subclass"); 96MODULE_PARM_DESC(bDeviceSubClass, "USB Device subclass");
85module_param_named(bDeviceProtocol, gfs_dev_desc.bDeviceProtocol, byte, 0644); 97module_param_named(bDeviceProtocol, gfs_dev_desc.bDeviceProtocol, byte, 0644);
86MODULE_PARM_DESC(bDeviceProtocol, "USB Device protocol"); 98MODULE_PARM_DESC(bDeviceProtocol, "USB Device protocol");
99module_param_array_named(functions, func_names, charp, &func_num, 0);
100MODULE_PARM_DESC(functions, "USB Functions list");
87 101
88static const struct usb_descriptor_header *gfs_otg_desc[] = { 102static const struct usb_descriptor_header *gfs_otg_desc[] = {
89 (const struct usb_descriptor_header *) 103 (const struct usb_descriptor_header *)
@@ -158,13 +172,34 @@ static struct usb_composite_driver gfs_driver = {
158 .iProduct = DRIVER_DESC, 172 .iProduct = DRIVER_DESC,
159}; 173};
160 174
161static struct ffs_data *gfs_ffs_data; 175static DEFINE_MUTEX(gfs_lock);
162static unsigned long gfs_registered; 176static unsigned int missing_funcs;
177static bool gfs_ether_setup;
178static bool gfs_registered;
179static bool gfs_single_func;
180static struct gfs_ffs_obj *ffs_tab;
163 181
164static int __init gfs_init(void) 182static int __init gfs_init(void)
165{ 183{
184 int i;
185
166 ENTER(); 186 ENTER();
167 187
188 if (!func_num) {
189 gfs_single_func = true;
190 func_num = 1;
191 }
192
193 ffs_tab = kcalloc(func_num, sizeof *ffs_tab, GFP_KERNEL);
194 if (!ffs_tab)
195 return -ENOMEM;
196
197 if (!gfs_single_func)
198 for (i = 0; i < func_num; i++)
199 ffs_tab[i].name = func_names[i];
200
201 missing_funcs = func_num;
202
168 return functionfs_init(); 203 return functionfs_init();
169} 204}
170module_init(gfs_init); 205module_init(gfs_init);
@@ -172,63 +207,165 @@ module_init(gfs_init);
172static void __exit gfs_exit(void) 207static void __exit gfs_exit(void)
173{ 208{
174 ENTER(); 209 ENTER();
210 mutex_lock(&gfs_lock);
175 211
176 if (test_and_clear_bit(0, &gfs_registered)) 212 if (gfs_registered)
177 usb_composite_unregister(&gfs_driver); 213 usb_composite_unregister(&gfs_driver);
214 gfs_registered = false;
178 215
179 functionfs_cleanup(); 216 functionfs_cleanup();
217
218 mutex_unlock(&gfs_lock);
219 kfree(ffs_tab);
180} 220}
181module_exit(gfs_exit); 221module_exit(gfs_exit);
182 222
223static struct gfs_ffs_obj *gfs_find_dev(const char *dev_name)
224{
225 int i;
226
227 ENTER();
228
229 if (gfs_single_func)
230 return &ffs_tab[0];
231
232 for (i = 0; i < func_num; i++)
233 if (strcmp(ffs_tab[i].name, dev_name) == 0)
234 return &ffs_tab[i];
235
236 return NULL;
237}
238
183static int functionfs_ready_callback(struct ffs_data *ffs) 239static int functionfs_ready_callback(struct ffs_data *ffs)
184{ 240{
241 struct gfs_ffs_obj *ffs_obj;
185 int ret; 242 int ret;
186 243
187 ENTER(); 244 ENTER();
245 mutex_lock(&gfs_lock);
246
247 ffs_obj = ffs->private_data;
248 if (!ffs_obj) {
249 ret = -EINVAL;
250 goto done;
251 }
252
253 if (WARN_ON(ffs_obj->desc_ready)) {
254 ret = -EBUSY;
255 goto done;
256 }
257 ffs_obj->desc_ready = true;
258 ffs_obj->ffs_data = ffs;
188 259
189 if (WARN_ON(test_and_set_bit(0, &gfs_registered))) 260 if (--missing_funcs) {
190 return -EBUSY; 261 ret = 0;
262 goto done;
263 }
264
265 if (gfs_registered) {
266 ret = -EBUSY;
267 goto done;
268 }
269 gfs_registered = true;
191 270
192 gfs_ffs_data = ffs;
193 ret = usb_composite_probe(&gfs_driver, gfs_bind); 271 ret = usb_composite_probe(&gfs_driver, gfs_bind);
194 if (unlikely(ret < 0)) 272 if (unlikely(ret < 0))
195 clear_bit(0, &gfs_registered); 273 gfs_registered = false;
274
275done:
276 mutex_unlock(&gfs_lock);
196 return ret; 277 return ret;
197} 278}
198 279
199static void functionfs_closed_callback(struct ffs_data *ffs) 280static void functionfs_closed_callback(struct ffs_data *ffs)
200{ 281{
282 struct gfs_ffs_obj *ffs_obj;
283
201 ENTER(); 284 ENTER();
285 mutex_lock(&gfs_lock);
202 286
203 if (test_and_clear_bit(0, &gfs_registered)) 287 ffs_obj = ffs->private_data;
288 if (!ffs_obj)
289 goto done;
290
291 ffs_obj->desc_ready = false;
292 missing_funcs++;
293
294 if (gfs_registered)
204 usb_composite_unregister(&gfs_driver); 295 usb_composite_unregister(&gfs_driver);
296 gfs_registered = false;
297
298done:
299 mutex_unlock(&gfs_lock);
205} 300}
206 301
207static int functionfs_check_dev_callback(const char *dev_name) 302static void *functionfs_acquire_dev_callback(const char *dev_name)
208{ 303{
209 return 0; 304 struct gfs_ffs_obj *ffs_dev;
305
306 ENTER();
307 mutex_lock(&gfs_lock);
308
309 ffs_dev = gfs_find_dev(dev_name);
310 if (!ffs_dev) {
311 ffs_dev = ERR_PTR(-ENODEV);
312 goto done;
313 }
314
315 if (ffs_dev->mounted) {
316 ffs_dev = ERR_PTR(-EBUSY);
317 goto done;
318 }
319 ffs_dev->mounted = true;
320
321done:
322 mutex_unlock(&gfs_lock);
323 return ffs_dev;
210} 324}
211 325
326static void functionfs_release_dev_callback(struct ffs_data *ffs_data)
327{
328 struct gfs_ffs_obj *ffs_dev;
329
330 ENTER();
331 mutex_lock(&gfs_lock);
332
333 ffs_dev = ffs_data->private_data;
334 if (ffs_dev)
335 ffs_dev->mounted = false;
336
337 mutex_unlock(&gfs_lock);
338}
339
340/*
341 * It is assumed that gfs_bind is called from a context where gfs_lock is held
342 */
212static int gfs_bind(struct usb_composite_dev *cdev) 343static int gfs_bind(struct usb_composite_dev *cdev)
213{ 344{
214 int ret, i; 345 int ret, i;
215 346
216 ENTER(); 347 ENTER();
217 348
218 if (WARN_ON(!gfs_ffs_data)) 349 if (missing_funcs)
219 return -ENODEV; 350 return -ENODEV;
220 351
221 ret = gether_setup(cdev->gadget, gfs_hostaddr); 352 ret = gether_setup(cdev->gadget, gfs_hostaddr);
222 if (unlikely(ret < 0)) 353 if (unlikely(ret < 0))
223 goto error_quick; 354 goto error_quick;
355 gfs_ether_setup = true;
224 356
225 ret = usb_string_ids_tab(cdev, gfs_strings); 357 ret = usb_string_ids_tab(cdev, gfs_strings);
226 if (unlikely(ret < 0)) 358 if (unlikely(ret < 0))
227 goto error; 359 goto error;
228 360
229 ret = functionfs_bind(gfs_ffs_data, cdev); 361 for (i = func_num; --i; ) {
230 if (unlikely(ret < 0)) 362 ret = functionfs_bind(ffs_tab[i].ffs_data, cdev);
231 goto error; 363 if (unlikely(ret < 0)) {
364 while (++i < func_num)
365 functionfs_unbind(ffs_tab[i].ffs_data);
366 goto error;
367 }
368 }
232 369
233 for (i = 0; i < ARRAY_SIZE(gfs_configurations); ++i) { 370 for (i = 0; i < ARRAY_SIZE(gfs_configurations); ++i) {
234 struct gfs_configuration *c = gfs_configurations + i; 371 struct gfs_configuration *c = gfs_configurations + i;
@@ -246,16 +383,22 @@ static int gfs_bind(struct usb_composite_dev *cdev)
246 return 0; 383 return 0;
247 384
248error_unbind: 385error_unbind:
249 functionfs_unbind(gfs_ffs_data); 386 for (i = 0; i < func_num; i++)
387 functionfs_unbind(ffs_tab[i].ffs_data);
250error: 388error:
251 gether_cleanup(); 389 gether_cleanup();
252error_quick: 390error_quick:
253 gfs_ffs_data = NULL; 391 gfs_ether_setup = false;
254 return ret; 392 return ret;
255} 393}
256 394
395/*
396 * It is assumed that gfs_unbind is called from a context where gfs_lock is held
397 */
257static int gfs_unbind(struct usb_composite_dev *cdev) 398static int gfs_unbind(struct usb_composite_dev *cdev)
258{ 399{
400 int i;
401
259 ENTER(); 402 ENTER();
260 403
261 /* 404 /*
@@ -266,22 +409,29 @@ static int gfs_unbind(struct usb_composite_dev *cdev)
266 * from composite on orror recovery, but what you're gonna 409 * from composite on orror recovery, but what you're gonna
267 * do...? 410 * do...?
268 */ 411 */
269 if (gfs_ffs_data) { 412 if (gfs_ether_setup)
270 gether_cleanup(); 413 gether_cleanup();
271 functionfs_unbind(gfs_ffs_data); 414 gfs_ether_setup = false;
272 gfs_ffs_data = NULL; 415
273 } 416 for (i = func_num; --i; )
417 if (ffs_tab[i].ffs_data)
418 functionfs_unbind(ffs_tab[i].ffs_data);
274 419
275 return 0; 420 return 0;
276} 421}
277 422
423/*
424 * It is assumed that gfs_do_config is called from a context where
425 * gfs_lock is held
426 */
278static int gfs_do_config(struct usb_configuration *c) 427static int gfs_do_config(struct usb_configuration *c)
279{ 428{
280 struct gfs_configuration *gc = 429 struct gfs_configuration *gc =
281 container_of(c, struct gfs_configuration, c); 430 container_of(c, struct gfs_configuration, c);
431 int i;
282 int ret; 432 int ret;
283 433
284 if (WARN_ON(!gfs_ffs_data)) 434 if (missing_funcs)
285 return -ENODEV; 435 return -ENODEV;
286 436
287 if (gadget_is_otg(c->cdev->gadget)) { 437 if (gadget_is_otg(c->cdev->gadget)) {
@@ -295,9 +445,11 @@ static int gfs_do_config(struct usb_configuration *c)
295 return ret; 445 return ret;
296 } 446 }
297 447
298 ret = functionfs_bind_config(c->cdev, c, gfs_ffs_data); 448 for (i = 0; i < func_num; i++) {
299 if (unlikely(ret < 0)) 449 ret = functionfs_bind_config(c->cdev, c, ffs_tab[i].ffs_data);
300 return ret; 450 if (unlikely(ret < 0))
451 return ret;
452 }
301 453
302 /* 454 /*
303 * After previous do_configs there may be some invalid 455 * After previous do_configs there may be some invalid