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