Initial copy from audio-hal-ak4953
[platform/adaptation/nexell/audio-hal-alc5658.git] / tizen-audio-impl-ucm.c
1 /*
2  * audio-hal
3  *
4  * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #ifdef ALSA_UCM_DEBUG_TIME
28 #include <sys/time.h>
29 #include <time.h>
30 #endif
31
32 #include "tizen-audio-internal.h"
33
34 #ifdef ALSA_UCM_DEBUG_TIME
35 #define SND_USE_CASE_SET __set_use_case_with_time
36 #else
37 #define SND_USE_CASE_SET snd_use_case_set
38 #endif
39
40 #define UCM_PREFIX_CURRENT   ">>> UCM current"
41 #define UCM_PREFIX_REQUESTED "> UCM requested"
42 #define UCM_PREFIX_CHANGED   "<<< UCM changed"
43
44 #define DUMP_LEN 512
45
46 static void __dump_use_case(const char* prefix, const char *verb, const char *devices[], int dev_count, const char *modifiers[], int mod_count)
47 {
48     int i;
49     dump_data_t* dump = NULL;
50
51     if (!(dump = _audio_dump_new(DUMP_LEN))) {
52         AUDIO_LOG_ERROR("Failed to create dump string...");
53         return;
54     }
55
56     /* Verb */
57     _audio_dump_add_str(dump, "Verb [ %s ] Devices [ ", verb ? verb : AUDIO_USE_CASE_VERB_INACTIVE);
58
59     /* Devices */
60     if (devices) {
61         for (i = 0; i < dev_count; i++) {
62             _audio_dump_add_str(dump, (i != dev_count - 1) ? "%s, " : "%s", devices[i]);
63         }
64     }
65     _audio_dump_add_str(dump, " ] Modifier [ ");
66
67     /* Modifiers */
68     if (modifiers) {
69         for (i = 0; i < mod_count; i++) {
70             _audio_dump_add_str(dump, (i != mod_count - 1) ? "%s, " : "%s", modifiers[i]);
71         }
72     }
73     _audio_dump_add_str(dump, " ]");
74
75     AUDIO_LOG_INFO("TEST %s : %s", prefix, _audio_dump_get_str(dump));
76
77     _audio_dump_free(dump);
78 }
79
80 #ifdef ALSA_UCM_DEBUG_TIME
81 static inline int __set_use_case_with_time(snd_use_case_mgr_t *uc_mgr, const char *identifier, const char *value)
82 {
83     int ret = 0;
84     struct timeval t_start, t_stop;
85     unsigned long long t_diff = 0;
86
87     gettimeofday(&t_start, NULL);
88     ret = snd_use_case_set(uc_mgr, identifier, value);
89     gettimeofday(&t_stop, NULL);
90     if (t_start.tv_sec < t_stop.tv_sec)
91         t_diff = (t_stop.tv_sec - t_start.tv_sec) * 1000000;
92     t_diff += (t_stop.tv_usec - t_start.tv_usec);
93     AUDIO_LOG_DEBUG("identifier %s value %s takes %lluusec", identifier, value, t_diff);
94
95     return ret;
96 }
97 #endif
98
99 audio_return_t _ucm_init(audio_hal_t *ah)
100 {
101     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
102
103     snd_use_case_mgr_open(&ah->ucm.uc_mgr, ALSA_DEFAULT_CARD);
104
105     if (!ah->ucm.uc_mgr) {
106         AUDIO_LOG_ERROR("uc_mgr open failed");
107         return AUDIO_ERR_RESOURCE;
108     }
109     return AUDIO_RET_OK;
110 }
111
112 audio_return_t _ucm_deinit(audio_hal_t *ah)
113 {
114     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
115     AUDIO_RETURN_VAL_IF_FAIL(ah->ucm.uc_mgr, AUDIO_ERR_PARAMETER);
116
117     if (ah->ucm.uc_mgr) {
118         snd_use_case_mgr_close(ah->ucm.uc_mgr);
119         ah->ucm.uc_mgr = NULL;
120     }
121
122     return AUDIO_RET_OK;
123 }
124
125 /* UCM sequence
126     1) If verb is null or verb is not changed
127     1-1) If device is changed
128          (If there is request for same device, it will be ignored)
129          -> Set "Inactive" verb, disable modifiers & devices, set current verb again, enable devices & modifiers
130             (playback/capture device will be enabled again if there is no request for playback/capture device)
131     1-2) If device is not changed
132      1-2-1) If modifier is changed
133             (If there is request for same modifier, it will be ignored)
134             -> Disable modifiers, enable modifiers
135    2) If verb is changed
136       -> Reset, set new verb, enable devices & modifiers
137  */
138 audio_return_t _ucm_set_use_case(audio_hal_t *ah, const char *verb, const char *devices[], const char *modifiers[])
139 {
140     audio_return_t audio_ret = AUDIO_RET_OK;
141     int is_verb_changed = 0, is_dev_changed = 0, is_mod_changed = 0;
142     const char *old_verb = NULL, **old_dev_list = NULL, **old_mod_list = NULL;
143     int old_dev_count = 0, dev_count = 0;
144     int old_mod_count = 0, mod_count = 0;
145     const char **dis_dev_list = NULL, **ena_dev_list = NULL;
146     const char **dis_mod_list = NULL, **ena_mod_list = NULL;
147     int dis_dev_count = 0, ena_dev_count = 0;
148     int dis_mod_count = 0, ena_mod_count = 0;
149     int i = 0, j = 0;
150
151     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
152     AUDIO_RETURN_VAL_IF_FAIL(ah->ucm.uc_mgr, AUDIO_ERR_PARAMETER);
153     AUDIO_RETURN_VAL_IF_FAIL(verb, AUDIO_ERR_PARAMETER);
154
155     snd_use_case_get(ah->ucm.uc_mgr, "_verb", &old_verb);
156     old_dev_count = snd_use_case_get_list(ah->ucm.uc_mgr, "_enadevs", &old_dev_list);
157     old_mod_count = snd_use_case_get_list(ah->ucm.uc_mgr, "_enamods", &old_mod_list);
158     __dump_use_case(UCM_PREFIX_CURRENT, old_verb, old_dev_list, old_dev_count, old_mod_list, old_mod_count);
159
160     if (devices) {
161         for (dev_count = 0; devices[dev_count]; dev_count++);
162     }
163     if (modifiers) {
164         for (mod_count = 0; modifiers[mod_count]; mod_count++);
165     }
166
167     __dump_use_case(UCM_PREFIX_REQUESTED, verb, devices, dev_count, modifiers, mod_count);
168
169     if (old_verb && streq(verb, old_verb)) {
170         AUDIO_LOG_DEBUG("current verb and new verb is same. No need to change verb, disable devices explicitely");
171
172         if (old_dev_count > 0) {
173             dis_dev_list = (const char **)malloc(sizeof(const char *) * old_dev_count);
174             for (i = 0; i < old_dev_count; i++) {
175                 dis_dev_list[i] = NULL;
176             }
177         }
178         if (dev_count > 0) {
179             ena_dev_list = (const char **)malloc(sizeof(const char *) * dev_count);
180             for (i = 0; i < dev_count; i++) {
181                 ena_dev_list[i] = NULL;
182             }
183         }
184         if (old_mod_count > 0) {
185             dis_mod_list = (const char **)malloc(sizeof(const char *) * old_mod_count);
186             for (i = 0; i < old_mod_count; i++) {
187                 dis_mod_list[i] = NULL;
188             }
189         }
190         if (mod_count > 0) {
191             ena_mod_list = (const char **)malloc(sizeof(const char *) * mod_count);
192             for (i = 0; i < mod_count; i++) {
193                 ena_mod_list[i] = NULL;
194             }
195         }
196
197         /* update disable modifiers list which are not present in new modifier list */
198         for (i = 0; i < old_mod_count; i++) {
199             int need_disable_mod = 1;
200
201             for (j = 0; j < mod_count; j++) {
202                 if (streq(old_mod_list[i], modifiers[j])) {
203                     need_disable_mod = 0;
204                     break;
205                 }
206             }
207             if (need_disable_mod) {
208                 if (is_mod_changed == 0)
209                     is_mod_changed = 1;
210                 dis_mod_list[dis_mod_count++] = old_mod_list[i];
211             }
212         }
213
214         /* update disable devices list which are not present in new device list */
215         for (i = 0; i < old_dev_count; i++) {
216             int need_disable_dev = 1;
217
218             for (j = 0; j < dev_count; j++) {
219                 if (streq(old_dev_list[i], devices[j])) {
220                     need_disable_dev = 0;
221                     break;
222                 }
223             }
224             if (need_disable_dev) {
225                 if (is_dev_changed == 0)
226                     is_dev_changed = 1;
227                 dis_dev_list[dis_dev_count++] = old_dev_list[i];
228             }
229         }
230
231         /* update enable devices list which are not present in old device list */
232         for (i = 0; i < dev_count; i++) {
233             int need_enable_dev = 1;
234
235             for (j = 0; j < old_dev_count; j++) {
236                 if (streq(devices[i], old_dev_list[j])) {
237                     need_enable_dev = 0;
238                     break;
239                 }
240             }
241             if (need_enable_dev) {
242                 if (is_dev_changed == 0)
243                     is_dev_changed = 1;
244                 ena_dev_list[ena_dev_count++] = devices[i];
245             }
246         }
247
248         /* update enable modifiers list which are not present in old modifier list */
249         for (i = 0; i < mod_count; i++) {
250             int need_enable_mod = 1;
251
252             for (j = 0; j < old_mod_count; j++) {
253                 if (streq(modifiers[i], old_mod_list[j])) {
254                     need_enable_mod = 0;
255                     break;
256                 }
257             }
258             if (need_enable_mod) {
259                 if (is_mod_changed == 0)
260                     is_mod_changed = 1;
261                 ena_mod_list[ena_mod_count++] = modifiers[i];
262             }
263         }
264
265         /* disable modifiers */
266         for (i = 0; i < dis_mod_count; i++) {
267             AUDIO_LOG_INFO("Disable modifier : %s", dis_mod_list[i]);
268             if (snd_use_case_set(ah->ucm.uc_mgr, "_dismod", dis_mod_list[i]) < 0)
269                 AUDIO_LOG_ERROR("disable %s modifier failed", dis_mod_list[i]);
270         }
271
272         /* disable devices */
273         for (i = 0; i < dis_dev_count; i++) {
274             AUDIO_LOG_INFO("Disable device : %s", dis_dev_list[i]);
275             if (snd_use_case_set(ah->ucm.uc_mgr, "_disdev", dis_dev_list[i]) < 0)
276                 AUDIO_LOG_ERROR("disable %s device failed", dis_dev_list[i]);
277         }
278
279         /* enable devices */
280         for (i = 0; i < ena_dev_count; i++) {
281             AUDIO_LOG_INFO("Enable device : %s", ena_dev_list[i]);
282             if (snd_use_case_set(ah->ucm.uc_mgr, "_enadev", ena_dev_list[i]) < 0)
283                 AUDIO_LOG_ERROR("enable %s device failed", ena_dev_list[i]);
284         }
285
286         /* enable modifiers */
287         for (i = 0; i < ena_mod_count; i++) {
288             AUDIO_LOG_INFO("Enable modifier : %s", ena_mod_list[i]);
289             if (snd_use_case_set(ah->ucm.uc_mgr, "_enamod", ena_mod_list[i]) < 0)
290                 AUDIO_LOG_ERROR("enable %s modifier failed", ena_mod_list[i]);
291         }
292     } else {
293         is_verb_changed = 1;
294
295         AUDIO_LOG_DEBUG("Setting new verb: %s", verb);
296         /* set new verb */
297         if (snd_use_case_set(ah->ucm.uc_mgr, "_verb", verb) < 0) {
298             AUDIO_LOG_ERROR("Setting verb %s failed", verb);
299             audio_ret = AUDIO_ERR_UNDEFINED;
300             goto exit;
301         }
302         /* enable devices */
303         for (i = 0; i < dev_count; i++) {
304             AUDIO_LOG_DEBUG("Enable device : %s", devices[i]);
305             if (snd_use_case_set(ah->ucm.uc_mgr, "_enadev", devices[i]) < 0)
306                 AUDIO_LOG_ERROR("Enable %s device failed", devices[i]);
307         }
308         /* enable modifiers */
309         for (i = 0; i < mod_count; i++) {
310             AUDIO_LOG_DEBUG("Enable modifier : %s", modifiers[i]);
311             if (snd_use_case_set(ah->ucm.uc_mgr, "_enamod", modifiers[i]) < 0)
312                 AUDIO_LOG_ERROR("Enable %s modifier failed", modifiers[i]);
313         }
314     }
315
316 exit:
317     if (old_verb)
318         free((void *)old_verb);
319     if (old_dev_list)
320         snd_use_case_free_list(old_dev_list, old_dev_count);
321     if (old_mod_list)
322         snd_use_case_free_list(old_mod_list, old_mod_count);
323     if (dis_dev_list)
324         free((void *)dis_dev_list);
325     if (ena_dev_list)
326         free((void *)ena_dev_list);
327     if (dis_mod_list)
328         free((void *)dis_mod_list);
329     if (ena_mod_list)
330         free((void *)ena_mod_list);
331
332     if (is_verb_changed == 1 || is_dev_changed == 1 || is_mod_changed == 1) {
333         const char *new_verb = NULL, **new_dev_list = NULL, **new_mod_list = NULL;
334         int new_dev_count = 0, new_mod_count = 0;
335
336         snd_use_case_get(ah->ucm.uc_mgr, "_verb", &new_verb);
337         new_dev_count = snd_use_case_get_list(ah->ucm.uc_mgr, "_enadevs", &new_dev_list);
338         new_mod_count = snd_use_case_get_list(ah->ucm.uc_mgr, "_enamods", &new_mod_list);
339         __dump_use_case(UCM_PREFIX_CHANGED, new_verb, new_dev_list, new_dev_count, new_mod_list, new_mod_count);
340
341         if (new_verb)
342             free((void *)new_verb);
343         if (new_dev_list)
344             snd_use_case_free_list(new_dev_list, new_dev_count);
345         if (new_mod_list)
346             snd_use_case_free_list(new_mod_list, new_mod_count);
347     }
348
349     return audio_ret;
350 }
351
352 audio_return_t _ucm_set_devices(audio_hal_t *ah, const char *verb, const char *devices[])
353 {
354     audio_return_t audio_ret = AUDIO_RET_OK;
355     int is_verb_changed = 0, is_dev_changed = 0;
356     const char *old_verb = NULL, **old_dev_list = NULL;
357     int old_dev_count = 0, dev_count = 0;
358     const char **dis_dev_list = NULL, **ena_dev_list = NULL;
359     int dis_dev_count = 0, ena_dev_count = 0;
360     int i = 0, j = 0;
361
362     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
363     AUDIO_RETURN_VAL_IF_FAIL(ah->ucm.uc_mgr, AUDIO_ERR_PARAMETER);
364     AUDIO_RETURN_VAL_IF_FAIL(verb, AUDIO_ERR_PARAMETER);
365     AUDIO_RETURN_VAL_IF_FAIL(devices, AUDIO_ERR_PARAMETER);
366
367     snd_use_case_get(ah->ucm.uc_mgr, "_verb", &old_verb);
368     old_dev_count = snd_use_case_get_list(ah->ucm.uc_mgr, "_enadevs", &old_dev_list);
369     __dump_use_case(UCM_PREFIX_CURRENT, old_verb, old_dev_list, old_dev_count, NULL, 0);
370
371     if (devices) {
372         for (dev_count = 0; devices[dev_count]; dev_count++);
373     }
374
375     __dump_use_case(UCM_PREFIX_REQUESTED, verb, devices, dev_count, NULL, 0);
376
377     if (old_verb && streq(verb, old_verb)) {
378         AUDIO_LOG_DEBUG("current verb and new verb is same. No need to change verb, disable devices explicitely");
379
380         if (old_dev_count > 0) {
381             dis_dev_list = (const char **)malloc(sizeof(const char *) * old_dev_count);
382             for (i = 0; i < old_dev_count; i++) {
383                 dis_dev_list[i] = NULL;
384             }
385         }
386         if (dev_count > 0) {
387             ena_dev_list = (const char **)malloc(sizeof(const char *) * dev_count);
388             for (i = 0; i < dev_count; i++) {
389                 ena_dev_list[i] = NULL;
390             }
391         }
392
393         /* update disable devices list which are not present in new device list */
394         for (i = 0; i < old_dev_count; i++) {
395             int need_disable_dev = 1;
396
397             for (j = 0; j < dev_count; j++) {
398                 if (streq(old_dev_list[i], devices[j])) {
399                     need_disable_dev = 0;
400                     break;
401                 }
402             }
403             if (need_disable_dev) {
404                 if (is_dev_changed == 0)
405                     is_dev_changed = 1;
406                 dis_dev_list[dis_dev_count++] = old_dev_list[i];
407             }
408         }
409
410         /* update enable devices list which are not present in old device list */
411         for (i = 0; i < dev_count; i++) {
412             int need_enable_dev = 1;
413
414             for (j = 0; j < old_dev_count; j++) {
415                 if (streq(devices[i], old_dev_list[j])) {
416                     need_enable_dev = 0;
417                     break;
418                 }
419             }
420             if (need_enable_dev) {
421                 if (is_dev_changed == 0)
422                     is_dev_changed = 1;
423                 ena_dev_list[ena_dev_count++] = devices[i];
424             }
425         }
426
427         /* disable devices */
428         for (i = 0; i < dis_dev_count; i++) {
429             AUDIO_LOG_INFO("Disable device : %s", dis_dev_list[i]);
430             if (snd_use_case_set(ah->ucm.uc_mgr, "_disdev", dis_dev_list[i]) < 0)
431                 AUDIO_LOG_ERROR("disable %s device failed", dis_dev_list[i]);
432         }
433
434         /* enable devices */
435         for (i = 0; i < ena_dev_count; i++) {
436             AUDIO_LOG_INFO("Enable device : %s", ena_dev_list[i]);
437             if (snd_use_case_set(ah->ucm.uc_mgr, "_enadev", ena_dev_list[i]) < 0)
438                 AUDIO_LOG_ERROR("enable %s device failed", ena_dev_list[i]);
439         }
440
441     } else {
442         is_verb_changed = 1;
443
444         AUDIO_LOG_INFO("Setting new verb: %s", verb);
445         /* set new verb */
446         if (snd_use_case_set(ah->ucm.uc_mgr, "_verb", verb) < 0) {
447             AUDIO_LOG_ERROR("Setting verb %s failed", verb);
448             audio_ret = AUDIO_ERR_UNDEFINED;
449             goto exit;
450         }
451         /* enable devices */
452         for (i = 0; i < dev_count; i++) {
453             AUDIO_LOG_INFO("Enable device : %s", devices[i]);
454             if (snd_use_case_set(ah->ucm.uc_mgr, "_enadev", devices[i]) < 0)
455                 AUDIO_LOG_ERROR("Enable %s device failed", devices[i]);
456         }
457     }
458
459 exit:
460     if (old_verb)
461         free((void *)old_verb);
462     if (old_dev_list)
463         snd_use_case_free_list(old_dev_list, old_dev_count);
464     if (dis_dev_list)
465         free((void *)dis_dev_list);
466     if (ena_dev_list)
467         free((void *)ena_dev_list);
468
469     if (is_verb_changed == 1 || is_dev_changed == 1) {
470         const char *new_verb = NULL, **new_dev_list = NULL;
471         int new_dev_count = 0;
472
473         snd_use_case_get(ah->ucm.uc_mgr, "_verb", &new_verb);
474         new_dev_count = snd_use_case_get_list(ah->ucm.uc_mgr, "_enadevs", &new_dev_list);
475         __dump_use_case(UCM_PREFIX_CHANGED, new_verb, new_dev_list, new_dev_count, NULL, 0);
476
477         if (new_verb)
478             free((void *)new_verb);
479         if (new_dev_list)
480             snd_use_case_free_list(new_dev_list, new_dev_count);
481     }
482
483     return audio_ret;
484
485 }
486
487 audio_return_t _ucm_set_modifiers(audio_hal_t *ah, const char *verb, const char *modifiers[])
488 {
489     audio_return_t audio_ret = AUDIO_RET_OK;
490     int is_verb_changed = 0, is_mod_changed = 0;
491     const char *old_verb = NULL, **old_mod_list = NULL;
492     int old_mod_count = 0, mod_count = 0;
493     const char **dis_mod_list = NULL, **ena_mod_list = NULL;
494     int dis_mod_count = 0, ena_mod_count = 0;
495     int i = 0, j = 0;
496
497     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
498     AUDIO_RETURN_VAL_IF_FAIL(ah->ucm.uc_mgr, AUDIO_ERR_PARAMETER);
499     AUDIO_RETURN_VAL_IF_FAIL(verb, AUDIO_ERR_PARAMETER);
500     AUDIO_RETURN_VAL_IF_FAIL(modifiers, AUDIO_ERR_PARAMETER);
501
502     snd_use_case_get(ah->ucm.uc_mgr, "_verb", &old_verb);
503     old_mod_count = snd_use_case_get_list(ah->ucm.uc_mgr, "_enamods", &old_mod_list);
504     __dump_use_case(UCM_PREFIX_CURRENT, old_verb, NULL, 0, old_mod_list, old_mod_count);
505
506     if (modifiers) {
507         for (mod_count = 0; modifiers[mod_count]; mod_count++);
508     }
509
510     __dump_use_case(UCM_PREFIX_REQUESTED, verb, NULL, 0, modifiers, mod_count);
511
512     if (old_verb && streq(verb, old_verb)) {
513         AUDIO_LOG_DEBUG("current verb and new verb is same. No need to change verb, disable devices explicitely");
514
515         if (old_mod_count > 0) {
516             dis_mod_list = (const char **)malloc(sizeof(const char *) * old_mod_count);
517             for (i = 0; i < old_mod_count; i++) {
518                 dis_mod_list[i] = NULL;
519             }
520         }
521         if (mod_count > 0) {
522             ena_mod_list = (const char **)malloc(sizeof(const char *) * mod_count);
523             for (i = 0; i < mod_count; i++) {
524                 ena_mod_list[i] = NULL;
525             }
526         }
527
528         /* update disable modifiers list which are not present in new modifier list */
529         for (i = 0; i < old_mod_count; i++) {
530             int need_disable_mod = 1;
531
532             for (j = 0; j < mod_count; j++) {
533                 if (streq(old_mod_list[i], modifiers[j])) {
534                     need_disable_mod = 0;
535                     break;
536                 }
537             }
538             if (need_disable_mod) {
539                 if (is_mod_changed == 0)
540                     is_mod_changed = 1;
541                 dis_mod_list[dis_mod_count++] = old_mod_list[i];
542             }
543         }
544
545         /* update enable modifiers list which are not present in old modifier list */
546         for (i = 0; i < mod_count; i++) {
547             int need_enable_mod = 1;
548
549             for (j = 0; j < old_mod_count; j++) {
550                 if (streq(modifiers[i], old_mod_list[j])) {
551                     need_enable_mod = 0;
552                     break;
553                 }
554             }
555             if (need_enable_mod) {
556                 if (is_mod_changed == 0)
557                     is_mod_changed = 1;
558                 ena_mod_list[ena_mod_count++] = modifiers[i];
559             }
560         }
561
562         /* disable modifiers */
563         for (i = 0; i < dis_mod_count; i++) {
564             AUDIO_LOG_INFO("Disable modifier : %s", dis_mod_list[i]);
565             if (snd_use_case_set(ah->ucm.uc_mgr, "_dismod", dis_mod_list[i]) < 0)
566                 AUDIO_LOG_ERROR("disable %s modifier failed", dis_mod_list[i]);
567         }
568
569         /* enable modifiers */
570         for (i = 0; i < ena_mod_count; i++) {
571             AUDIO_LOG_INFO("Enable modifier : %s", ena_mod_list[i]);
572             if (snd_use_case_set(ah->ucm.uc_mgr, "_enamod", ena_mod_list[i]) < 0)
573                 AUDIO_LOG_ERROR("enable %s modifier failed", ena_mod_list[i]);
574         }
575     } else {
576         is_verb_changed = 1;
577
578         AUDIO_LOG_DEBUG("Setting new verb: %s", verb);
579         /* set new verb */
580         if (snd_use_case_set(ah->ucm.uc_mgr, "_verb", verb) < 0) {
581             AUDIO_LOG_ERROR("Setting verb %s failed", verb);
582             audio_ret = AUDIO_ERR_UNDEFINED;
583             goto exit;
584         }
585         /* enable modifiers */
586         for (i = 0; i < mod_count; i++) {
587             AUDIO_LOG_DEBUG("Enable modifier : %s", modifiers[i]);
588             if (snd_use_case_set(ah->ucm.uc_mgr, "_enamod", modifiers[i]) < 0)
589                 AUDIO_LOG_ERROR("Enable %s modifier failed", modifiers[i]);
590         }
591     }
592
593 exit:
594     if (old_verb)
595         free((void *)old_verb);
596     if (old_mod_list)
597         snd_use_case_free_list(old_mod_list, old_mod_count);
598     if (dis_mod_list)
599         free((void *)dis_mod_list);
600     if (ena_mod_list)
601         free((void *)ena_mod_list);
602
603     if (is_verb_changed == 1 || is_mod_changed == 1) {
604         const char *new_verb = NULL, **new_mod_list = NULL;
605         int new_mod_count = 0;
606
607         snd_use_case_get(ah->ucm.uc_mgr, "_verb", &new_verb);
608         new_mod_count = snd_use_case_get_list(ah->ucm.uc_mgr, "_enamods", &new_mod_list);
609         __dump_use_case(UCM_PREFIX_CHANGED, new_verb, NULL, 0, new_mod_list, new_mod_count);
610
611         if (new_verb)
612             free((void *)new_verb);
613         if (new_mod_list)
614             snd_use_case_free_list(new_mod_list, new_mod_count);
615     }
616
617     return audio_ret;
618 }
619
620 audio_return_t _ucm_get_verb(audio_hal_t *ah, const char **value)
621 {
622     audio_return_t ret = AUDIO_RET_OK;
623
624     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
625     AUDIO_RETURN_VAL_IF_FAIL(ah->ucm.uc_mgr, AUDIO_ERR_PARAMETER);
626     AUDIO_RETURN_VAL_IF_FAIL(value, AUDIO_ERR_PARAMETER);
627
628     if ((ret = snd_use_case_get(ah->ucm.uc_mgr, "_verb", value)) < 0) {
629         AUDIO_LOG_ERROR("Getting current verb failed: Reason %d", ret);
630         ret = AUDIO_ERR_UNDEFINED;
631     }
632
633     return ret;
634 }
635
636 audio_return_t _ucm_reset_use_case(audio_hal_t *ah)
637 {
638     audio_return_t ret = AUDIO_RET_OK;
639
640     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
641     AUDIO_RETURN_VAL_IF_FAIL(ah->ucm.uc_mgr, AUDIO_ERR_PARAMETER);
642
643     AUDIO_LOG_INFO(">>> UCM reset Verb [ %s ]", AUDIO_USE_CASE_VERB_INACTIVE);
644
645     if ((ret = snd_use_case_set(ah->ucm.uc_mgr, "_verb", AUDIO_USE_CASE_VERB_INACTIVE)) < 0) {
646         AUDIO_LOG_ERROR("Reset use case failed: Reason %d", ret);
647         ret = AUDIO_ERR_UNDEFINED;
648     }
649
650     return ret;
651 }