diff options
| author | Andrzej Pietrasiewicz <andrzej.p@samsung.com> | 2014-07-22 13:58:30 -0400 |
|---|---|---|
| committer | Felipe Balbi <balbi@ti.com> | 2014-08-20 15:04:16 -0400 |
| commit | f8f93d244afad804e09595fcb14320fe2896fef5 (patch) | |
| tree | bb6e0e0aca769fa559481cc10f84c24a98cfebc7 /drivers/usb/gadget/function | |
| parent | 5d73abf2a77a090ca4c920ac99c8ec0e272398a9 (diff) | |
usb: gadget: f_uac2: convert to new function interface with backward compatibility
Converting uac2 to the new function interface requires converting
the USB uac2's function code and its users.
This patch converts the f_uac2.c to the new function interface.
The file is now compiled into a separate usb_f_uac2.ko module.
The old function interface is provided by means of a preprocessor
conditional directives. After all users are converted, the old interface
can be removed.
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/Makefile | 2 | ||||
| -rw-r--r-- | drivers/usb/gadget/function/f_uac2.c | 244 | ||||
| -rw-r--r-- | drivers/usb/gadget/function/u_uac2.h | 32 |
3 files changed, 238 insertions, 40 deletions
diff --git a/drivers/usb/gadget/function/Makefile b/drivers/usb/gadget/function/Makefile index 6d91f21b52a6..20775a87e51a 100644 --- a/drivers/usb/gadget/function/Makefile +++ b/drivers/usb/gadget/function/Makefile | |||
| @@ -32,3 +32,5 @@ usb_f_mass_storage-y := f_mass_storage.o storage_common.o | |||
| 32 | obj-$(CONFIG_USB_F_MASS_STORAGE)+= usb_f_mass_storage.o | 32 | obj-$(CONFIG_USB_F_MASS_STORAGE)+= usb_f_mass_storage.o |
| 33 | usb_f_fs-y := f_fs.o | 33 | usb_f_fs-y := f_fs.o |
| 34 | obj-$(CONFIG_USB_F_FS) += usb_f_fs.o | 34 | obj-$(CONFIG_USB_F_FS) += usb_f_fs.o |
| 35 | usb_f_uac2-y := f_uac2.o | ||
| 36 | obj-$(CONFIG_USB_F_UAC2) += usb_f_uac2.o | ||
diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c index 91615619c204..29b477fa2050 100644 --- a/drivers/usb/gadget/function/f_uac2.c +++ b/drivers/usb/gadget/function/f_uac2.c | |||
| @@ -20,6 +20,10 @@ | |||
| 20 | #include <sound/pcm.h> | 20 | #include <sound/pcm.h> |
| 21 | #include <sound/pcm_params.h> | 21 | #include <sound/pcm_params.h> |
| 22 | 22 | ||
| 23 | #include "u_uac2.h" | ||
| 24 | |||
| 25 | #ifdef USB_FUAC2_INCLUDED | ||
| 26 | |||
| 23 | /* Playback(USB-IN) Default Stereo - Fl/Fr */ | 27 | /* Playback(USB-IN) Default Stereo - Fl/Fr */ |
| 24 | static int p_chmask = 0x3; | 28 | static int p_chmask = 0x3; |
| 25 | module_param(p_chmask, uint, S_IRUGO); | 29 | module_param(p_chmask, uint, S_IRUGO); |
| @@ -50,6 +54,8 @@ static int c_ssize = 2; | |||
| 50 | module_param(c_ssize, uint, S_IRUGO); | 54 | module_param(c_ssize, uint, S_IRUGO); |
| 51 | MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)"); | 55 | MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)"); |
| 52 | 56 | ||
| 57 | #endif | ||
| 58 | |||
| 53 | /* Keep everyone on toes */ | 59 | /* Keep everyone on toes */ |
| 54 | #define USB_XFERS 2 | 60 | #define USB_XFERS 2 |
| 55 | 61 | ||
| @@ -340,6 +346,22 @@ static int uac2_pcm_open(struct snd_pcm_substream *substream) | |||
| 340 | { | 346 | { |
| 341 | struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream); | 347 | struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream); |
| 342 | struct snd_pcm_runtime *runtime = substream->runtime; | 348 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 349 | #ifndef USB_FUAC2_INCLUDED | ||
| 350 | struct audio_dev *audio_dev; | ||
| 351 | struct f_uac2_opts *opts; | ||
| 352 | int p_ssize, c_ssize; | ||
| 353 | int p_srate, c_srate; | ||
| 354 | int p_chmask, c_chmask; | ||
| 355 | |||
| 356 | audio_dev = uac2_to_agdev(uac2); | ||
| 357 | opts = container_of(audio_dev->func.fi, struct f_uac2_opts, func_inst); | ||
| 358 | p_ssize = opts->p_ssize; | ||
| 359 | c_ssize = opts->c_ssize; | ||
| 360 | p_srate = opts->p_srate; | ||
| 361 | c_srate = opts->c_srate; | ||
| 362 | p_chmask = opts->p_chmask; | ||
| 363 | c_chmask = opts->c_chmask; | ||
| 364 | #endif | ||
| 343 | 365 | ||
| 344 | runtime->hw = uac2_pcm_hardware; | 366 | runtime->hw = uac2_pcm_hardware; |
| 345 | 367 | ||
| @@ -409,7 +431,19 @@ static int snd_uac2_probe(struct platform_device *pdev) | |||
| 409 | struct snd_uac2_chip *uac2 = pdev_to_uac2(pdev); | 431 | struct snd_uac2_chip *uac2 = pdev_to_uac2(pdev); |
| 410 | struct snd_card *card; | 432 | struct snd_card *card; |
| 411 | struct snd_pcm *pcm; | 433 | struct snd_pcm *pcm; |
| 434 | #ifndef USB_FUAC2_INCLUDED | ||
| 435 | struct audio_dev *audio_dev; | ||
| 436 | struct f_uac2_opts *opts; | ||
| 437 | #endif | ||
| 412 | int err; | 438 | int err; |
| 439 | #ifndef USB_FUAC2_INCLUDED | ||
| 440 | int p_chmask, c_chmask; | ||
| 441 | |||
| 442 | audio_dev = uac2_to_agdev(uac2); | ||
| 443 | opts = container_of(audio_dev->func.fi, struct f_uac2_opts, func_inst); | ||
| 444 | p_chmask = opts->p_chmask; | ||
| 445 | c_chmask = opts->c_chmask; | ||
| 446 | #endif | ||
| 413 | 447 | ||
| 414 | /* Choose any slot, with no id */ | 448 | /* Choose any slot, with no id */ |
| 415 | err = snd_card_new(&pdev->dev, -1, NULL, THIS_MODULE, 0, &card); | 449 | err = snd_card_new(&pdev->dev, -1, NULL, THIS_MODULE, 0, &card); |
| @@ -917,7 +951,7 @@ free_ep(struct uac2_rtd_params *prm, struct usb_ep *ep) | |||
| 917 | "%s:%d Error!\n", __func__, __LINE__); | 951 | "%s:%d Error!\n", __func__, __LINE__); |
| 918 | } | 952 | } |
| 919 | 953 | ||
| 920 | static int __init | 954 | static int |
| 921 | afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) | 955 | afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) |
| 922 | { | 956 | { |
| 923 | struct audio_dev *agdev = func_to_agdev(fn); | 957 | struct audio_dev *agdev = func_to_agdev(fn); |
| @@ -925,8 +959,50 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) | |||
| 925 | struct usb_composite_dev *cdev = cfg->cdev; | 959 | struct usb_composite_dev *cdev = cfg->cdev; |
| 926 | struct usb_gadget *gadget = cdev->gadget; | 960 | struct usb_gadget *gadget = cdev->gadget; |
| 927 | struct uac2_rtd_params *prm; | 961 | struct uac2_rtd_params *prm; |
| 962 | #ifndef USB_FUAC2_INCLUDED | ||
| 963 | struct f_uac2_opts *uac2_opts; | ||
| 964 | #endif | ||
| 928 | int ret; | 965 | int ret; |
| 929 | 966 | ||
| 967 | #ifndef USB_FUAC2_INCLUDED | ||
| 968 | uac2_opts = container_of(fn->fi, struct f_uac2_opts, func_inst); | ||
| 969 | #endif | ||
| 970 | |||
| 971 | ret = usb_string_ids_tab(cfg->cdev, strings_fn); | ||
| 972 | if (ret) | ||
| 973 | return ret; | ||
| 974 | iad_desc.iFunction = strings_fn[STR_ASSOC].id; | ||
| 975 | std_ac_if_desc.iInterface = strings_fn[STR_IF_CTRL].id; | ||
| 976 | in_clk_src_desc.iClockSource = strings_fn[STR_CLKSRC_IN].id; | ||
| 977 | out_clk_src_desc.iClockSource = strings_fn[STR_CLKSRC_OUT].id; | ||
| 978 | usb_out_it_desc.iTerminal = strings_fn[STR_USB_IT].id; | ||
| 979 | io_in_it_desc.iTerminal = strings_fn[STR_IO_IT].id; | ||
| 980 | usb_in_ot_desc.iTerminal = strings_fn[STR_USB_OT].id; | ||
| 981 | io_out_ot_desc.iTerminal = strings_fn[STR_IO_OT].id; | ||
| 982 | std_as_out_if0_desc.iInterface = strings_fn[STR_AS_OUT_ALT0].id; | ||
| 983 | std_as_out_if1_desc.iInterface = strings_fn[STR_AS_OUT_ALT1].id; | ||
| 984 | std_as_in_if0_desc.iInterface = strings_fn[STR_AS_IN_ALT0].id; | ||
| 985 | std_as_in_if1_desc.iInterface = strings_fn[STR_AS_IN_ALT1].id; | ||
| 986 | |||
| 987 | #ifndef USB_FUAC2_INCLUDED | ||
| 988 | /* Initialize the configurable parameters */ | ||
| 989 | usb_out_it_desc.bNrChannels = num_channels(uac2_opts->c_chmask); | ||
| 990 | usb_out_it_desc.bmChannelConfig = cpu_to_le32(uac2_opts->c_chmask); | ||
| 991 | io_in_it_desc.bNrChannels = num_channels(uac2_opts->p_chmask); | ||
| 992 | io_in_it_desc.bmChannelConfig = cpu_to_le32(uac2_opts->p_chmask); | ||
| 993 | as_out_hdr_desc.bNrChannels = num_channels(uac2_opts->c_chmask); | ||
| 994 | as_out_hdr_desc.bmChannelConfig = cpu_to_le32(uac2_opts->c_chmask); | ||
| 995 | as_in_hdr_desc.bNrChannels = num_channels(uac2_opts->p_chmask); | ||
| 996 | as_in_hdr_desc.bmChannelConfig = cpu_to_le32(uac2_opts->p_chmask); | ||
| 997 | as_out_fmt1_desc.bSubslotSize = uac2_opts->c_ssize; | ||
| 998 | as_out_fmt1_desc.bBitResolution = uac2_opts->c_ssize * 8; | ||
| 999 | as_in_fmt1_desc.bSubslotSize = uac2_opts->p_ssize; | ||
| 1000 | as_in_fmt1_desc.bBitResolution = uac2_opts->p_ssize * 8; | ||
| 1001 | |||
| 1002 | snprintf(clksrc_in, sizeof(clksrc_in), "%uHz", uac2_opts->p_srate); | ||
| 1003 | snprintf(clksrc_out, sizeof(clksrc_out), "%uHz", uac2_opts->c_srate); | ||
| 1004 | #endif | ||
| 1005 | |||
| 930 | ret = usb_interface_id(cfg, fn); | 1006 | ret = usb_interface_id(cfg, fn); |
| 931 | if (ret < 0) { | 1007 | if (ret < 0) { |
| 932 | dev_err(&uac2->pdev.dev, | 1008 | dev_err(&uac2->pdev.dev, |
| @@ -1018,28 +1094,6 @@ err: | |||
| 1018 | return -EINVAL; | 1094 | return -EINVAL; |
| 1019 | } | 1095 | } |
| 1020 | 1096 | ||
| 1021 | static void | ||
| 1022 | afunc_unbind(struct usb_configuration *cfg, struct usb_function *fn) | ||
| 1023 | { | ||
| 1024 | struct audio_dev *agdev = func_to_agdev(fn); | ||
| 1025 | struct uac2_rtd_params *prm; | ||
| 1026 | |||
| 1027 | alsa_uac2_exit(agdev); | ||
| 1028 | |||
| 1029 | prm = &agdev->uac2.p_prm; | ||
| 1030 | kfree(prm->rbuf); | ||
| 1031 | |||
| 1032 | prm = &agdev->uac2.c_prm; | ||
| 1033 | kfree(prm->rbuf); | ||
| 1034 | usb_free_all_descriptors(fn); | ||
| 1035 | |||
| 1036 | if (agdev->in_ep) | ||
| 1037 | agdev->in_ep->driver_data = NULL; | ||
| 1038 | if (agdev->out_ep) | ||
| 1039 | agdev->out_ep->driver_data = NULL; | ||
| 1040 | kfree(agdev); | ||
| 1041 | } | ||
| 1042 | |||
| 1043 | static int | 1097 | static int |
| 1044 | afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt) | 1098 | afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt) |
| 1045 | { | 1099 | { |
| @@ -1163,12 +1217,22 @@ in_rq_cur(struct usb_function *fn, const struct usb_ctrlrequest *cr) | |||
| 1163 | struct usb_request *req = fn->config->cdev->req; | 1217 | struct usb_request *req = fn->config->cdev->req; |
| 1164 | struct audio_dev *agdev = func_to_agdev(fn); | 1218 | struct audio_dev *agdev = func_to_agdev(fn); |
| 1165 | struct snd_uac2_chip *uac2 = &agdev->uac2; | 1219 | struct snd_uac2_chip *uac2 = &agdev->uac2; |
| 1220 | #ifndef USB_FUAC2_INCLUDED | ||
| 1221 | struct f_uac2_opts *opts; | ||
| 1222 | #endif | ||
| 1166 | u16 w_length = le16_to_cpu(cr->wLength); | 1223 | u16 w_length = le16_to_cpu(cr->wLength); |
| 1167 | u16 w_index = le16_to_cpu(cr->wIndex); | 1224 | u16 w_index = le16_to_cpu(cr->wIndex); |
| 1168 | u16 w_value = le16_to_cpu(cr->wValue); | 1225 | u16 w_value = le16_to_cpu(cr->wValue); |
| 1169 | u8 entity_id = (w_index >> 8) & 0xff; | 1226 | u8 entity_id = (w_index >> 8) & 0xff; |
| 1170 | u8 control_selector = w_value >> 8; | 1227 | u8 control_selector = w_value >> 8; |
| 1171 | int value = -EOPNOTSUPP; | 1228 | int value = -EOPNOTSUPP; |
| 1229 | #ifndef USB_FUAC2_INCLUDED | ||
| 1230 | int p_srate, c_srate; | ||
| 1231 | |||
| 1232 | opts = container_of(agdev->func.fi, struct f_uac2_opts, func_inst); | ||
| 1233 | p_srate = opts->p_srate; | ||
| 1234 | c_srate = opts->c_srate; | ||
| 1235 | #endif | ||
| 1172 | 1236 | ||
| 1173 | if (control_selector == UAC2_CS_CONTROL_SAM_FREQ) { | 1237 | if (control_selector == UAC2_CS_CONTROL_SAM_FREQ) { |
| 1174 | struct cntrl_cur_lay3 c; | 1238 | struct cntrl_cur_lay3 c; |
| @@ -1198,6 +1262,9 @@ in_rq_range(struct usb_function *fn, const struct usb_ctrlrequest *cr) | |||
| 1198 | struct usb_request *req = fn->config->cdev->req; | 1262 | struct usb_request *req = fn->config->cdev->req; |
| 1199 | struct audio_dev *agdev = func_to_agdev(fn); | 1263 | struct audio_dev *agdev = func_to_agdev(fn); |
| 1200 | struct snd_uac2_chip *uac2 = &agdev->uac2; | 1264 | struct snd_uac2_chip *uac2 = &agdev->uac2; |
| 1265 | #ifndef USB_FUAC2_INCLUDED | ||
| 1266 | struct f_uac2_opts *opts; | ||
| 1267 | #endif | ||
| 1201 | u16 w_length = le16_to_cpu(cr->wLength); | 1268 | u16 w_length = le16_to_cpu(cr->wLength); |
| 1202 | u16 w_index = le16_to_cpu(cr->wIndex); | 1269 | u16 w_index = le16_to_cpu(cr->wIndex); |
| 1203 | u16 w_value = le16_to_cpu(cr->wValue); | 1270 | u16 w_value = le16_to_cpu(cr->wValue); |
| @@ -1205,6 +1272,13 @@ in_rq_range(struct usb_function *fn, const struct usb_ctrlrequest *cr) | |||
| 1205 | u8 control_selector = w_value >> 8; | 1272 | u8 control_selector = w_value >> 8; |
| 1206 | struct cntrl_range_lay3 r; | 1273 | struct cntrl_range_lay3 r; |
| 1207 | int value = -EOPNOTSUPP; | 1274 | int value = -EOPNOTSUPP; |
| 1275 | #ifndef USB_FUAC2_INCLUDED | ||
| 1276 | int p_srate, c_srate; | ||
| 1277 | |||
| 1278 | opts = container_of(agdev->func.fi, struct f_uac2_opts, func_inst); | ||
| 1279 | p_srate = opts->p_srate; | ||
| 1280 | c_srate = opts->c_srate; | ||
| 1281 | #endif | ||
| 1208 | 1282 | ||
| 1209 | if (control_selector == UAC2_CS_CONTROL_SAM_FREQ) { | 1283 | if (control_selector == UAC2_CS_CONTROL_SAM_FREQ) { |
| 1210 | if (entity_id == USB_IN_CLK_ID) | 1284 | if (entity_id == USB_IN_CLK_ID) |
| @@ -1308,6 +1382,30 @@ afunc_setup(struct usb_function *fn, const struct usb_ctrlrequest *cr) | |||
| 1308 | return value; | 1382 | return value; |
| 1309 | } | 1383 | } |
| 1310 | 1384 | ||
| 1385 | #ifdef USB_FUAC2_INCLUDED | ||
| 1386 | |||
| 1387 | static void | ||
| 1388 | old_afunc_unbind(struct usb_configuration *cfg, struct usb_function *fn) | ||
| 1389 | { | ||
| 1390 | struct audio_dev *agdev = func_to_agdev(fn); | ||
| 1391 | struct uac2_rtd_params *prm; | ||
| 1392 | |||
| 1393 | alsa_uac2_exit(agdev); | ||
| 1394 | |||
| 1395 | prm = &agdev->uac2.p_prm; | ||
| 1396 | kfree(prm->rbuf); | ||
| 1397 | |||
| 1398 | prm = &agdev->uac2.c_prm; | ||
| 1399 | kfree(prm->rbuf); | ||
| 1400 | usb_free_all_descriptors(fn); | ||
| 1401 | |||
| 1402 | if (agdev->in_ep) | ||
| 1403 | agdev->in_ep->driver_data = NULL; | ||
| 1404 | if (agdev->out_ep) | ||
| 1405 | agdev->out_ep->driver_data = NULL; | ||
| 1406 | kfree(agdev); | ||
| 1407 | } | ||
| 1408 | |||
| 1311 | static int audio_bind_config(struct usb_configuration *cfg) | 1409 | static int audio_bind_config(struct usb_configuration *cfg) |
| 1312 | { | 1410 | { |
| 1313 | struct audio_dev *agdev; | 1411 | struct audio_dev *agdev; |
| @@ -1317,26 +1415,10 @@ static int audio_bind_config(struct usb_configuration *cfg) | |||
| 1317 | if (agdev == NULL) | 1415 | if (agdev == NULL) |
| 1318 | return -ENOMEM; | 1416 | return -ENOMEM; |
| 1319 | 1417 | ||
| 1320 | res = usb_string_ids_tab(cfg->cdev, strings_fn); | ||
| 1321 | if (res) | ||
| 1322 | return res; | ||
| 1323 | iad_desc.iFunction = strings_fn[STR_ASSOC].id; | ||
| 1324 | std_ac_if_desc.iInterface = strings_fn[STR_IF_CTRL].id; | ||
| 1325 | in_clk_src_desc.iClockSource = strings_fn[STR_CLKSRC_IN].id; | ||
| 1326 | out_clk_src_desc.iClockSource = strings_fn[STR_CLKSRC_OUT].id; | ||
| 1327 | usb_out_it_desc.iTerminal = strings_fn[STR_USB_IT].id; | ||
| 1328 | io_in_it_desc.iTerminal = strings_fn[STR_IO_IT].id; | ||
| 1329 | usb_in_ot_desc.iTerminal = strings_fn[STR_USB_OT].id; | ||
| 1330 | io_out_ot_desc.iTerminal = strings_fn[STR_IO_OT].id; | ||
| 1331 | std_as_out_if0_desc.iInterface = strings_fn[STR_AS_OUT_ALT0].id; | ||
| 1332 | std_as_out_if1_desc.iInterface = strings_fn[STR_AS_OUT_ALT1].id; | ||
| 1333 | std_as_in_if0_desc.iInterface = strings_fn[STR_AS_IN_ALT0].id; | ||
| 1334 | std_as_in_if1_desc.iInterface = strings_fn[STR_AS_IN_ALT1].id; | ||
| 1335 | |||
| 1336 | agdev->func.name = "uac2_func"; | 1418 | agdev->func.name = "uac2_func"; |
| 1337 | agdev->func.strings = fn_strings; | 1419 | agdev->func.strings = fn_strings; |
| 1338 | agdev->func.bind = afunc_bind; | 1420 | agdev->func.bind = afunc_bind; |
| 1339 | agdev->func.unbind = afunc_unbind; | 1421 | agdev->func.unbind = old_afunc_unbind; |
| 1340 | agdev->func.set_alt = afunc_set_alt; | 1422 | agdev->func.set_alt = afunc_set_alt; |
| 1341 | agdev->func.get_alt = afunc_get_alt; | 1423 | agdev->func.get_alt = afunc_get_alt; |
| 1342 | agdev->func.disable = afunc_disable; | 1424 | agdev->func.disable = afunc_disable; |
| @@ -1365,3 +1447,85 @@ static int audio_bind_config(struct usb_configuration *cfg) | |||
| 1365 | 1447 | ||
| 1366 | return res; | 1448 | return res; |
| 1367 | } | 1449 | } |
| 1450 | |||
| 1451 | #else | ||
| 1452 | |||
| 1453 | static void afunc_free_inst(struct usb_function_instance *f) | ||
| 1454 | { | ||
| 1455 | struct f_uac2_opts *opts; | ||
| 1456 | |||
| 1457 | opts = container_of(f, struct f_uac2_opts, func_inst); | ||
| 1458 | kfree(opts); | ||
| 1459 | } | ||
| 1460 | |||
| 1461 | static struct usb_function_instance *afunc_alloc_inst(void) | ||
| 1462 | { | ||
| 1463 | struct f_uac2_opts *opts; | ||
| 1464 | |||
| 1465 | opts = kzalloc(sizeof(*opts), GFP_KERNEL); | ||
| 1466 | if (!opts) | ||
| 1467 | return ERR_PTR(-ENOMEM); | ||
| 1468 | |||
| 1469 | opts->func_inst.free_func_inst = afunc_free_inst; | ||
| 1470 | |||
| 1471 | return &opts->func_inst; | ||
| 1472 | } | ||
| 1473 | |||
| 1474 | static void afunc_free(struct usb_function *f) | ||
| 1475 | { | ||
| 1476 | struct audio_dev *agdev; | ||
| 1477 | |||
| 1478 | agdev = func_to_agdev(f); | ||
| 1479 | kfree(agdev); | ||
| 1480 | } | ||
| 1481 | |||
| 1482 | static void afunc_unbind(struct usb_configuration *c, struct usb_function *f) | ||
| 1483 | { | ||
| 1484 | struct audio_dev *agdev = func_to_agdev(f); | ||
| 1485 | struct uac2_rtd_params *prm; | ||
| 1486 | |||
| 1487 | alsa_uac2_exit(agdev); | ||
| 1488 | |||
| 1489 | prm = &agdev->uac2.p_prm; | ||
| 1490 | kfree(prm->rbuf); | ||
| 1491 | |||
| 1492 | prm = &agdev->uac2.c_prm; | ||
| 1493 | kfree(prm->rbuf); | ||
| 1494 | usb_free_all_descriptors(f); | ||
| 1495 | |||
| 1496 | if (agdev->in_ep) | ||
| 1497 | agdev->in_ep->driver_data = NULL; | ||
| 1498 | if (agdev->out_ep) | ||
| 1499 | agdev->out_ep->driver_data = NULL; | ||
| 1500 | } | ||
| 1501 | |||
| 1502 | struct usb_function *afunc_alloc(struct usb_function_instance *fi) | ||
| 1503 | { | ||
| 1504 | struct audio_dev *agdev; | ||
| 1505 | struct f_uac2_opts *opts; | ||
| 1506 | |||
| 1507 | agdev = kzalloc(sizeof(*agdev), GFP_KERNEL); | ||
| 1508 | if (agdev == NULL) | ||
| 1509 | return ERR_PTR(-ENOMEM); | ||
| 1510 | |||
| 1511 | opts = container_of(fi, struct f_uac2_opts, func_inst); | ||
| 1512 | |||
| 1513 | agdev->func.name = "uac2_func"; | ||
| 1514 | agdev->func.strings = fn_strings; | ||
| 1515 | agdev->func.bind = afunc_bind; | ||
| 1516 | agdev->func.unbind = afunc_unbind; | ||
| 1517 | agdev->func.set_alt = afunc_set_alt; | ||
| 1518 | agdev->func.get_alt = afunc_get_alt; | ||
| 1519 | agdev->func.disable = afunc_disable; | ||
| 1520 | agdev->func.setup = afunc_setup; | ||
| 1521 | agdev->func.free_func = afunc_free; | ||
| 1522 | |||
| 1523 | return &agdev->func; | ||
| 1524 | } | ||
| 1525 | |||
| 1526 | DECLARE_USB_FUNCTION_INIT(uac2, afunc_alloc_inst, afunc_alloc); | ||
| 1527 | MODULE_LICENSE("GPL"); | ||
| 1528 | MODULE_AUTHOR("Yadwinder Singh"); | ||
| 1529 | MODULE_AUTHOR("Jaswinder Singh"); | ||
| 1530 | |||
| 1531 | #endif | ||
diff --git a/drivers/usb/gadget/function/u_uac2.h b/drivers/usb/gadget/function/u_uac2.h new file mode 100644 index 000000000000..290b83af1b69 --- /dev/null +++ b/drivers/usb/gadget/function/u_uac2.h | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | /* | ||
| 2 | * u_uac2.h | ||
| 3 | * | ||
| 4 | * Utility definitions for UAC2 function | ||
| 5 | * | ||
| 6 | * Copyright (c) 2014 Samsung Electronics Co., Ltd. | ||
| 7 | * http://www.samsung.com | ||
| 8 | * | ||
| 9 | * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify | ||
| 12 | * it under the terms of the GNU General Public License version 2 as | ||
| 13 | * published by the Free Software Foundation. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #ifndef U_UAC2_H | ||
| 17 | #define U_UAC2_H | ||
| 18 | |||
| 19 | #include <linux/usb/composite.h> | ||
| 20 | |||
| 21 | struct f_uac2_opts { | ||
| 22 | struct usb_function_instance func_inst; | ||
| 23 | int p_chmask; | ||
| 24 | int p_srate; | ||
| 25 | int p_ssize; | ||
| 26 | int c_chmask; | ||
| 27 | int c_srate; | ||
| 28 | int c_ssize; | ||
| 29 | bool bound; | ||
| 30 | }; | ||
| 31 | |||
| 32 | #endif | ||
