blob: f6083f3d1e5ea3c8377c11b47c80b4e720c94307 [file] [log] [blame]
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001/*
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002 * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003 * Not a contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070020#define LOG_TAG "voice_extn"
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -080021/*#define LOG_NDEBUG 0*/
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070022#define LOG_NDDEBUG 0
23
24#include <errno.h>
25#include <math.h>
26#include <cutils/log.h>
27#include <cutils/str_parms.h>
28#include <sys/ioctl.h>
29#include <sound/voice_params.h>
30
31#include "audio_hw.h"
32#include "voice.h"
33#include "platform.h"
34#include "platform_api.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080035#include "voice_extn.h"
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070036
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -080037#define AUDIO_PARAMETER_KEY_VSID "vsid"
38#define AUDIO_PARAMETER_KEY_CALL_STATE "call_state"
39#define AUDIO_PARAMETER_KEY_AUDIO_MODE "audio_mode"
40#define AUDIO_PARAMETER_KEY_ALL_CALL_STATES "all_call_states"
Shiv Maliyappanahalli575c1552014-03-07 15:31:55 -080041#define AUDIO_PARAMETER_KEY_DEVICE_MUTE "device_mute"
42#define AUDIO_PARAMETER_KEY_DIRECTION "direction"
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -080043
44#define VOICE_EXTN_PARAMETER_VALUE_MAX_LEN 256
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070045
46#define VOICE2_VSID 0x10DC1000
47#define VOLTE_VSID 0x10C02000
48#define QCHAT_VSID 0x10803000
Vicky Sehrawat111aeb32014-02-12 17:58:59 -080049#define VOWLAN_VSID 0x10002000
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070050#define ALL_VSID 0xFFFFFFFF
51
52/* Voice Session Indices */
53#define VOICE2_SESS_IDX (VOICE_SESS_IDX + 1)
54#define VOLTE_SESS_IDX (VOICE_SESS_IDX + 2)
55#define QCHAT_SESS_IDX (VOICE_SESS_IDX + 3)
Vicky Sehrawat111aeb32014-02-12 17:58:59 -080056#define VOWLAN_SESS_IDX (VOICE_SESS_IDX + 4)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070057
58/* Call States */
59#define CALL_HOLD (BASE_CALL_STATE + 2)
60#define CALL_LOCAL_HOLD (BASE_CALL_STATE + 3)
61
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -070062struct pcm_config pcm_config_incall_music = {
63 .channels = 1,
64 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
65 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
66 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
67 .format = PCM_FORMAT_S16_LE,
68 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
69 .stop_threshold = INT_MAX,
70 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
71};
72
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070073extern int start_call(struct audio_device *adev, audio_usecase_t usecase_id);
74extern int stop_call(struct audio_device *adev, audio_usecase_t usecase_id);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -080075int voice_extn_is_in_call(struct audio_device *adev, bool *in_call);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070076
77static bool is_valid_call_state(int call_state)
78{
79 if (call_state < CALL_INACTIVE || call_state > CALL_LOCAL_HOLD)
80 return false;
81 else
82 return true;
83}
84
85static bool is_valid_vsid(uint32_t vsid)
86{
87 if (vsid == VOICE_VSID ||
88 vsid == VOICE2_VSID ||
89 vsid == VOLTE_VSID ||
Vicky Sehrawat111aeb32014-02-12 17:58:59 -080090 vsid == QCHAT_VSID ||
91 vsid == VOWLAN_VSID)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070092 return true;
93 else
94 return false;
95}
96
97static audio_usecase_t voice_extn_get_usecase_for_session_idx(const int index)
98{
99 audio_usecase_t usecase_id = -1;
100
101 switch(index) {
102 case VOICE_SESS_IDX:
103 usecase_id = USECASE_VOICE_CALL;
104 break;
105
106 case VOICE2_SESS_IDX:
107 usecase_id = USECASE_VOICE2_CALL;
108 break;
109
110 case VOLTE_SESS_IDX:
111 usecase_id = USECASE_VOLTE_CALL;
112 break;
113
114 case QCHAT_SESS_IDX:
115 usecase_id = USECASE_QCHAT_CALL;
116 break;
117
Vicky Sehrawat111aeb32014-02-12 17:58:59 -0800118 case VOWLAN_SESS_IDX:
119 usecase_id = USECASE_VOWLAN_CALL;
120 break;
121
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700122 default:
123 ALOGE("%s: Invalid voice session index\n", __func__);
124 }
125
126 return usecase_id;
127}
128
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700129static uint32_t get_session_id_with_state(struct audio_device *adev,
130 int call_state)
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700131{
132 struct voice_session *session = NULL;
133 int i = 0;
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700134 uint32_t session_id = 0;
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700135
136 for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
137 session = &adev->voice.session[i];
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700138 if(session->state.current == call_state){
139 session_id = session->vsid;
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700140 break;
141 }
142 }
143
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700144 return session_id;
145}
146
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800147static int update_calls(struct audio_device *adev)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700148{
149 int i = 0;
150 audio_usecase_t usecase_id = 0;
151 enum voice_lch_mode lch_mode;
152 struct voice_session *session = NULL;
153 int fd = 0;
154 int ret = 0;
Shiv Maliyappanahalli07a9ea22014-01-06 14:53:52 -0800155 bool is_in_call = false;
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700156
157 ALOGD("%s: enter:", __func__);
158
159 for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
160 usecase_id = voice_extn_get_usecase_for_session_idx(i);
161 session = &adev->voice.session[i];
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700162 ALOGD("%s: cur_state=%d new_state=%d vsid=%x",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700163 __func__, session->state.current, session->state.new, session->vsid);
164
165 switch(session->state.new)
166 {
167 case CALL_ACTIVE:
168 switch(session->state.current)
169 {
170 case CALL_INACTIVE:
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700171 ALOGD("%s: INACTIVE -> ACTIVE vsid:%x", __func__, session->vsid);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700172 ret = start_call(adev, usecase_id);
173 if(ret < 0) {
174 ALOGE("%s: voice_start_call() failed for usecase: %d\n",
175 __func__, usecase_id);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800176 } else {
177 session->state.current = session->state.new;
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700178 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700179 break;
180
181 case CALL_HOLD:
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700182 ALOGD("%s: HOLD -> ACTIVE vsid:%x", __func__, session->vsid);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700183 session->state.current = session->state.new;
184 break;
185
186 case CALL_LOCAL_HOLD:
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700187 ALOGD("%s: LOCAL_HOLD -> ACTIVE vsid:%x", __func__, session->vsid);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700188 lch_mode = VOICE_LCH_STOP;
189 if (pcm_ioctl(session->pcm_tx, SNDRV_VOICE_IOCTL_LCH, &lch_mode) < 0) {
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700190 ALOGE("LOCAL_HOLD -> ACTIVE failed");
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700191 } else {
192 session->state.current = session->state.new;
193 }
194 break;
195
196 default:
197 ALOGV("%s: CALL_ACTIVE cannot be handled in state=%d vsid:%x",
198 __func__, session->state.current, session->vsid);
199 break;
200 }
201 break;
202
203 case CALL_INACTIVE:
204 switch(session->state.current)
205 {
206 case CALL_ACTIVE:
207 case CALL_HOLD:
208 case CALL_LOCAL_HOLD:
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700209 ALOGD("%s: ACTIVE/HOLD/LOCAL_HOLD -> INACTIVE vsid:%x", __func__, session->vsid);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700210 ret = stop_call(adev, usecase_id);
211 if(ret < 0) {
212 ALOGE("%s: voice_end_call() failed for usecase: %d\n",
213 __func__, usecase_id);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800214 } else {
Shiv Maliyappanahalli07a9ea22014-01-06 14:53:52 -0800215 voice_extn_is_in_call(adev, &is_in_call);
216 if (!is_in_call) {
217 adev->voice.voice_device_set = false;
218 }
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800219 session->state.current = session->state.new;
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700220 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700221 break;
222
223 default:
224 ALOGV("%s: CALL_INACTIVE cannot be handled in state=%d vsid:%x",
225 __func__, session->state.current, session->vsid);
226 break;
227 }
228 break;
229
230 case CALL_HOLD:
231 switch(session->state.current)
232 {
233 case CALL_ACTIVE:
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700234 ALOGD("%s: CALL_ACTIVE -> HOLD vsid:%x", __func__, session->vsid);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700235 session->state.current = session->state.new;
236 break;
237
238 case CALL_LOCAL_HOLD:
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700239 ALOGD("%s: CALL_LOCAL_HOLD -> HOLD vsid:%x", __func__, session->vsid);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700240 lch_mode = VOICE_LCH_STOP;
241 if (pcm_ioctl(session->pcm_tx, SNDRV_VOICE_IOCTL_LCH, &lch_mode) < 0) {
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700242 ALOGE("LOCAL_HOLD -> HOLD failed");
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700243 } else {
244 session->state.current = session->state.new;
245 }
246 break;
247
248 default:
249 ALOGV("%s: CALL_HOLD cannot be handled in state=%d vsid:%x",
250 __func__, session->state.current, session->vsid);
251 break;
252 }
253 break;
254
255 case CALL_LOCAL_HOLD:
256 switch(session->state.current)
257 {
258 case CALL_ACTIVE:
259 case CALL_HOLD:
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700260 ALOGD("%s: ACTIVE/CALL_HOLD -> LOCAL_HOLD vsid:%x", __func__,
261 session->vsid);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700262 lch_mode = VOICE_LCH_START;
263 if (pcm_ioctl(session->pcm_tx, SNDRV_VOICE_IOCTL_LCH, &lch_mode) < 0) {
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700264 ALOGE("LOCAL_HOLD -> HOLD failed");
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700265 } else {
266 session->state.current = session->state.new;
267 }
268 break;
269
270 default:
271 ALOGV("%s: CALL_LOCAL_HOLD cannot be handled in state=%d vsid:%x",
272 __func__, session->state.current, session->vsid);
273 break;
274 }
275 break;
276
277 default:
278 break;
279 } //end out switch loop
280 } //end for loop
281
282 return ret;
283}
284
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800285static int update_call_states(struct audio_device *adev,
286 const uint32_t vsid, const int call_state)
287{
288 struct voice_session *session = NULL;
289 int i = 0;
290 bool is_in_call;
Shiv Maliyappanahalli07a9ea22014-01-06 14:53:52 -0800291 int no_of_calls_active = 0;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800292
293 for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
294 if (vsid == adev->voice.session[i].vsid) {
295 session = &adev->voice.session[i];
296 break;
297 }
298 }
299
Shiv Maliyappanahalli07a9ea22014-01-06 14:53:52 -0800300 for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
301 if (CALL_INACTIVE != adev->voice.session[i].state.current)
302 no_of_calls_active++;
303 }
304
305 /* When there is only one call active, wait for audio policy manager to set
306 * the mode to AUDIO_MODE_NORMAL and trigger routing to end the last call.
307 */
308 if (no_of_calls_active == 1 && call_state == CALL_INACTIVE)
309 return 0;
310
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800311 if (session) {
312 session->state.new = call_state;
313 voice_extn_is_in_call(adev, &is_in_call);
Shiv Maliyappanahalli07a9ea22014-01-06 14:53:52 -0800314 ALOGD("%s is_in_call:%d voice_device_set:%d, mode:%d\n",
315 __func__, is_in_call, adev->voice.voice_device_set, adev->mode);
Shiv Maliyappanahalli7a2545c2013-11-08 18:26:33 -0800316 /* Dont start voice call before device routing for voice usescases has
317 * occured, otherwise voice calls will be started unintendedly on
318 * speaker.
319 */
Shiv Maliyappanahalli07a9ea22014-01-06 14:53:52 -0800320 if (is_in_call || adev->voice.voice_device_set) {
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800321 /* Device routing is not triggered for voice calls on the subsequent
322 * subs, Hence update the call states if voice call is already
323 * active on other sub.
324 */
325 update_calls(adev);
326 }
327 } else {
328 return -EINVAL;
329 }
330
331 return 0;
332
333}
334
335int voice_extn_get_active_session_id(struct audio_device *adev,
336 uint32_t *session_id)
337{
338 *session_id = get_session_id_with_state(adev, CALL_ACTIVE);
339 return 0;
340}
341
342int voice_extn_is_in_call(struct audio_device *adev, bool *in_call)
343{
344 struct voice_session *session = NULL;
345 int i = 0;
346 *in_call = false;
347
348 for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
349 session = &adev->voice.session[i];
350 if(session->state.current != CALL_INACTIVE){
351 *in_call = true;
352 break;
353 }
354 }
355
356 return 0;
357}
358
359void voice_extn_init(struct audio_device *adev)
360{
361 adev->voice.session[VOICE_SESS_IDX].vsid = VOICE_VSID;
362 adev->voice.session[VOICE2_SESS_IDX].vsid = VOICE2_VSID;
363 adev->voice.session[VOLTE_SESS_IDX].vsid = VOLTE_VSID;
364 adev->voice.session[QCHAT_SESS_IDX].vsid = QCHAT_VSID;
Vicky Sehrawat111aeb32014-02-12 17:58:59 -0800365 adev->voice.session[VOWLAN_SESS_IDX].vsid = VOWLAN_VSID;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800366}
367
368int voice_extn_get_session_from_use_case(struct audio_device *adev,
369 const audio_usecase_t usecase_id,
370 struct voice_session **session)
371{
372
373 switch(usecase_id)
374 {
375 case USECASE_VOICE_CALL:
376 *session = &adev->voice.session[VOICE_SESS_IDX];
377 break;
378
379 case USECASE_VOICE2_CALL:
380 *session = &adev->voice.session[VOICE2_SESS_IDX];
381 break;
382
383 case USECASE_VOLTE_CALL:
384 *session = &adev->voice.session[VOLTE_SESS_IDX];
385 break;
386
387 case USECASE_QCHAT_CALL:
388 *session = &adev->voice.session[QCHAT_SESS_IDX];
389 break;
390
Vicky Sehrawat111aeb32014-02-12 17:58:59 -0800391 case USECASE_VOWLAN_CALL:
392 *session = &adev->voice.session[VOWLAN_SESS_IDX];
393 break;
394
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800395 default:
396 ALOGE("%s: Invalid usecase_id:%d\n", __func__, usecase_id);
397 *session = NULL;
398 return -EINVAL;
399 }
400
401 return 0;
402}
403
404int voice_extn_start_call(struct audio_device *adev)
405{
406 /* Start voice calls on sessions whose call state has been
407 * udpated.
408 */
409 ALOGV("%s: enter:", __func__);
Shiv Maliyappanahalli07a9ea22014-01-06 14:53:52 -0800410 adev->voice.voice_device_set = true;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800411 return update_calls(adev);
412}
413
414int voice_extn_stop_call(struct audio_device *adev)
415{
416 int i;
417 int ret = 0;
418
419 ALOGV("%s: enter:", __func__);
420
421 /* If BT device is enabled and voice calls are ended, telephony will call
422 * set_mode(AUDIO_MODE_NORMAL) which will trigger audio policy manager to
423 * set routing with device BT A2DP profile. Hence end all voice calls when
424 * set_mode(AUDIO_MODE_NORMAL) before BT A2DP profile is selected.
425 */
426 if (adev->mode == AUDIO_MODE_NORMAL) {
427 ALOGD("%s: end all calls", __func__);
428 for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
429 adev->voice.session[i].state.new = CALL_INACTIVE;
430 }
431
432 ret = update_calls(adev);
433 }
434
435 return ret;
436}
437
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700438int voice_extn_set_parameters(struct audio_device *adev,
439 struct str_parms *parms)
440{
441 char *str;
442 int value;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -0800443 int ret = 0, err;
Krishnankutty Kolathappilly301cc362014-01-31 18:12:13 -0800444 char *kv_pairs = str_parms_to_str(parms);
Shiv Maliyappanahalli575c1552014-03-07 15:31:55 -0800445 char str_value[256] = {0};
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700446
Krishnankutty Kolathappilly301cc362014-01-31 18:12:13 -0800447 ALOGV_IF(kv_pairs != NULL, "%s: enter: %s", __func__, kv_pairs);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700448
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -0800449 err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_VSID, &value);
450 if (err >= 0) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700451 str_parms_del(parms, AUDIO_PARAMETER_KEY_VSID);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -0800452 uint32_t vsid = value;
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700453 int call_state = -1;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -0800454 err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_CALL_STATE, &value);
455 if (err >= 0) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700456 call_state = value;
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700457 } else {
458 ALOGE("%s: call_state key not found", __func__);
459 ret = -EINVAL;
460 goto done;
461 }
462
463 if (is_valid_vsid(vsid) && is_valid_call_state(call_state)) {
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800464 ret = update_call_states(adev, vsid, call_state);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700465 } else {
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800466 ALOGE("%s: invalid vsid:%x or call_state:%d",
467 __func__, vsid, call_state);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700468 ret = -EINVAL;
469 goto done;
470 }
Shiv Maliyappanahalli575c1552014-03-07 15:31:55 -0800471 }
472
473 err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_DEVICE_MUTE, str_value,
474 sizeof(str_value));
475 if (err >= 0) {
476 str_parms_del(parms, AUDIO_PARAMETER_KEY_DEVICE_MUTE);
477 bool mute = false;
478
479 if (!strncmp("true", str_value, sizeof("true"))) {
480 mute = true;
481 }
482
483 err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_DIRECTION, str_value,
484 sizeof(str_value));
485 if (err >= 0) {
486 str_parms_del(parms, AUDIO_PARAMETER_KEY_DIRECTION);
487 } else {
488 ALOGE("%s: direction key not found", __func__);
489 ret = -EINVAL;
490 goto done;
491 }
492
493 ret = platform_set_device_mute(adev->platform, mute, str_value);
494 if (ret != 0) {
495 ALOGE("%s: Failed to set mute err:%d", __func__, ret);
496 ret = -EINVAL;
497 goto done;
498 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700499 }
500
501done:
502 ALOGV("%s: exit with code(%d)", __func__, ret);
Krishnankutty Kolathappilly301cc362014-01-31 18:12:13 -0800503 free(kv_pairs);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700504 return ret;
505}
506
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -0800507int get_all_call_states_str(const struct audio_device *adev,
508 char *value)
509{
510 int ret = 0;
511 char *cur_ptr = value;
512 int i, len=0;
513
514 for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
515 snprintf(cur_ptr, VOICE_EXTN_PARAMETER_VALUE_MAX_LEN - len,
516 "%d:%d,",adev->voice.session[i].vsid,
517 adev->voice.session[i].state.current);
518 len = strlen(cur_ptr);
519 cur_ptr = cur_ptr + len;
520 }
521 ALOGV("%s:value=%s", __func__, value);
522 return ret;
523}
524
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -0800525void voice_extn_get_parameters(const struct audio_device *adev,
526 struct str_parms *query,
527 struct str_parms *reply)
528{
529 int ret;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -0800530 char value[VOICE_EXTN_PARAMETER_VALUE_MAX_LEN] = {0};
Krishnankutty Kolathappilly301cc362014-01-31 18:12:13 -0800531 char *str = str_parms_to_str(query);
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -0800532
Krishnankutty Kolathappilly301cc362014-01-31 18:12:13 -0800533 ALOGV_IF(str != NULL, "%s: enter %s", __func__, str);
534 free(str);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -0800535
536 ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_AUDIO_MODE, value,
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -0800537 sizeof(value));
538 if (ret >= 0) {
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -0800539 str_parms_add_int(reply, AUDIO_PARAMETER_KEY_AUDIO_MODE, adev->mode);
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -0800540 }
541
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -0800542 ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_ALL_CALL_STATES,
543 value, sizeof(value));
544 if (ret >= 0) {
545 ret = get_all_call_states_str(adev, value);
546 if (ret) {
547 ALOGE("%s: Error fetching call states, err:%d", __func__, ret);
548 return;
549 }
550 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_ALL_CALL_STATES, value);
551 }
Narsinga Rao Chella707e7512014-01-10 10:18:13 -0800552 voice_extn_compress_voip_get_parameters(adev, query, reply);
553
Krishnankutty Kolathappilly301cc362014-01-31 18:12:13 -0800554 str = str_parms_to_str(reply);
555 ALOGV_IF(str != NULL, "%s: exit: returns \"%s\"", __func__, str);
556 free(str);
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -0800557}
558
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800559void voice_extn_out_get_parameters(struct stream_out *out,
560 struct str_parms *query,
561 struct str_parms *reply)
562{
563 voice_extn_compress_voip_out_get_parameters(out, query, reply);
564}
565
566void voice_extn_in_get_parameters(struct stream_in *in,
567 struct str_parms *query,
568 struct str_parms *reply)
569{
570 voice_extn_compress_voip_in_get_parameters(in, query, reply);
571}
572
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700573int voice_extn_check_and_set_incall_music_usecase(struct audio_device *adev,
574 struct stream_out *out)
575{
576 uint32_t session_id = 0;
577
578 session_id = get_session_id_with_state(adev, CALL_LOCAL_HOLD);
579 if (session_id == VOICE_VSID) {
580 out->usecase = USECASE_INCALL_MUSIC_UPLINK;
581 } else if (session_id == VOICE2_VSID) {
582 out->usecase = USECASE_INCALL_MUSIC_UPLINK2;
583 } else {
584 ALOGE("%s: Invalid session id %x", __func__, session_id);
585 return -EINVAL;
586 }
587
588 out->config = pcm_config_incall_music;
589 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
590 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
591
592 return 0;
593}
594