Fix coverity issues (EVALUATION_ORDER)
[platform/adaptation/emulator/audio-hal-emul.git] / tizen-audio-routing.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
28 #include "tizen-audio-internal.h"
29 #include "tizen-audio-impl.h"
30
31 /* #define DEBUG_TIMING */
32
33 static device_type_s outDeviceTypes[] = {
34     { AUDIO_DEVICE_OUT_SPEAKER, "Speaker" },
35     { AUDIO_DEVICE_OUT_JACK, "Headphones" },
36     { AUDIO_DEVICE_OUT_BT_SCO, "Bluetooth" },
37     { AUDIO_DEVICE_OUT_AUX, "Line" },
38     { AUDIO_DEVICE_OUT_HDMI, "HDMI" },
39     { 0, 0 },
40 };
41
42 static device_type_s inDeviceTypes[] = {
43     { AUDIO_DEVICE_IN_MAIN_MIC, "MainMic" },
44     { AUDIO_DEVICE_IN_JACK, "HeadsetMic" },
45     { AUDIO_DEVICE_IN_BT_SCO, "BT Mic" },
46     { 0, 0 },
47 };
48
49 static uint32_t __convert_device_string_to_enum(const char* device_str, uint32_t direction)
50 {
51     uint32_t device = 0;
52
53     if (!strncmp(device_str, "builtin-speaker", MAX_NAME_LEN)) {
54         device = AUDIO_DEVICE_OUT_SPEAKER;
55     } else if (!strncmp(device_str, "builtin-receiver", MAX_NAME_LEN)) {
56         device = AUDIO_DEVICE_OUT_RECEIVER;
57     } else if ((!strncmp(device_str, "audio-jack", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_OUT)) {
58         device = AUDIO_DEVICE_OUT_JACK;
59     } else if ((!strncmp(device_str, "bt-sco", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_OUT)) {
60         device = AUDIO_DEVICE_OUT_BT_SCO;
61     } else if (!strncmp(device_str, "aux", MAX_NAME_LEN)) {
62         device = AUDIO_DEVICE_OUT_AUX;
63     } else if (!strncmp(device_str, "hdmi", MAX_NAME_LEN)) {
64         device = AUDIO_DEVICE_OUT_HDMI;
65     } else if ((!strncmp(device_str, "builtin-mic", MAX_NAME_LEN))) {
66         device = AUDIO_DEVICE_IN_MAIN_MIC;
67     } else if ((!strncmp(device_str, "audio-jack", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_IN)) {
68         device = AUDIO_DEVICE_IN_JACK;
69     } else if ((!strncmp(device_str, "bt-sco", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_IN)) {
70         device = AUDIO_DEVICE_IN_BT_SCO;
71     } else {
72         device = AUDIO_DEVICE_NONE;
73     }
74     AUDIO_LOG_INFO("device type(%s), enum(0x%x)", device_str, device);
75     return device;
76 }
77
78 static audio_return_e __set_devices(audio_hal_s *ah, device_info_s *devices, uint32_t num_of_devices)
79 {
80     audio_return_e audio_ret = AUDIO_RET_OK;
81     uint32_t new_device = 0;
82     const char *active_devices[MAX_DEVICES] = {NULL,};
83     int i = 0, j = 0, dev_idx = 0;
84
85     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
86     AUDIO_RETURN_VAL_IF_FAIL(devices, AUDIO_ERR_PARAMETER);
87     AUDIO_RETURN_VAL_IF_FAIL(num_of_devices, AUDIO_ERR_PARAMETER);
88
89     if (num_of_devices > MAX_DEVICES) {
90         num_of_devices = MAX_DEVICES;
91         AUDIO_LOG_ERROR("error: num_of_devices");
92         return AUDIO_ERR_PARAMETER;
93     }
94
95     if (devices[0].direction == AUDIO_DIRECTION_OUT) {
96         ah->device.active_out &= 0x0;
97         if (ah->device.active_in) {
98             /* check the active in devices */
99             for (j = 0; j < inDeviceTypes[j].type; j++) {
100                 if (((ah->device.active_in & (~AUDIO_DEVICE_IN)) & inDeviceTypes[j].type))
101                     active_devices[dev_idx++] = inDeviceTypes[j].name;
102             }
103         }
104     } else if (devices[0].direction == AUDIO_DIRECTION_IN) {
105         ah->device.active_in &= 0x0;
106         if (ah->device.active_out) {
107             /* check the active out devices */
108             for (j = 0; j < outDeviceTypes[j].type; j++) {
109                 if (ah->device.active_out & outDeviceTypes[j].type)
110                     active_devices[dev_idx++] = outDeviceTypes[j].name;
111             }
112         }
113     }
114
115     for (i = 0; i < num_of_devices; i++) {
116         new_device = __convert_device_string_to_enum(devices[i].type, devices[i].direction);
117         if (new_device & AUDIO_DEVICE_IN) {
118             for (j = 0; j < inDeviceTypes[j].type; j++) {
119                 if (new_device == inDeviceTypes[j].type) {
120                     active_devices[dev_idx++] = inDeviceTypes[j].name;
121                     ah->device.active_in |= new_device;
122                 }
123             }
124         } else {
125             for (j = 0; j < outDeviceTypes[j].type; j++) {
126                 if (new_device == outDeviceTypes[j].type) {
127                     active_devices[dev_idx++] = outDeviceTypes[j].name;
128                     ah->device.active_out |= new_device;
129                 }
130             }
131         }
132     }
133
134     if (active_devices[0] == NULL) {
135         AUDIO_LOG_ERROR("Failed to set device: active device is NULL");
136         return AUDIO_ERR_PARAMETER;
137     }
138
139     /* TODO : Set device here */
140
141     return audio_ret;
142 }
143
144 static audio_return_e __update_route_ap_playback_capture(audio_hal_s *ah, audio_route_info_s *route_info)
145 {
146     audio_return_e audio_ret = AUDIO_RET_OK;
147     device_info_s *devices = NULL;
148
149     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
150     AUDIO_RETURN_VAL_IF_FAIL(route_info, AUDIO_ERR_PARAMETER);
151
152     devices = route_info->device_infos;
153
154     AUDIO_LOG_INFO("update_route_ap_playback_capture++ ");
155
156     audio_ret = __set_devices(ah, devices, route_info->num_of_devices);
157     if (audio_ret) {
158         AUDIO_LOG_ERROR("Failed to set devices: error = 0x%x", audio_ret);
159         return audio_ret;
160     }
161
162     return audio_ret;
163 }
164
165 static audio_return_e __update_route_voip(audio_hal_s *ah, device_info_s *devices, int32_t num_of_devices)
166 {
167     audio_return_e audio_ret = AUDIO_RET_OK;
168
169     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
170     AUDIO_RETURN_VAL_IF_FAIL(devices, AUDIO_ERR_PARAMETER);
171
172     AUDIO_LOG_INFO("update_route_voip++");
173
174     audio_ret = __set_devices(ah, devices, num_of_devices);
175     if (audio_ret) {
176         AUDIO_LOG_ERROR("Failed to set devices: error = 0x%x", audio_ret);
177         return audio_ret;
178     }
179
180     return audio_ret;
181 }
182
183 static audio_return_e __update_route_reset(audio_hal_s *ah, uint32_t direction)
184 {
185     audio_return_e audio_ret = AUDIO_RET_OK;
186     const char *active_devices[MAX_DEVICES] = {NULL,};
187     int i = 0, dev_idx = 0;
188
189     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
190
191     AUDIO_LOG_INFO("update_route_reset++, direction(0x%x)", direction);
192
193     if (direction == AUDIO_DIRECTION_OUT) {
194         ah->device.active_out &= 0x0;
195         if (ah->device.active_in) {
196             /* check the active in devices */
197             for (i = 0; i < inDeviceTypes[i].type; i++) {
198                 if (((ah->device.active_in & (~AUDIO_DEVICE_IN)) & inDeviceTypes[i].type)) {
199                     active_devices[dev_idx++] = inDeviceTypes[i].name;
200                     AUDIO_LOG_INFO("added for in : %s", inDeviceTypes[i].name);
201                 }
202             }
203         }
204     } else {
205         ah->device.active_in &= 0x0;
206         if (ah->device.active_out) {
207             /* check the active out devices */
208             for (i = 0; i < outDeviceTypes[i].type; i++) {
209                 if (ah->device.active_out & outDeviceTypes[i].type) {
210                     active_devices[dev_idx++] = outDeviceTypes[i].name;
211                     AUDIO_LOG_INFO("added for out : %s", outDeviceTypes[i].name);
212                 }
213             }
214         }
215     }
216
217     if (active_devices[0] == NULL) {
218         AUDIO_LOG_DEBUG("active device is NULL, no need to update.");
219         return AUDIO_RET_OK;
220     }
221
222     return audio_ret;
223 }
224
225 audio_return_e _audio_routing_init(audio_hal_s *ah)
226 {
227     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
228
229     ah->device.active_in = 0x0;
230     ah->device.active_out = 0x0;
231
232     /* TODO : Device init here */
233
234     return AUDIO_RET_OK;
235 }
236
237 audio_return_e _audio_routing_deinit(audio_hal_s *ah)
238 {
239     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
240
241     /* TODO : Device deinit here */
242
243     return AUDIO_RET_OK;
244 }
245
246 #define LOOPBACK_ARG_LATENCY_MSEC      30
247 #define LOOPBACK_ARG_ADJUST_TIME_SEC   3
248 audio_return_e audio_update_route(void *audio_handle, audio_route_info_s *info)
249 {
250     audio_return_e audio_ret = AUDIO_RET_OK;
251     audio_hal_s *ah = (audio_hal_s *)audio_handle;
252     device_info_s *devices = NULL;
253
254     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
255     AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER);
256     AUDIO_RETURN_VAL_IF_FAIL(info->role, AUDIO_ERR_PARAMETER);
257
258     AUDIO_LOG_INFO("role:%s", info->role);
259
260     devices = info->device_infos;
261
262     if (!strncmp("voip", info->role, MAX_NAME_LEN)) {
263         if ((audio_ret = __update_route_voip(ah, devices, info->num_of_devices)))
264             AUDIO_LOG_WARN("update voip route return 0x%x", audio_ret);
265
266     } else if (!strncmp("reset", info->role, MAX_NAME_LEN)) {
267         if ((audio_ret = __update_route_reset(ah, devices->direction)))
268             AUDIO_LOG_WARN("update reset return 0x%x", audio_ret);
269
270     } else {
271         /* send latency and adjust time for loopback */
272         if (!strncmp("loopback", info->role, MAX_NAME_LEN)) {
273             _audio_comm_send_message(ah, "loopback::latency", LOOPBACK_ARG_LATENCY_MSEC);
274             _audio_comm_send_message(ah, "loopback::adjust_time", LOOPBACK_ARG_ADJUST_TIME_SEC);
275         }
276         /* need to prepare for "alarm","notification","emergency","voice-information","voice-recognition","ringtone" */
277         if ((audio_ret = __update_route_ap_playback_capture(ah, info)))
278             AUDIO_LOG_WARN("update playback route return 0x%x", audio_ret);
279     }
280     return audio_ret;
281 }
282
283 audio_return_e audio_update_route_option(void *audio_handle, audio_route_option_s *option)
284 {
285     audio_return_e audio_ret = AUDIO_RET_OK;
286     audio_hal_s *ah = (audio_hal_s *)audio_handle;
287
288     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
289     AUDIO_RETURN_VAL_IF_FAIL(option, AUDIO_ERR_PARAMETER);
290
291     AUDIO_LOG_INFO("role:%s, name:%s, value:%d", option->role, option->name, option->value);
292
293     return audio_ret;
294 }