aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/function
diff options
context:
space:
mode:
authorAndrzej Pietrasiewicz <andrzej.p@samsung.com>2014-07-22 13:58:35 -0400
committerFelipe Balbi <balbi@ti.com>2014-08-20 15:04:42 -0400
commit3aeea3c53e73b972ff07a1d03d6cc07f97de4f2f (patch)
treee05e46602c596d7b717f5db3bfb93894f782baef /drivers/usb/gadget/function
parent065a107cdd70f0621011424009b3ecd4e42481b1 (diff)
usb: gadget: f_uac2: add configfs support
Add support for using f_uac2 function as a component of a gadget composed with configfs. Tested-by: Sebastian Reimers <sebastian.reimers@googlemail.com> Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/gadget/function')
-rw-r--r--drivers/usb/gadget/function/f_uac2.c105
-rw-r--r--drivers/usb/gadget/function/u_uac2.h3
2 files changed, 108 insertions, 0 deletions
diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c
index 1b9671effa12..0d65e7c08a93 100644
--- a/drivers/usb/gadget/function/f_uac2.c
+++ b/drivers/usb/gadget/function/f_uac2.c
@@ -1330,6 +1330,93 @@ afunc_setup(struct usb_function *fn, const struct usb_ctrlrequest *cr)
1330 return value; 1330 return value;
1331} 1331}
1332 1332
1333static inline struct f_uac2_opts *to_f_uac2_opts(struct config_item *item)
1334{
1335 return container_of(to_config_group(item), struct f_uac2_opts,
1336 func_inst.group);
1337}
1338
1339CONFIGFS_ATTR_STRUCT(f_uac2_opts);
1340CONFIGFS_ATTR_OPS(f_uac2_opts);
1341
1342static void f_uac2_attr_release(struct config_item *item)
1343{
1344 struct f_uac2_opts *opts = to_f_uac2_opts(item);
1345
1346 usb_put_function_instance(&opts->func_inst);
1347}
1348
1349static struct configfs_item_operations f_uac2_item_ops = {
1350 .release = f_uac2_attr_release,
1351 .show_attribute = f_uac2_opts_attr_show,
1352 .store_attribute = f_uac2_opts_attr_store,
1353};
1354
1355#define UAC2_ATTRIBUTE(name) \
1356static ssize_t f_uac2_opts_##name##_show(struct f_uac2_opts *opts, \
1357 char *page) \
1358{ \
1359 int result; \
1360 \
1361 mutex_lock(&opts->lock); \
1362 result = sprintf(page, "%u\n", opts->name); \
1363 mutex_unlock(&opts->lock); \
1364 \
1365 return result; \
1366} \
1367 \
1368static ssize_t f_uac2_opts_##name##_store(struct f_uac2_opts *opts, \
1369 const char *page, size_t len) \
1370{ \
1371 int ret; \
1372 u32 num; \
1373 \
1374 mutex_lock(&opts->lock); \
1375 if (opts->refcnt) { \
1376 ret = -EBUSY; \
1377 goto end; \
1378 } \
1379 \
1380 ret = kstrtou32(page, 0, &num); \
1381 if (ret) \
1382 goto end; \
1383 \
1384 opts->name = num; \
1385 ret = len; \
1386 \
1387end: \
1388 mutex_unlock(&opts->lock); \
1389 return ret; \
1390} \
1391 \
1392static struct f_uac2_opts_attribute f_uac2_opts_##name = \
1393 __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, \
1394 f_uac2_opts_##name##_show, \
1395 f_uac2_opts_##name##_store)
1396
1397UAC2_ATTRIBUTE(p_chmask);
1398UAC2_ATTRIBUTE(p_srate);
1399UAC2_ATTRIBUTE(p_ssize);
1400UAC2_ATTRIBUTE(c_chmask);
1401UAC2_ATTRIBUTE(c_srate);
1402UAC2_ATTRIBUTE(c_ssize);
1403
1404static struct configfs_attribute *f_uac2_attrs[] = {
1405 &f_uac2_opts_p_chmask.attr,
1406 &f_uac2_opts_p_srate.attr,
1407 &f_uac2_opts_p_ssize.attr,
1408 &f_uac2_opts_c_chmask.attr,
1409 &f_uac2_opts_c_srate.attr,
1410 &f_uac2_opts_c_ssize.attr,
1411 NULL,
1412};
1413
1414static struct config_item_type f_uac2_func_type = {
1415 .ct_item_ops = &f_uac2_item_ops,
1416 .ct_attrs = f_uac2_attrs,
1417 .ct_owner = THIS_MODULE,
1418};
1419
1333static void afunc_free_inst(struct usb_function_instance *f) 1420static void afunc_free_inst(struct usb_function_instance *f)
1334{ 1421{
1335 struct f_uac2_opts *opts; 1422 struct f_uac2_opts *opts;
@@ -1346,17 +1433,32 @@ static struct usb_function_instance *afunc_alloc_inst(void)
1346 if (!opts) 1433 if (!opts)
1347 return ERR_PTR(-ENOMEM); 1434 return ERR_PTR(-ENOMEM);
1348 1435
1436 mutex_init(&opts->lock);
1349 opts->func_inst.free_func_inst = afunc_free_inst; 1437 opts->func_inst.free_func_inst = afunc_free_inst;
1350 1438
1439 config_group_init_type_name(&opts->func_inst.group, "",
1440 &f_uac2_func_type);
1441
1442 opts->p_chmask = UAC2_DEF_PCHMASK;
1443 opts->p_srate = UAC2_DEF_PSRATE;
1444 opts->p_ssize = UAC2_DEF_PSSIZE;
1445 opts->c_chmask = UAC2_DEF_CCHMASK;
1446 opts->c_srate = UAC2_DEF_CSRATE;
1447 opts->c_ssize = UAC2_DEF_CSSIZE;
1351 return &opts->func_inst; 1448 return &opts->func_inst;
1352} 1449}
1353 1450
1354static void afunc_free(struct usb_function *f) 1451static void afunc_free(struct usb_function *f)
1355{ 1452{
1356 struct audio_dev *agdev; 1453 struct audio_dev *agdev;
1454 struct f_uac2_opts *opts;
1357 1455
1358 agdev = func_to_agdev(f); 1456 agdev = func_to_agdev(f);
1457 opts = container_of(f->fi, struct f_uac2_opts, func_inst);
1359 kfree(agdev); 1458 kfree(agdev);
1459 mutex_lock(&opts->lock);
1460 --opts->refcnt;
1461 mutex_unlock(&opts->lock);
1360} 1462}
1361 1463
1362static void afunc_unbind(struct usb_configuration *c, struct usb_function *f) 1464static void afunc_unbind(struct usb_configuration *c, struct usb_function *f)
@@ -1389,6 +1491,9 @@ struct usb_function *afunc_alloc(struct usb_function_instance *fi)
1389 return ERR_PTR(-ENOMEM); 1491 return ERR_PTR(-ENOMEM);
1390 1492
1391 opts = container_of(fi, struct f_uac2_opts, func_inst); 1493 opts = container_of(fi, struct f_uac2_opts, func_inst);
1494 mutex_lock(&opts->lock);
1495 ++opts->refcnt;
1496 mutex_unlock(&opts->lock);
1392 1497
1393 agdev->func.name = "uac2_func"; 1498 agdev->func.name = "uac2_func";
1394 agdev->func.bind = afunc_bind; 1499 agdev->func.bind = afunc_bind;
diff --git a/drivers/usb/gadget/function/u_uac2.h b/drivers/usb/gadget/function/u_uac2.h
index ed7f7361a53e..78dd37279bd4 100644
--- a/drivers/usb/gadget/function/u_uac2.h
+++ b/drivers/usb/gadget/function/u_uac2.h
@@ -34,6 +34,9 @@ struct f_uac2_opts {
34 int c_srate; 34 int c_srate;
35 int c_ssize; 35 int c_ssize;
36 bool bound; 36 bool bound;
37
38 struct mutex lock;
39 int refcnt;
37}; 40};
38 41
39#endif 42#endif