Fix possible buffer overflow using sprintf/fprintf
[platform/adaptation/emulator/audio-hal-emul.git] / tizen-audio-impl-ctrl.c
1 /*
2  * audio-hal
3  *
4  * Copyright (c) 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 <pthread.h>
28
29 #include "tizen-audio-internal.h"
30
31 audio_return_t _control_init(audio_hal_t *ah)
32 {
33     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
34
35     pthread_mutex_init(&(ah->mixer.mutex), NULL);
36     return AUDIO_RET_OK;
37 }
38
39 audio_return_t _control_deinit(audio_hal_t *ah)
40 {
41     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
42
43     pthread_mutex_destroy(&(ah->mixer.mutex));
44     return AUDIO_RET_OK;
45 }
46
47 audio_return_t _mixer_control_set_param(audio_hal_t *ah, const char* ctl_name, snd_ctl_elem_value_t* param, int size)
48 {
49     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
50
51     /* TODO. */
52     return AUDIO_RET_OK;
53 }
54
55 audio_return_t _mixer_control_get_value(audio_hal_t *ah, const char *card, const char *ctl_name, int *val)
56 {
57     snd_ctl_t *handle;
58     snd_ctl_elem_value_t *control;
59     snd_ctl_elem_id_t *id;
60     snd_ctl_elem_info_t *info;
61     snd_ctl_elem_type_t type;
62
63     int ret = 0, count = 0, i = 0;
64
65     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
66     AUDIO_RETURN_VAL_IF_FAIL(card, AUDIO_ERR_PARAMETER);
67     AUDIO_RETURN_VAL_IF_FAIL(ctl_name, AUDIO_ERR_PARAMETER);
68     AUDIO_RETURN_VAL_IF_FAIL(val, AUDIO_ERR_PARAMETER);
69
70     pthread_mutex_lock(&(ah->mixer.mutex));
71
72     ret = snd_ctl_open(&handle, card, 0);
73     if (ret < 0) {
74         AUDIO_LOG_ERROR("snd_ctl_open error, %s\n", snd_strerror(ret));
75         pthread_mutex_unlock(&(ah->mixer.mutex));
76         return AUDIO_ERR_IOCTL;
77     }
78
79     // Get Element Info
80
81     snd_ctl_elem_id_alloca(&id);
82     snd_ctl_elem_info_alloca(&info);
83     snd_ctl_elem_value_alloca(&control);
84
85     snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
86     snd_ctl_elem_id_set_name(id, ctl_name);
87
88     snd_ctl_elem_info_set_id(info, id);
89     if (snd_ctl_elem_info(handle, info) < 0) {
90         AUDIO_LOG_ERROR("Cannot find control element: %s\n", ctl_name);
91         goto close;
92     }
93     snd_ctl_elem_info_get_id(info, id);
94
95     type = snd_ctl_elem_info_get_type(info);
96     count = snd_ctl_elem_info_get_count(info);
97
98     snd_ctl_elem_value_set_id(control, id);
99
100     if (snd_ctl_elem_read(handle, control) < 0) {
101         AUDIO_LOG_ERROR("snd_ctl_elem_read failed \n");
102         goto close;
103 }
104
105     switch (type) {
106     case SND_CTL_ELEM_TYPE_BOOLEAN:
107         *val = snd_ctl_elem_value_get_boolean(control, i);
108         break;
109     case SND_CTL_ELEM_TYPE_INTEGER:
110         for (i = 0; i < count; i++)
111         *val = snd_ctl_elem_value_get_integer(control, i);
112         break;
113     case SND_CTL_ELEM_TYPE_ENUMERATED:
114         for (i = 0; i < count; i++)
115         *val = snd_ctl_elem_value_get_enumerated(control, i);
116         break;
117     default:
118         AUDIO_LOG_WARN("unsupported control element type\n");
119         goto close;
120     }
121
122     snd_ctl_close(handle);
123
124 #ifdef AUDIO_DEBUG
125     AUDIO_LOG_INFO("get mixer(%s) = %d success", ctl_name, *val);
126 #endif
127
128     pthread_mutex_unlock(&(ah->mixer.mutex));
129     return AUDIO_RET_OK;
130
131 close:
132     AUDIO_LOG_ERROR("Error\n");
133     snd_ctl_close(handle);
134     pthread_mutex_unlock(&(ah->mixer.mutex));
135     return AUDIO_ERR_UNDEFINED;
136 }
137
138 audio_return_t _mixer_control_set_value(audio_hal_t *ah, const char *card, const char *ctl_name, int val)
139 {
140     snd_ctl_t *handle;
141     snd_ctl_elem_value_t *control;
142     snd_ctl_elem_id_t *id;
143     snd_ctl_elem_info_t *info;
144     snd_ctl_elem_type_t type;
145     int ret = 0, count = 0, i = 0;
146
147     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
148     AUDIO_RETURN_VAL_IF_FAIL(card, AUDIO_ERR_PARAMETER);
149     AUDIO_RETURN_VAL_IF_FAIL(ctl_name, AUDIO_ERR_PARAMETER);
150
151     pthread_mutex_lock(&(ah->mixer.mutex));
152
153     ret = snd_ctl_open(&handle, card, 0);
154     if (ret < 0) {
155         AUDIO_LOG_ERROR("snd_ctl_open error, card: %s: %s", card, snd_strerror(ret));
156         pthread_mutex_unlock(&(ah->mixer.mutex));
157         return AUDIO_ERR_IOCTL;
158     }
159
160     // Get Element Info
161
162     snd_ctl_elem_id_alloca(&id);
163     snd_ctl_elem_info_alloca(&info);
164     snd_ctl_elem_value_alloca(&control);
165
166     snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
167     snd_ctl_elem_id_set_name(id, ctl_name);
168
169     snd_ctl_elem_info_set_id(info, id);
170     if (snd_ctl_elem_info(handle, info) < 0) {
171         AUDIO_LOG_ERROR("Cannot find control element: %s", ctl_name);
172         goto close;
173     }
174     snd_ctl_elem_info_get_id(info, id);
175
176     type = snd_ctl_elem_info_get_type(info);
177     count = snd_ctl_elem_info_get_count(info);
178
179     snd_ctl_elem_value_set_id(control, id);
180
181     snd_ctl_elem_read(handle, control);
182
183     switch (type) {
184     case SND_CTL_ELEM_TYPE_BOOLEAN:
185         for (i = 0; i < count; i++)
186             snd_ctl_elem_value_set_boolean(control, i, val);
187         break;
188     case SND_CTL_ELEM_TYPE_INTEGER:
189         for (i = 0; i < count; i++)
190             snd_ctl_elem_value_set_integer(control, i, val);
191         break;
192     case SND_CTL_ELEM_TYPE_ENUMERATED:
193         for (i = 0; i < count; i++)
194             snd_ctl_elem_value_set_enumerated(control, i, val);
195         break;
196
197     default:
198         AUDIO_LOG_WARN("unsupported control element type");
199         goto close;
200     }
201
202     snd_ctl_elem_write(handle, control);
203
204     snd_ctl_close(handle);
205
206     AUDIO_LOG_INFO("set mixer(%s) = %d success", ctl_name, val);
207
208     pthread_mutex_unlock(&(ah->mixer.mutex));
209     return AUDIO_RET_OK;
210
211 close:
212     AUDIO_LOG_ERROR("Error");
213     snd_ctl_close(handle);
214     pthread_mutex_unlock(&(ah->mixer.mutex));
215     return AUDIO_ERR_UNDEFINED;
216 }
217
218 audio_return_t _mixer_control_set_value_string(audio_hal_t *ah, const char* ctl_name, const char* value)
219 {
220     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
221     AUDIO_RETURN_VAL_IF_FAIL(ctl_name, AUDIO_ERR_PARAMETER);
222
223     /* TODO. */
224     return AUDIO_RET_OK;
225 }
226
227
228 audio_return_t _mixer_control_get_element(audio_hal_t *ah, const char *ctl_name, snd_hctl_elem_t **elem)
229 {
230     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
231     AUDIO_RETURN_VAL_IF_FAIL(ctl_name, AUDIO_ERR_PARAMETER);
232     AUDIO_RETURN_VAL_IF_FAIL(elem, AUDIO_ERR_PARAMETER);
233
234     /* TODO. */
235     return AUDIO_RET_OK;
236 }