summaryrefslogtreecommitdiffstats
path: root/hal/voice_extn/voice_extn.c
diff options
context:
space:
mode:
Diffstat (limited to 'hal/voice_extn/voice_extn.c')
-rw-r--r--hal/voice_extn/voice_extn.c585
1 files changed, 0 insertions, 585 deletions
diff --git a/hal/voice_extn/voice_extn.c b/hal/voice_extn/voice_extn.c
deleted file mode 100644
index 05c5fcbd..00000000
--- a/hal/voice_extn/voice_extn.c
+++ /dev/null
@@ -1,585 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "voice_extn"
-/*#define LOG_NDEBUG 0*/
-#define LOG_NDDEBUG 0
-
-#include <errno.h>
-#include <math.h>
-#include <cutils/log.h>
-#include <cutils/str_parms.h>
-#include <sys/ioctl.h>
-#include <sound/voice_params.h>
-
-#include "audio_hw.h"
-#include "voice.h"
-#include "platform.h"
-#include "platform_api.h"
-#include "voice_extn.h"
-
-#define AUDIO_PARAMETER_KEY_VSID "vsid"
-#define AUDIO_PARAMETER_KEY_CALL_STATE "call_state"
-#define AUDIO_PARAMETER_KEY_AUDIO_MODE "audio_mode"
-#define AUDIO_PARAMETER_KEY_ALL_CALL_STATES "all_call_states"
-#define AUDIO_PARAMETER_KEY_DEVICE_MUTE "device_mute"
-#define AUDIO_PARAMETER_KEY_DIRECTION "direction"
-
-#define VOICE_EXTN_PARAMETER_VALUE_MAX_LEN 256
-
-#define VOICE2_VSID 0x10DC1000
-#define VOLTE_VSID 0x10C02000
-#define QCHAT_VSID 0x10803000
-#define VOWLAN_VSID 0x10002000
-#define ALL_VSID 0xFFFFFFFF
-
-/* Voice Session Indices */
-#define VOICE2_SESS_IDX (VOICE_SESS_IDX + 1)
-#define VOLTE_SESS_IDX (VOICE_SESS_IDX + 2)
-#define QCHAT_SESS_IDX (VOICE_SESS_IDX + 3)
-#define VOWLAN_SESS_IDX (VOICE_SESS_IDX + 4)
-
-/* Call States */
-#define CALL_HOLD (BASE_CALL_STATE + 2)
-#define CALL_LOCAL_HOLD (BASE_CALL_STATE + 3)
-
-struct pcm_config pcm_config_incall_music = {
- .channels = 1,
- .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
- .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
- .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
- .format = PCM_FORMAT_S16_LE,
- .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
- .stop_threshold = INT_MAX,
- .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
-};
-
-extern int start_call(struct audio_device *adev, audio_usecase_t usecase_id);
-extern int stop_call(struct audio_device *adev, audio_usecase_t usecase_id);
-int voice_extn_is_in_call(struct audio_device *adev, bool *in_call);
-
-static bool is_valid_call_state(int call_state)
-{
- if (call_state < CALL_INACTIVE || call_state > CALL_LOCAL_HOLD)
- return false;
- else
- return true;
-}
-
-static bool is_valid_vsid(uint32_t vsid)
-{
- if (vsid == VOICE_VSID ||
- vsid == VOICE2_VSID ||
- vsid == VOLTE_VSID ||
- vsid == QCHAT_VSID ||
- vsid == VOWLAN_VSID)
- return true;
- else
- return false;
-}
-
-static audio_usecase_t voice_extn_get_usecase_for_session_idx(const int index)
-{
- audio_usecase_t usecase_id = -1;
-
- switch(index) {
- case VOICE_SESS_IDX:
- usecase_id = USECASE_VOICE_CALL;
- break;
-
- case VOICE2_SESS_IDX:
- usecase_id = USECASE_VOICE2_CALL;
- break;
-
- case VOLTE_SESS_IDX:
- usecase_id = USECASE_VOLTE_CALL;
- break;
-
- case QCHAT_SESS_IDX:
- usecase_id = USECASE_QCHAT_CALL;
- break;
-
- case VOWLAN_SESS_IDX:
- usecase_id = USECASE_VOWLAN_CALL;
- break;
-
- default:
- ALOGE("%s: Invalid voice session index\n", __func__);
- }
-
- return usecase_id;
-}
-
-static uint32_t get_session_id_with_state(struct audio_device *adev,
- int call_state)
-{
- struct voice_session *session = NULL;
- int i = 0;
- uint32_t session_id = 0;
-
- for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
- session = &adev->voice.session[i];
- if(session->state.current == call_state){
- session_id = session->vsid;
- break;
- }
- }
-
- return session_id;
-}
-
-static int update_calls(struct audio_device *adev)
-{
- int i = 0;
- audio_usecase_t usecase_id = 0;
- enum voice_lch_mode lch_mode;
- struct voice_session *session = NULL;
- int fd = 0;
- int ret = 0;
- bool is_in_call = false;
-
- ALOGD("%s: enter:", __func__);
-
- for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
- usecase_id = voice_extn_get_usecase_for_session_idx(i);
- session = &adev->voice.session[i];
- ALOGD("%s: cur_state=%d new_state=%d vsid=%x",
- __func__, session->state.current, session->state.new, session->vsid);
-
- switch(session->state.new)
- {
- case CALL_ACTIVE:
- switch(session->state.current)
- {
- case CALL_INACTIVE:
- ALOGD("%s: INACTIVE -> ACTIVE vsid:%x", __func__, session->vsid);
- ret = start_call(adev, usecase_id);
- if(ret < 0) {
- ALOGE("%s: voice_start_call() failed for usecase: %d\n",
- __func__, usecase_id);
- } else {
- session->state.current = session->state.new;
- }
- break;
-
- case CALL_HOLD:
- ALOGD("%s: HOLD -> ACTIVE vsid:%x", __func__, session->vsid);
- session->state.current = session->state.new;
- break;
-
- case CALL_LOCAL_HOLD:
- ALOGD("%s: LOCAL_HOLD -> ACTIVE vsid:%x", __func__, session->vsid);
- lch_mode = VOICE_LCH_STOP;
- if (pcm_ioctl(session->pcm_tx, SNDRV_VOICE_IOCTL_LCH, &lch_mode) < 0) {
- ALOGE("LOCAL_HOLD -> ACTIVE failed");
- } else {
- session->state.current = session->state.new;
- }
- break;
-
- default:
- ALOGV("%s: CALL_ACTIVE cannot be handled in state=%d vsid:%x",
- __func__, session->state.current, session->vsid);
- break;
- }
- break;
-
- case CALL_INACTIVE:
- switch(session->state.current)
- {
- case CALL_ACTIVE:
- case CALL_HOLD:
- case CALL_LOCAL_HOLD:
- ALOGD("%s: ACTIVE/HOLD/LOCAL_HOLD -> INACTIVE vsid:%x", __func__, session->vsid);
- ret = stop_call(adev, usecase_id);
- if(ret < 0) {
- ALOGE("%s: voice_end_call() failed for usecase: %d\n",
- __func__, usecase_id);
- } else {
- voice_extn_is_in_call(adev, &is_in_call);
- if (!is_in_call) {
- adev->voice.voice_device_set = false;
- }
- session->state.current = session->state.new;
- }
- break;
-
- default:
- ALOGV("%s: CALL_INACTIVE cannot be handled in state=%d vsid:%x",
- __func__, session->state.current, session->vsid);
- break;
- }
- break;
-
- case CALL_HOLD:
- switch(session->state.current)
- {
- case CALL_ACTIVE:
- ALOGD("%s: CALL_ACTIVE -> HOLD vsid:%x", __func__, session->vsid);
- session->state.current = session->state.new;
- break;
-
- case CALL_LOCAL_HOLD:
- ALOGD("%s: CALL_LOCAL_HOLD -> HOLD vsid:%x", __func__, session->vsid);
- lch_mode = VOICE_LCH_STOP;
- if (pcm_ioctl(session->pcm_tx, SNDRV_VOICE_IOCTL_LCH, &lch_mode) < 0) {
- ALOGE("LOCAL_HOLD -> HOLD failed");
- } else {
- session->state.current = session->state.new;
- }
- break;
-
- default:
- ALOGV("%s: CALL_HOLD cannot be handled in state=%d vsid:%x",
- __func__, session->state.current, session->vsid);
- break;
- }
- break;
-
- case CALL_LOCAL_HOLD:
- switch(session->state.current)
- {
- case CALL_ACTIVE:
- case CALL_HOLD:
- ALOGD("%s: ACTIVE/CALL_HOLD -> LOCAL_HOLD vsid:%x", __func__,
- session->vsid);
- lch_mode = VOICE_LCH_START;
- if (pcm_ioctl(session->pcm_tx, SNDRV_VOICE_IOCTL_LCH, &lch_mode) < 0) {
- ALOGE("LOCAL_HOLD -> HOLD failed");
- } else {
- session->state.current = session->state.new;
- }
- break;
-
- default:
- ALOGV("%s: CALL_LOCAL_HOLD cannot be handled in state=%d vsid:%x",
- __func__, session->state.current, session->vsid);
- break;
- }
- break;
-
- default:
- break;
- } //end out switch loop
- } //end for loop
-
- return ret;
-}
-
-static int update_call_states(struct audio_device *adev,
- const uint32_t vsid, const int call_state)
-{
- struct voice_session *session = NULL;
- int i = 0;
- bool is_in_call;
- int no_of_calls_active = 0;
-
- for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
- if (vsid == adev->voice.session[i].vsid) {
- session = &adev->voice.session[i];
- break;
- }
- }
-
- for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
- if (CALL_INACTIVE != adev->voice.session[i].state.current)
- no_of_calls_active++;
- }
-
- if (session) {
- session->state.new = call_state;
- voice_extn_is_in_call(adev, &is_in_call);
- ALOGD("%s is_in_call:%d voice_device_set:%d, mode:%d\n",
- __func__, is_in_call, adev->voice.voice_device_set, adev->mode);
- /* Dont start voice call before device routing for voice usescases has
- * occured, otherwise voice calls will be started unintendedly on
- * speaker.
- */
- if (is_in_call || adev->voice.voice_device_set) {
- /* Device routing is not triggered for voice calls on the subsequent
- * subs, Hence update the call states if voice call is already
- * active on other sub.
- */
- update_calls(adev);
- }
- } else {
- return -EINVAL;
- }
-
- return 0;
-
-}
-
-int voice_extn_get_active_session_id(struct audio_device *adev,
- uint32_t *session_id)
-{
- *session_id = get_session_id_with_state(adev, CALL_ACTIVE);
- return 0;
-}
-
-int voice_extn_is_in_call(struct audio_device *adev, bool *in_call)
-{
- struct voice_session *session = NULL;
- int i = 0;
- *in_call = false;
-
- for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
- session = &adev->voice.session[i];
- if(session->state.current != CALL_INACTIVE){
- *in_call = true;
- break;
- }
- }
-
- return 0;
-}
-
-int voice_extn_is_in_call_rec_stream(struct stream_in *in, bool *in_call_rec)
-{
- *in_call_rec = false;
-
- if(in->source == AUDIO_SOURCE_VOICE_DOWNLINK ||
- in->source == AUDIO_SOURCE_VOICE_UPLINK ||
- in->source == AUDIO_SOURCE_VOICE_CALL) {
- *in_call_rec = true;
- }
-
- return 0;
-}
-
-void voice_extn_init(struct audio_device *adev)
-{
- adev->voice.session[VOICE_SESS_IDX].vsid = VOICE_VSID;
- adev->voice.session[VOICE2_SESS_IDX].vsid = VOICE2_VSID;
- adev->voice.session[VOLTE_SESS_IDX].vsid = VOLTE_VSID;
- adev->voice.session[QCHAT_SESS_IDX].vsid = QCHAT_VSID;
- adev->voice.session[VOWLAN_SESS_IDX].vsid = VOWLAN_VSID;
-}
-
-int voice_extn_get_session_from_use_case(struct audio_device *adev,
- const audio_usecase_t usecase_id,
- struct voice_session **session)
-{
-
- switch(usecase_id)
- {
- case USECASE_VOICE_CALL:
- *session = &adev->voice.session[VOICE_SESS_IDX];
- break;
-
- case USECASE_VOICE2_CALL:
- *session = &adev->voice.session[VOICE2_SESS_IDX];
- break;
-
- case USECASE_VOLTE_CALL:
- *session = &adev->voice.session[VOLTE_SESS_IDX];
- break;
-
- case USECASE_QCHAT_CALL:
- *session = &adev->voice.session[QCHAT_SESS_IDX];
- break;
-
- case USECASE_VOWLAN_CALL:
- *session = &adev->voice.session[VOWLAN_SESS_IDX];
- break;
-
- default:
- ALOGE("%s: Invalid usecase_id:%d\n", __func__, usecase_id);
- *session = NULL;
- return -EINVAL;
- }
-
- return 0;
-}
-
-int voice_extn_start_call(struct audio_device *adev)
-{
- /* Start voice calls on sessions whose call state has been
- * udpated.
- */
- ALOGV("%s: enter:", __func__);
- adev->voice.voice_device_set = true;
- return update_calls(adev);
-}
-
-int voice_extn_stop_call(struct audio_device *adev)
-{
- int i;
- int ret = 0;
-
- ALOGV("%s: enter:", __func__);
-
- /* If BT device is enabled and voice calls are ended, telephony will call
- * set_mode(AUDIO_MODE_NORMAL) which will trigger audio policy manager to
- * set routing with device BT A2DP profile. Hence end all voice calls when
- * set_mode(AUDIO_MODE_NORMAL) before BT A2DP profile is selected.
- */
- if (adev->mode == AUDIO_MODE_NORMAL) {
- ALOGD("%s: end all calls", __func__);
- for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
- adev->voice.session[i].state.new = CALL_INACTIVE;
- }
-
- ret = update_calls(adev);
- }
-
- return ret;
-}
-
-int voice_extn_set_parameters(struct audio_device *adev,
- struct str_parms *parms)
-{
- char *str;
- int value;
- int ret = 0, err;
- char *kv_pairs = str_parms_to_str(parms);
- char str_value[256] = {0};
-
- ALOGV_IF(kv_pairs != NULL, "%s: enter: %s", __func__, kv_pairs);
-
- err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_VSID, &value);
- if (err >= 0) {
- str_parms_del(parms, AUDIO_PARAMETER_KEY_VSID);
- uint32_t vsid = value;
- int call_state = -1;
- err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_CALL_STATE, &value);
- if (err >= 0) {
- call_state = value;
- } else {
- ALOGE("%s: call_state key not found", __func__);
- ret = -EINVAL;
- goto done;
- }
-
- if (is_valid_vsid(vsid) && is_valid_call_state(call_state)) {
- ret = update_call_states(adev, vsid, call_state);
- } else {
- ALOGE("%s: invalid vsid:%x or call_state:%d",
- __func__, vsid, call_state);
- ret = -EINVAL;
- goto done;
- }
- }
-
- err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_DEVICE_MUTE, str_value,
- sizeof(str_value));
- if (err >= 0) {
- str_parms_del(parms, AUDIO_PARAMETER_KEY_DEVICE_MUTE);
- bool mute = false;
-
- if (!strncmp("true", str_value, sizeof("true"))) {
- mute = true;
- }
-
- err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_DIRECTION, str_value,
- sizeof(str_value));
- if (err >= 0) {
- str_parms_del(parms, AUDIO_PARAMETER_KEY_DIRECTION);
- } else {
- ALOGE("%s: direction key not found", __func__);
- ret = -EINVAL;
- goto done;
- }
-
- ret = platform_set_device_mute(adev->platform, mute, str_value);
- if (ret != 0) {
- ALOGE("%s: Failed to set mute err:%d", __func__, ret);
- ret = -EINVAL;
- goto done;
- }
- }
-
-done:
- ALOGV("%s: exit with code(%d)", __func__, ret);
- free(kv_pairs);
- return ret;
-}
-
-static int get_all_call_states_str(const struct audio_device *adev,
- char *value)
-{
- int ret = 0;
- char *cur_ptr = value;
- int i, len=0;
-
- for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
- snprintf(cur_ptr, VOICE_EXTN_PARAMETER_VALUE_MAX_LEN - len,
- "%d:%d,",adev->voice.session[i].vsid,
- adev->voice.session[i].state.current);
- len = strlen(cur_ptr);
- cur_ptr = cur_ptr + len;
- }
- ALOGV("%s:value=%s", __func__, value);
- return ret;
-}
-
-void voice_extn_get_parameters(const struct audio_device *adev,
- struct str_parms *query,
- struct str_parms *reply)
-{
- int ret;
- char value[VOICE_EXTN_PARAMETER_VALUE_MAX_LEN] = {0};
- char *str = str_parms_to_str(query);
-
- ALOGV_IF(str != NULL, "%s: enter %s", __func__, str);
- free(str);
-
- ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_AUDIO_MODE, value,
- sizeof(value));
- if (ret >= 0) {
- str_parms_add_int(reply, AUDIO_PARAMETER_KEY_AUDIO_MODE, adev->mode);
- }
-
- ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_ALL_CALL_STATES,
- value, sizeof(value));
- if (ret >= 0) {
- ret = get_all_call_states_str(adev, value);
- if (ret) {
- ALOGE("%s: Error fetching call states, err:%d", __func__, ret);
- return;
- }
- str_parms_add_str(reply, AUDIO_PARAMETER_KEY_ALL_CALL_STATES, value);
- }
-
- str = str_parms_to_str(reply);
- ALOGV_IF(str != NULL, "%s: exit: returns \"%s\"", __func__, str);
- free(str);
-}
-
-#ifdef INCALL_MUSIC_ENABLED
-int voice_extn_check_and_set_incall_music_usecase(struct audio_device *adev,
- struct stream_out *out)
-{
- uint32_t session_id = 0;
-
- session_id = get_session_id_with_state(adev, CALL_LOCAL_HOLD);
- if (session_id == VOICE_VSID) {
- out->usecase = USECASE_INCALL_MUSIC_UPLINK;
- } else if (session_id == VOICE2_VSID) {
- out->usecase = USECASE_INCALL_MUSIC_UPLINK2;
- } else {
- ALOGE("%s: Invalid session id %x", __func__, session_id);
- return -EINVAL;
- }
-
- out->config = pcm_config_incall_music;
- out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
- out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
-
- return 0;
-}
-#endif
-