Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Andrzej Pietrasiewicz and committed by
Felipe Balbi
3aeea3c5 065a107c

+120
+12
Documentation/ABI/testing/configfs-usb-gadget-uac2
··· 1 + What: /config/usb-gadget/gadget/functions/uac2.name 2 + Date: Sep 2014 3 + KernelVersion: 3.18 4 + Description: 5 + The attributes: 6 + 7 + c_chmask - capture channel mask 8 + c_srate - capture sampling rate 9 + c_ssize - capture sample size (bytes) 10 + p_chmask - playback channel mask 11 + p_srate - playback sampling rate 12 + p_ssize - playback sample size (bytes)
+105
drivers/usb/gadget/function/f_uac2.c
··· 1330 1330 return value; 1331 1331 } 1332 1332 1333 + static 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 + 1339 + CONFIGFS_ATTR_STRUCT(f_uac2_opts); 1340 + CONFIGFS_ATTR_OPS(f_uac2_opts); 1341 + 1342 + static 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 + 1349 + static 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) \ 1356 + static 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 + \ 1368 + static 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 + \ 1387 + end: \ 1388 + mutex_unlock(&opts->lock); \ 1389 + return ret; \ 1390 + } \ 1391 + \ 1392 + static 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 + 1397 + UAC2_ATTRIBUTE(p_chmask); 1398 + UAC2_ATTRIBUTE(p_srate); 1399 + UAC2_ATTRIBUTE(p_ssize); 1400 + UAC2_ATTRIBUTE(c_chmask); 1401 + UAC2_ATTRIBUTE(c_srate); 1402 + UAC2_ATTRIBUTE(c_ssize); 1403 + 1404 + static 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 + 1414 + static 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 + 1333 1420 static void afunc_free_inst(struct usb_function_instance *f) 1334 1421 { 1335 1422 struct f_uac2_opts *opts; ··· 1433 1346 if (!opts) 1434 1347 return ERR_PTR(-ENOMEM); 1435 1348 1349 + mutex_init(&opts->lock); 1436 1350 opts->func_inst.free_func_inst = afunc_free_inst; 1437 1351 1352 + config_group_init_type_name(&opts->func_inst.group, "", 1353 + &f_uac2_func_type); 1354 + 1355 + opts->p_chmask = UAC2_DEF_PCHMASK; 1356 + opts->p_srate = UAC2_DEF_PSRATE; 1357 + opts->p_ssize = UAC2_DEF_PSSIZE; 1358 + opts->c_chmask = UAC2_DEF_CCHMASK; 1359 + opts->c_srate = UAC2_DEF_CSRATE; 1360 + opts->c_ssize = UAC2_DEF_CSSIZE; 1438 1361 return &opts->func_inst; 1439 1362 } 1440 1363 1441 1364 static void afunc_free(struct usb_function *f) 1442 1365 { 1443 1366 struct audio_dev *agdev; 1367 + struct f_uac2_opts *opts; 1444 1368 1445 1369 agdev = func_to_agdev(f); 1370 + opts = container_of(f->fi, struct f_uac2_opts, func_inst); 1446 1371 kfree(agdev); 1372 + mutex_lock(&opts->lock); 1373 + --opts->refcnt; 1374 + mutex_unlock(&opts->lock); 1447 1375 } 1448 1376 1449 1377 static void afunc_unbind(struct usb_configuration *c, struct usb_function *f) ··· 1491 1389 return ERR_PTR(-ENOMEM); 1492 1390 1493 1391 opts = container_of(fi, struct f_uac2_opts, func_inst); 1392 + mutex_lock(&opts->lock); 1393 + ++opts->refcnt; 1394 + mutex_unlock(&opts->lock); 1494 1395 1495 1396 agdev->func.name = "uac2_func"; 1496 1397 agdev->func.bind = afunc_bind;
+3
drivers/usb/gadget/function/u_uac2.h
··· 34 34 int c_srate; 35 35 int c_ssize; 36 36 bool bound; 37 + 38 + struct mutex lock; 39 + int refcnt; 37 40 }; 38 41 39 42 #endif