Enhance to check parameters and move volume_level_max array to audio_hal_volume_t
[platform/adaptation/spreadtrum/audio-hal-sc7727.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 audio_return_t _ucm_get_device_name(audio_hal_t *ah, const char *use_case, audio_direction_t direction, const char **value)
126 {
127     char identifier[70] = { 0, };
128
129     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
130     AUDIO_RETURN_VAL_IF_FAIL(use_case, AUDIO_ERR_PARAMETER);
131     AUDIO_RETURN_VAL_IF_FAIL(ah->ucm.uc_mgr, AUDIO_ERR_PARAMETER);
132
133     snprintf(identifier, sizeof(identifier), "%sPCM//%s",
134              (direction == AUDIO_DIRECTION_IN) ? "Capture" : "Playback", use_case);
135
136     snd_use_case_get(ah->ucm.uc_mgr, identifier, value);
137
138     AUDIO_LOG_INFO("get device name : [%s]", *value);
139
140     return AUDIO_RET_OK;
141 }
142
143 /* UCM sequence
144     1) If verb is null or verb is not changed
145     1-1) If device is changed
146          (If there is request for same device, it will be ignored)
147          -> Set "Inactive" verb, disable modifiers & devices, set current verb again, enable devices & modifiers
148             (playback/capture device will be enabled again if there is no request for playback/capture device)
149     1-2) If device is not changed
150      1-2-1) If modifier is changed
151             (If there is request for same modifier, it will be ignored)
152             -> Disable modifiers, enable modifiers
153    2) If verb is changed
154       -> Reset, set new verb, enable devices & modifiers
155  */
156 audio_return_t _ucm_set_use_case(audio_hal_t *ah, const char *verb, const char *devices[], const char *modifiers[])
157 {
158     audio_return_t audio_ret = AUDIO_RET_OK;
159     int is_verb_changed = 0, is_dev_changed = 0, is_mod_changed = 0;
160     const char *old_verb = NULL, **old_dev_list = NULL, **old_mod_list = NULL;
161     int old_dev_count = 0, dev_count = 0;
162     int old_mod_count = 0, mod_count = 0;
163     const char **dis_dev_list = NULL, **ena_dev_list = NULL;
164     const char **dis_mod_list = NULL, **ena_mod_list = NULL;
165     int dis_dev_count = 0, ena_dev_count = 0;
166     int dis_mod_count = 0, ena_mod_count = 0;
167     int i = 0, j = 0;
168
169     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
170     AUDIO_RETURN_VAL_IF_FAIL(ah->ucm.uc_mgr, AUDIO_ERR_PARAMETER);
171     AUDIO_RETURN_VAL_IF_FAIL(verb, AUDIO_ERR_PARAMETER);
172
173     snd_use_case_get(ah->ucm.uc_mgr, "_verb", &old_verb);
174     old_dev_count = snd_use_case_get_list(ah->ucm.uc_mgr, "_enadevs", &old_dev_list);
175     old_mod_count = snd_use_case_get_list(ah->ucm.uc_mgr, "_enamods", &old_mod_list);
176     __dump_use_case(UCM_PREFIX_CURRENT, old_verb, old_dev_list, old_dev_count, old_mod_list, old_mod_count);
177
178     if (devices) {
179         for (dev_count = 0; devices[dev_count]; dev_count++);
180     }
181     if (modifiers) {
182         for (mod_count = 0; modifiers[mod_count]; mod_count++);
183     }
184
185     __dump_use_case(UCM_PREFIX_REQUESTED, verb, devices, dev_count, modifiers, mod_count);
186
187     if (old_verb && streq(verb, old_verb)) {
188         AUDIO_LOG_DEBUG("current verb and new verb is same. No need to change verb, disable devices explicitely");
189
190         if (old_dev_count > 0) {
191             dis_dev_list = (const char **)malloc(sizeof(const char *) * old_dev_count);
192             for (i = 0; i < old_dev_count; i++) {
193                 dis_dev_list[i] = NULL;
194             }
195         }
196         if (dev_count > 0) {
197             ena_dev_list = (const char **)malloc(sizeof(const char *) * dev_count);
198             for (i = 0; i < dev_count; i++) {
199                 ena_dev_list[i] = NULL;
200             }
201         }
202         if (old_mod_count > 0) {
203             dis_mod_list = (const char **)malloc(sizeof(const char *) * old_mod_count);
204             for (i = 0; i < old_mod_count; i++) {
205                 dis_mod_list[i] = NULL;
206             }
207         }
208         if (mod_count > 0) {
209             ena_mod_list = (const char **)malloc(sizeof(const char *) * mod_count);
210             for (i = 0; i < mod_count; i++) {
211                 ena_mod_list[i] = NULL;
212             }
213         }
214
215         /* update disable modifiers list which are not present in new modifier list */
216         for (i = 0; i < old_mod_count; i++) {
217             int need_disable_mod = 1;
218
219             for (j = 0; j < mod_count; j++) {
220                 if (streq(old_mod_list[i], modifiers[j])) {
221                     need_disable_mod = 0;
222                     break;
223                 }
224             }
225             if (need_disable_mod) {
226                 if (is_mod_changed == 0)
227                     is_mod_changed = 1;
228                 dis_mod_list[dis_mod_count++] = old_mod_list[i];
229             }
230         }
231
232         /* update disable devices list which are not present in new device list */
233         for (i = 0; i < old_dev_count; i++) {
234             int need_disable_dev = 1;
235
236             for (j = 0; j < dev_count; j++) {
237                 if (streq(old_dev_list[i], devices[j])) {
238                     need_disable_dev = 0;
239                     break;
240                 }
241             }
242             if (need_disable_dev) {
243                 if (is_dev_changed == 0)
244                     is_dev_changed = 1;
245                 dis_dev_list[dis_dev_count++] = old_dev_list[i];
246             }
247         }
248
249         /* update enable devices list which are not present in old device list */
250         for (i = 0; i < dev_count; i++) {
251             int need_enable_dev = 1;
252
253             for (j = 0; j < old_dev_count; j++) {
254                 if (streq(devices[i], old_dev_list[j])) {
255                     need_enable_dev = 0;
256                     break;
257                 }
258             }
259             if (need_enable_dev) {
260                 if (is_dev_changed == 0)
261                     is_dev_changed = 1;
262                 ena_dev_list[ena_dev_count++] = devices[i];
263             }
264         }
265
266         /* update enable modifiers list which are not present in old modifier list */
267         for (i = 0; i < mod_count; i++) {
268             int need_enable_mod = 1;
269
270             for (j = 0; j < old_mod_count; j++) {
271                 if (streq(modifiers[i], old_mod_list[j])) {
272                     need_enable_mod = 0;
273                     break;
274                 }
275             }
276             if (need_enable_mod) {
277                 if (is_mod_changed == 0)
278                     is_mod_changed = 1;
279                 ena_mod_list[ena_mod_count++] = modifiers[i];
280             }
281         }
282
283         /* disable modifiers */
284         for (i = 0; i < dis_mod_count; i++) {
285             AUDIO_LOG_INFO("Disable modifier : %s", dis_mod_list[i]);
286             if (snd_use_case_set(ah->ucm.uc_mgr, "_dismod", dis_mod_list[i]) < 0)
287                 AUDIO_LOG_ERROR("disable %s modifier failed", dis_mod_list[i]);
288         }
289
290         /* disable devices */
291         for (i = 0; i < dis_dev_count; i++) {
292             AUDIO_LOG_INFO("Disable device : %s", dis_dev_list[i]);
293             if (snd_use_case_set(ah->ucm.uc_mgr, "_disdev", dis_dev_list[i]) < 0)
294                 AUDIO_LOG_ERROR("disable %s device failed", dis_dev_list[i]);
295         }
296
297         /* enable devices */
298         for (i = 0; i < ena_dev_count; i++) {
299             AUDIO_LOG_INFO("Enable device : %s", ena_dev_list[i]);
300             if (snd_use_case_set(ah->ucm.uc_mgr, "_enadev", ena_dev_list[i]) < 0)
301                 AUDIO_LOG_ERROR("enable %s device failed", ena_dev_list[i]);
302         }
303
304         /* enable modifiers */
305         for (i = 0; i < ena_mod_count; i++) {
306             AUDIO_LOG_INFO("Enable modifier : %s", ena_mod_list[i]);
307             if (snd_use_case_set(ah->ucm.uc_mgr, "_enamod", ena_mod_list[i]) < 0)
308                 AUDIO_LOG_ERROR("enable %s modifier failed", ena_mod_list[i]);
309         }
310     } else {
311         is_verb_changed = 1;
312
313         AUDIO_LOG_DEBUG("Setting new verb: %s", verb);
314         /* set new verb */
315         if (snd_use_case_set(ah->ucm.uc_mgr, "_verb", verb) < 0) {
316             AUDIO_LOG_ERROR("Setting verb %s failed", verb);
317             audio_ret = AUDIO_ERR_UNDEFINED;
318             goto exit;
319         }
320         /* enable devices */
321         for (i = 0; i < dev_count; i++) {
322             AUDIO_LOG_DEBUG("Enable device : %s", devices[i]);
323             if (snd_use_case_set(ah->ucm.uc_mgr, "_enadev", devices[i]) < 0)
324                 AUDIO_LOG_ERROR("Enable %s device failed", devices[i]);
325         }
326         /* enable modifiers */
327         for (i = 0; i < mod_count; i++) {
328             AUDIO_LOG_DEBUG("Enable modifier : %s", modifiers[i]);
329             if (snd_use_case_set(ah->ucm.uc_mgr, "_enamod", modifiers[i]) < 0)
330                 AUDIO_LOG_ERROR("Enable %s modifier failed", modifiers[i]);
331         }
332     }
333
334 exit:
335     if (old_verb)
336         free((void *)old_verb);
337     if (old_dev_list)
338         snd_use_case_free_list(old_dev_list, old_dev_count);
339     if (old_mod_list)
340         snd_use_case_free_list(old_mod_list, old_mod_count);
341     if (dis_dev_list)
342         free((void *)dis_dev_list);
343     if (ena_dev_list)
344         free((void *)ena_dev_list);
345     if (dis_mod_list)
346         free((void *)dis_mod_list);
347     if (ena_mod_list)
348         free((void *)ena_mod_list);
349
350     if (is_verb_changed == 1 || is_dev_changed == 1 || is_mod_changed == 1) {
351         const char *new_verb = NULL, **new_dev_list = NULL, **new_mod_list = NULL;
352         int new_dev_count = 0, new_mod_count = 0;
353
354         snd_use_case_get(ah->ucm.uc_mgr, "_verb", &new_verb);
355         new_dev_count = snd_use_case_get_list(ah->ucm.uc_mgr, "_enadevs", &new_dev_list);
356         new_mod_count = snd_use_case_get_list(ah->ucm.uc_mgr, "_enamods", &new_mod_list);
357         __dump_use_case(UCM_PREFIX_CHANGED, new_verb, new_dev_list, new_dev_count, new_mod_list, new_mod_count);
358
359         if (new_verb)
360             free((void *)new_verb);
361         if (new_dev_list)
362             snd_use_case_free_list(new_dev_list, new_dev_count);
363         if (new_mod_list)
364             snd_use_case_free_list(new_mod_list, new_mod_count);
365     }
366
367     return audio_ret;
368 }
369
370 audio_return_t _ucm_set_devices(audio_hal_t *ah, const char *verb, const char *devices[])
371 {
372     audio_return_t audio_ret = AUDIO_RET_OK;
373     int is_verb_changed = 0, is_dev_changed = 0;
374     const char *old_verb = NULL, **old_dev_list = NULL;
375     int old_dev_count = 0, dev_count = 0;
376     const char **dis_dev_list = NULL, **ena_dev_list = NULL;
377     int dis_dev_count = 0, ena_dev_count = 0;
378     int i = 0, j = 0;
379
380     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
381     AUDIO_RETURN_VAL_IF_FAIL(ah->ucm.uc_mgr, AUDIO_ERR_PARAMETER);
382     AUDIO_RETURN_VAL_IF_FAIL(verb, AUDIO_ERR_PARAMETER);
383     AUDIO_RETURN_VAL_IF_FAIL(devices, AUDIO_ERR_PARAMETER);
384
385     snd_use_case_get(ah->ucm.uc_mgr, "_verb", &old_verb);
386     old_dev_count = snd_use_case_get_list(ah->ucm.uc_mgr, "_enadevs", &old_dev_list);
387     __dump_use_case(UCM_PREFIX_CURRENT, old_verb, old_dev_list, old_dev_count, NULL, 0);
388
389     if (devices) {
390         if (streq(verb, "Voice")) {
391             /* In case of Voice verb with Bluetooth device, make this device alone */
392             for (dev_count = 0; devices[dev_count]; dev_count++) {
393                 if (streq(devices[dev_count], "Bluetooth")) {
394                     devices = &devices[dev_count];
395                     dev_count = 1;
396                     AUDIO_LOG_DEBUG("Voice verb with Bluetooth device only");
397                     break;
398                 }
399             }
400         } else
401             for (dev_count = 0; devices[dev_count]; dev_count++);
402     }
403
404     __dump_use_case(UCM_PREFIX_REQUESTED, verb, devices, dev_count, NULL, 0);
405
406     if (old_verb && streq(verb, old_verb)) {
407         AUDIO_LOG_DEBUG("current verb and new verb is same. No need to change verb, disable devices explicitely");
408
409         if (old_dev_count > 0) {
410             dis_dev_list = (const char **)malloc(sizeof(const char *) * old_dev_count);
411             for (i = 0; i < old_dev_count; i++) {
412                 dis_dev_list[i] = NULL;
413             }
414         }
415         if (dev_count > 0) {
416             ena_dev_list = (const char **)malloc(sizeof(const char *) * dev_count);
417             for (i = 0; i < dev_count; i++) {
418                 ena_dev_list[i] = NULL;
419             }
420         }
421
422         /* update disable devices list which are not present in new device list */
423         for (i = 0; i < old_dev_count; i++) {
424             int need_disable_dev = 1;
425
426             for (j = 0; j < dev_count; j++) {
427                 if (streq(old_dev_list[i], devices[j])) {
428                     need_disable_dev = 0;
429                     break;
430                 }
431             }
432             if (need_disable_dev) {
433                 if (is_dev_changed == 0)
434                     is_dev_changed = 1;
435                 dis_dev_list[dis_dev_count++] = old_dev_list[i];
436             }
437         }
438
439         /* update enable devices list which are not present in old device list */
440         for (i = 0; i < dev_count; i++) {
441             int need_enable_dev = 1;
442
443             for (j = 0; j < old_dev_count; j++) {
444                 if (streq(devices[i], old_dev_list[j])) {
445                     need_enable_dev = 0;
446                     break;
447                 }
448             }
449             if (need_enable_dev) {
450                 if (is_dev_changed == 0)
451                     is_dev_changed = 1;
452                 ena_dev_list[ena_dev_count++] = devices[i];
453             }
454         }
455
456         /* disable devices */
457         for (i = 0; i < dis_dev_count; i++) {
458             AUDIO_LOG_INFO("Disable device : %s", dis_dev_list[i]);
459             if (snd_use_case_set(ah->ucm.uc_mgr, "_disdev", dis_dev_list[i]) < 0)
460                 AUDIO_LOG_ERROR("disable %s device failed", dis_dev_list[i]);
461         }
462
463         /* enable devices */
464         for (i = 0; i < ena_dev_count; i++) {
465             AUDIO_LOG_INFO("Enable device : %s", ena_dev_list[i]);
466             if (snd_use_case_set(ah->ucm.uc_mgr, "_enadev", ena_dev_list[i]) < 0)
467                 AUDIO_LOG_ERROR("enable %s device failed", ena_dev_list[i]);
468         }
469
470     } else {
471         is_verb_changed = 1;
472
473         AUDIO_LOG_INFO("Setting new verb: %s", verb);
474         /* set new verb */
475         if (snd_use_case_set(ah->ucm.uc_mgr, "_verb", verb) < 0) {
476             AUDIO_LOG_ERROR("Setting verb %s failed", verb);
477             audio_ret = AUDIO_ERR_UNDEFINED;
478             goto exit;
479         }
480         /* enable devices */
481         for (i = 0; i < dev_count; i++) {
482             AUDIO_LOG_INFO("Enable device : %s", devices[i]);
483             if (snd_use_case_set(ah->ucm.uc_mgr, "_enadev", devices[i]) < 0)
484                 AUDIO_LOG_ERROR("Enable %s device failed", devices[i]);
485         }
486     }
487
488 exit:
489     if (old_verb)
490         free((void *)old_verb);
491     if (old_dev_list)
492         snd_use_case_free_list(old_dev_list, old_dev_count);
493     if (dis_dev_list)
494         free((void *)dis_dev_list);
495     if (ena_dev_list)
496         free((void *)ena_dev_list);
497
498     if (is_verb_changed == 1 || is_dev_changed == 1) {
499         const char *new_verb = NULL, **new_dev_list = NULL;
500         int new_dev_count = 0;
501
502         snd_use_case_get(ah->ucm.uc_mgr, "_verb", &new_verb);
503         new_dev_count = snd_use_case_get_list(ah->ucm.uc_mgr, "_enadevs", &new_dev_list);
504         __dump_use_case(UCM_PREFIX_CHANGED, new_verb, new_dev_list, new_dev_count, NULL, 0);
505
506         if (new_verb)
507             free((void *)new_verb);
508         if (new_dev_list)
509             snd_use_case_free_list(new_dev_list, new_dev_count);
510     }
511
512     return audio_ret;
513
514 }
515
516 audio_return_t _ucm_set_modifiers(audio_hal_t *ah, const char *verb, const char *modifiers[])
517 {
518     audio_return_t audio_ret = AUDIO_RET_OK;
519     int is_verb_changed = 0, is_mod_changed = 0;
520     const char *old_verb = NULL, **old_mod_list = NULL;
521     int old_mod_count = 0, mod_count = 0;
522     const char **dis_mod_list = NULL, **ena_mod_list = NULL;
523     int dis_mod_count = 0, ena_mod_count = 0;
524     int i = 0, j = 0;
525
526     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
527     AUDIO_RETURN_VAL_IF_FAIL(ah->ucm.uc_mgr, AUDIO_ERR_PARAMETER);
528     AUDIO_RETURN_VAL_IF_FAIL(verb, AUDIO_ERR_PARAMETER);
529     AUDIO_RETURN_VAL_IF_FAIL(modifiers, AUDIO_ERR_PARAMETER);
530
531     snd_use_case_get(ah->ucm.uc_mgr, "_verb", &old_verb);
532     old_mod_count = snd_use_case_get_list(ah->ucm.uc_mgr, "_enamods", &old_mod_list);
533     __dump_use_case(UCM_PREFIX_CURRENT, old_verb, NULL, 0, old_mod_list, old_mod_count);
534
535     if (modifiers) {
536         for (mod_count = 0; modifiers[mod_count]; mod_count++);
537     }
538
539     __dump_use_case(UCM_PREFIX_REQUESTED, verb, NULL, 0, modifiers, mod_count);
540
541     if (old_verb && streq(verb, old_verb)) {
542         AUDIO_LOG_DEBUG("current verb and new verb is same. No need to change verb, disable devices explicitely");
543
544         if (old_mod_count > 0) {
545             dis_mod_list = (const char **)malloc(sizeof(const char *) * old_mod_count);
546             for (i = 0; i < old_mod_count; i++) {
547                 dis_mod_list[i] = NULL;
548             }
549         }
550         if (mod_count > 0) {
551             ena_mod_list = (const char **)malloc(sizeof(const char *) * mod_count);
552             for (i = 0; i < mod_count; i++) {
553                 ena_mod_list[i] = NULL;
554             }
555         }
556
557         /* update disable modifiers list which are not present in new modifier list */
558         for (i = 0; i < old_mod_count; i++) {
559             int need_disable_mod = 1;
560
561             for (j = 0; j < mod_count; j++) {
562                 if (streq(old_mod_list[i], modifiers[j])) {
563                     need_disable_mod = 0;
564                     break;
565                 }
566             }
567             if (need_disable_mod) {
568                 if (is_mod_changed == 0)
569                     is_mod_changed = 1;
570                 dis_mod_list[dis_mod_count++] = old_mod_list[i];
571             }
572         }
573
574         /* update enable modifiers list which are not present in old modifier list */
575         for (i = 0; i < mod_count; i++) {
576             int need_enable_mod = 1;
577
578             for (j = 0; j < old_mod_count; j++) {
579                 if (streq(modifiers[i], old_mod_list[j])) {
580                     need_enable_mod = 0;
581                     break;
582                 }
583             }
584             if (need_enable_mod) {
585                 if (is_mod_changed == 0)
586                     is_mod_changed = 1;
587                 ena_mod_list[ena_mod_count++] = modifiers[i];
588             }
589         }
590
591         /* disable modifiers */
592         for (i = 0; i < dis_mod_count; i++) {
593             AUDIO_LOG_INFO("Disable modifier : %s", dis_mod_list[i]);
594             if (snd_use_case_set(ah->ucm.uc_mgr, "_dismod", dis_mod_list[i]) < 0)
595                 AUDIO_LOG_ERROR("disable %s modifier failed", dis_mod_list[i]);
596         }
597
598         /* enable modifiers */
599         for (i = 0; i < ena_mod_count; i++) {
600             AUDIO_LOG_INFO("Enable modifier : %s", ena_mod_list[i]);
601             if (snd_use_case_set(ah->ucm.uc_mgr, "_enamod", ena_mod_list[i]) < 0)
602                 AUDIO_LOG_ERROR("enable %s modifier failed", ena_mod_list[i]);
603         }
604     } else {
605         is_verb_changed = 1;
606
607         AUDIO_LOG_DEBUG("Setting new verb: %s", verb);
608         /* set new verb */
609         if (snd_use_case_set(ah->ucm.uc_mgr, "_verb", verb) < 0) {
610             AUDIO_LOG_ERROR("Setting verb %s failed", verb);
611             audio_ret = AUDIO_ERR_UNDEFINED;
612             goto exit;
613         }
614         /* enable modifiers */
615         for (i = 0; i < mod_count; i++) {
616             AUDIO_LOG_DEBUG("Enable modifier : %s", modifiers[i]);
617             if (snd_use_case_set(ah->ucm.uc_mgr, "_enamod", modifiers[i]) < 0)
618                 AUDIO_LOG_ERROR("Enable %s modifier failed", modifiers[i]);
619         }
620     }
621
622 exit:
623     if (old_verb)
624         free((void *)old_verb);
625     if (old_mod_list)
626         snd_use_case_free_list(old_mod_list, old_mod_count);
627     if (dis_mod_list)
628         free((void *)dis_mod_list);
629     if (ena_mod_list)
630         free((void *)ena_mod_list);
631
632     if (is_verb_changed == 1 || is_mod_changed == 1) {
633         const char *new_verb = NULL, **new_mod_list = NULL;
634         int new_mod_count = 0;
635
636         snd_use_case_get(ah->ucm.uc_mgr, "_verb", &new_verb);
637         new_mod_count = snd_use_case_get_list(ah->ucm.uc_mgr, "_enamods", &new_mod_list);
638         __dump_use_case(UCM_PREFIX_CHANGED, new_verb, NULL, 0, new_mod_list, new_mod_count);
639
640         if (new_verb)
641             free((void *)new_verb);
642         if (new_mod_list)
643             snd_use_case_free_list(new_mod_list, new_mod_count);
644     }
645
646     return audio_ret;
647 }
648
649 audio_return_t _ucm_get_verb(audio_hal_t *ah, const char **value)
650 {
651     audio_return_t ret = AUDIO_RET_OK;
652
653     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
654     AUDIO_RETURN_VAL_IF_FAIL(ah->ucm.uc_mgr, AUDIO_ERR_PARAMETER);
655     AUDIO_RETURN_VAL_IF_FAIL(value, AUDIO_ERR_PARAMETER);
656
657     if ((ret = snd_use_case_get(ah->ucm.uc_mgr, "_verb", value)) < 0) {
658         AUDIO_LOG_ERROR("Getting current verb failed: Reason %d", ret);
659         ret = AUDIO_ERR_UNDEFINED;
660     }
661
662     return ret;
663 }
664
665 audio_return_t _ucm_reset_use_case(audio_hal_t *ah)
666 {
667     audio_return_t ret = AUDIO_RET_OK;
668
669     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
670     AUDIO_RETURN_VAL_IF_FAIL(ah->ucm.uc_mgr, AUDIO_ERR_PARAMETER);
671
672     AUDIO_LOG_INFO(">>> UCM reset Verb [ %s ]", AUDIO_USE_CASE_VERB_INACTIVE);
673
674     if ((ret = snd_use_case_set(ah->ucm.uc_mgr, "_verb", AUDIO_USE_CASE_VERB_INACTIVE)) < 0) {
675         AUDIO_LOG_ERROR("Reset use case failed: Reason %d", ret);
676         ret = AUDIO_ERR_UNDEFINED;
677     }
678
679     return ret;
680 }