blob: 961b8c3d67feb6ce05a7c6b638dcee38fe2137bd [file] [log] [blame]
/******************************************************************************
*(C) Copyright 2014 Marvell International Ltd.
* All Rights Reserved
******************************************************************************/
/* -------------------------------------------------------------------------------------------------------------------
*
* Filename: audio_if_ubus.c
*
* Authors: tzahi stern
*
* Description: This file handle all interface with UBUS for audio_if such as:
* 1. open ubus server for audio_if
* 2. register as ubus clent for RIL indication
* 3. create a thread for handling requests from audioHAL toward ubus
*
* HISTORY:
*
*
* Notes:
*
******************************************************************************/
/******************************************************************************
* Include files
******************************************************************************/
#include "audio_if_types.h"
#include "audio_if_ubus.h"
#include "audio_if_parameter.h"
#include "audio_if.h"
#include "audio_if_api.h"
#include "telephony/ril.h"
#include "audio_if_audio_hw_mrvl.h"
#include "audio_pa.h"
#include "rilutil.h"
#include <signal.h>
#include <time.h>
/******************************************************************************
* Macros / Defines
******************************************************************************/
#define RIL_UBUS_ID "ril"
#define RIL_UBUS_REQ "ril_request"
/*#define RIL_EVENT_PREFIX "ril.unsol."*/
#define AUDIOIFREQID "reqid"
#define AUDIOIFRESPID "audioifid"
#define AUDIOIFRESPERRNO "resperrno"
#define AUDIO_IF_CALLMAX 9 //Max call index is 8
const char *RIL_MessageMap[] =
{
"RIL_CALL_ACTIVE", //0,
"RIL_CALL_HOLDING", //1,
"RIL_CALL_DIALING", //2, /* MO call only */
"RIL_CALL_ALERTING", //3, /* MO call only */
"RIL_CALL_INCOMING", //4, /* MT call only */
"RIL_CALL_WAITING", //5, /* MT call only */
"RIL_CALL_OFFERING", //6, /* MT call offering (call setup) */
"RIL_CALL_DISCONNECTING",//7, /* call in disconnect procedure */
"RIL_CALL_DISCONNECTED" //8, /* call is disconnected */
};
#define AUDIO_IF_UBUS_SUBSCRIBE_EVENT(x,s) \
{ \
int local_ret; \
uint32_t local_id; \
if (ubus_lookup_id(x.ctx, s, &local_id)) { \
AUDIO_IF_LOGE("ubus subscribe FAILED to lookup object: %s", s); \
} else { \
local_ret = ubus_subscribe(x.ctx, &x.ind_event, local_id); \
AUDIO_IF_LOGD("ubus subscribe Watching object %s %08x: %s", s, \
local_id, ubus_strerror(local_ret)); \
} \
}/*endM*/
#define AUDIO_IF_UBUS_UNSUBSCRIBE_EVENT(x,s) \
{ \
uint32_t local_id; \
if (!ubus_lookup_id(x.ctx, s, &local_id)) \
ubus_subscribe(x.ctx, &x.ind_event, local_id); \
}/*endM*/
/******************************************************************************
* enum
******************************************************************************/
enum {
AUDIO_IF_REQID,
AUDIO_IF_DATA,
_AUDIO_IF_MAX
};
/******************************************************************************
* Prototypes
******************************************************************************/
/**************** ubus utility API ************/
static void AudioIf_uBussubscribeCb(struct ubus_context *ctx, struct ubus_object *obj);
static int AudioIf_uBusInd_RIL(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg);
extern void AudioIf_ReadFromDevice(int fd);
/******************************************************************************
* Globals
******************************************************************************/
extern audio_hw_device_t *ahw_dev_ubus;
extern struct mrvl_audio_device *mrvl_ahw_dev_ubus;
static struct uloop_fd audio_if_fd;
extern audioIfReqDb_t audioIfReqDb;
extern audioIfUbusDb_t audioIfUbusDb;
extern AUDIO_IF_DATABASE audioIfDb;
extern pthread_mutex_t req_data_mutex;
extern pthread_mutex_t AudioIf_mutex;
/*****************************************************\
* Call State
* 0: idle
* 1: active
* 2: hold
* 3: alerting
\*****************************************************/
int AUDIO_IF_CallIndexState[AUDIO_IF_CALLMAX] = {0};
/**************** supported policies ************/
const struct blobmsg_policy int_policy[PARAM_INT_POLICY_MAX] ={
[PARAM_INT_POLICY_0] = {
.name = "param0",
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_INT_POLICY_1] = {
.name = "param1",
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_INT_POLICY_2] = {
.name = "param2",
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_INT_POLICY_3] = {
.name = "param3",
.type = BLOBMSG_TYPE_INT32,
},
};
const struct blobmsg_policy ecall_data_set_policy[] ={
[PARAM_ECALL_DATA_SET_POLICY_0] = {
.name = "length", /* op+param1+data total length */
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_ECALL_DATA_SET_POLICY_1] = {
.name = "op", /* Operation to perform */
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_ECALL_DATA_SET_POLICY_2] = {
.name = "param1", /* The meaning depends on the op parameter. */
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_ECALL_DATA_SET_POLICY_3] = {
.name = "data", /* 140 bytes of data, corresponds to the MSD data to be sent */
.type = BLOBMSG_TYPE_STRING,
},
};
const struct blobmsg_policy ecall_data_get_policy[] ={
[PARAM_ECALL_DATA_GET_POLICY_0] = {
.name = "length", /* op+param1 total length */
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_ECALL_DATA_GET_POLICY_1] = {
.name = "op", /* Operation to perform */
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_ECALL_DATA_GET_POLICY_2] = {
.name = "param1", /* The meaning depends on the op parameter. */
.type = BLOBMSG_TYPE_INT32,
},
};
const struct blobmsg_policy ecall_data_get_reply_policy[] ={
[PARAM_ECALL_DATA_GET_REPLY_POLICY_0] = {
.name = "op", /* Operation to perform */
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_ECALL_DATA_GET_REPLY_POLICY_1] = {
.name = "param1", /* The meaning depends on the op parameter. */
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_ECALL_DATA_GET_REPLY_POLICY_2] = {
.name = "value1", /* Contains a returned eIM value according to eCall specifications. */
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_ECALL_DATA_GET_REPLY_POLICY_3] = {
.name = "value2", /* Contains an optional returned eIM value according to eCall specifications. */
.type = BLOBMSG_TYPE_INT32,
},
};
const struct blobmsg_policy ecall_voice_set_policy[] ={
[PARAM_ECALL_VOICE_SET_POLICY_0] = {
.name = "cmd_id", /* Type of operation */
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_ECALL_VOICE_SET_POLICY_1] = {
.name = "res_id", /* Voice resource identifier */
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_ECALL_VOICE_SET_POLICY_2] = {
.name = "param2", /* The meaning depends on the res_id parameter. */
.type = BLOBMSG_TYPE_INT32,
},
};
const struct blobmsg_policy ecall_voice_get_policy[] ={
[PARAM_ECALL_VOICE_GET_POLICY_0] = {
.name = "cmd_id", /* Type of operation */
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_ECALL_VOICE_GET_POLICY_1] = {
.name = "res_id", /* Voice resource identifier */
.type = BLOBMSG_TYPE_INT32,
},
};
const struct blobmsg_policy ecall_voice_get_reply_policy[] ={
[PARAM_ECALL_VOICE_GET_REPLY_POLICY_0] = {
.name = "cmd_id", /* Type of operation */
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_ECALL_VOICE_GET_REPLY_POLICY_1] = {
.name = "res_id", /* Voice resource identifier */
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_ECALL_VOICE_GET_REPLY_POLICY_2] = {
.name = "param2", /* The meaning depends on the res_id parameter. */
.type = BLOBMSG_TYPE_INT32,
},
};
const struct blobmsg_policy vcm_play_rec_policy[] ={
[PARAM_VCM_PLAY_REC_POLICY_0] = {
.name = "path", /* Up to 256 char path */
.type = BLOBMSG_TYPE_STRING,
},
};
const struct blobmsg_policy cp_loopback_enable_policy[] ={
[PARAM_INT_POLICY_0] = {
.name = "param0", /* Device. 0 - earpiece, 1 - speaker, 2 - headset */
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_INT_POLICY_1] = {
.name = "mode", /* Mode. 1 - loopback pcm, 2 - loopback packet/vocoder loop, *
* 3 - pcm loop without enhancement, 4 - vocoder loop without enhancement */
.type = BLOBMSG_TYPE_INT32,
},
};
const struct blobmsg_policy vcm_config_policy[] ={ /*TODO add difference configs for rec/playback */
[PARAM_VCM_CONFIG_POLICY_0] = {
.name = "direction", /* Chosen direction to configure. 0 - Output, 1 - Input */
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_VCM_CONFIG_POLICY_1] = {
.name = "type", /* Type of data package. 0 - PCM, 1 - PCM_WB */
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_VCM_CONFIG_POLICY_2] = {
.name = "srcdst", /* Location to rec/play from/to. 0 - None, 1 - Near end, *
* 2 - Far end, 3 - Both ends */
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_VCM_CONFIG_POLICY_3] = {
.name = "priority", /* Combine with call option. 0 - Do not combine (override), 1 - Combine *
* Not used in vcm recording */
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_VCM_CONFIG_POLICY_4] = {
.name = "dest", /* Which side of the dsp to connect. 0 - Near codec, 1 - Near vocoder */
.type = BLOBMSG_TYPE_INT32,
},
};
const struct blobmsg_policy switch_pcm_policy[] ={
[PARAM_INT_POLICY_0] = {
.name = "param0",
.type = BLOBMSG_TYPE_INT32,
},
};
const struct blobmsg_policy config_pcm_policy[] ={
[PARAM_INT_POLICY_0] = {
.name = "role",
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_INT_POLICY_1] = {
.name = "rate",
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_INT_POLICY_2] = {
.name = "bitclk",
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_INT_POLICY_3] = {
.name = "2slots",
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_INT_POLICY_4] = {
.name = "controller",
.type = BLOBMSG_TYPE_INT32,
},
};
const struct blobmsg_policy config_dspgain_policy[] ={
[PARAM_INT_POLICY_0] = {
.name = "type",
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_INT_POLICY_1] = {
.name = "gain",
.type = BLOBMSG_TYPE_INT32,
},
};
const struct blobmsg_policy config_pcmexpert_policy[] ={
[PARAM_PCMEXPERT_CONFIG_POLICY_0] = {
.name = "frame_format",
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_PCMEXPERT_CONFIG_POLICY_1] = {
.name = "invert_frame",
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_PCMEXPERT_CONFIG_POLICY_2] = {
.name = "frame_polarity",
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_PCMEXPERT_CONFIG_POLICY_3] = {
.name = "bitclk_polarity",
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_PCMEXPERT_CONFIG_POLICY_4] = {
.name = "fsyc_shift",
.type = BLOBMSG_TYPE_INT32,
},
};
const struct blobmsg_policy vcm_dtmfcontrol_policy[] ={
[PARAM_PCMEXPERT_CONFIG_POLICY_0] = {
.name = "on",
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_PCMEXPERT_CONFIG_POLICY_1] = {
.name = "tone1_index",
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_PCMEXPERT_CONFIG_POLICY_2] = {
.name = "tone2_index",
.type = BLOBMSG_TYPE_INT32,
},
};
const struct blobmsg_policy config_pa_policy[] ={
[PARAM_PCMEXPERT_CONFIG_POLICY_0] = {
.name = "on",
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_PCMEXPERT_CONFIG_POLICY_1] = {
.name = "gpio",
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_PCMEXPERT_CONFIG_POLICY_2] = {
.name = "delay_start",
.type = BLOBMSG_TYPE_INT32,
},
[PARAM_PCMEXPERT_CONFIG_POLICY_3] = {
.name = "delay_stop",
.type = BLOBMSG_TYPE_INT32,
},
};
#ifdef TARGET_mmp_asr1901_KSTR901
const struct blobmsg_policy adsp_set_policy[] ={
[PARAM_ADSP_SET_POLICY_0] = {
.name = "cmd", /* Up to 256 char*/
.type = BLOBMSG_TYPE_STRING,
},
};
#endif
/**************** supported methods ************/
static const struct ubus_method audio_if_methods[] = {
UBUS_METHOD(AUDIO_IF_UBUS_AUDIO_MODE_SET, audio_if_audio_mode_set, int_policy),
UBUS_METHOD(AUDIO_IF_UBUS_AUDIO_MODE_STATUS, audio_if_audio_mode_status, int_policy),
UBUS_METHOD(AUDIO_IF_UBUS_AUDIO_DEVICE_SET, audio_if_audio_device_set, int_policy),
UBUS_METHOD(AUDIO_IF_UBUS_AUDIO_DEVICE_STATUS, audio_if_audio_device_status, int_policy),
UBUS_METHOD(AUDIO_IF_UBUS_TTY_SET, audio_if_tty_set, int_policy),
UBUS_METHOD(AUDIO_IF_UBUS_VOLUME_SET, audio_if_volume_set, int_policy),
UBUS_METHOD(AUDIO_IF_UBUS_VOLUME_STATUS, audio_if_volume_status, int_policy),
UBUS_METHOD(AUDIO_IF_UBUS_MUTE_SET, audio_if_mute_set, int_policy),
UBUS_METHOD(AUDIO_IF_UBUS_MUTE_STATUS, audio_if_mute_status, int_policy),
UBUS_METHOD(AUDIO_IF_UBUS_ECALL_DATA_SET, audio_if_ecall_data_set, ecall_data_set_policy),
UBUS_METHOD(AUDIO_IF_UBUS_ECALL_DATA_STATUS, audio_if_ecall_data_status, ecall_data_get_policy),
UBUS_METHOD(AUDIO_IF_UBUS_ECALL_VOICE_SET, audio_if_ecall_voice_set, ecall_voice_set_policy ),
UBUS_METHOD(AUDIO_IF_UBUS_ECALL_VOICE_STATUS, audio_if_ecall_voice_status, ecall_voice_get_policy),
UBUS_METHOD(AUDIO_IF_UBUS_SWITCH_PCM, audio_if_switch_pcm, switch_pcm_policy),
UBUS_METHOD(AUDIO_IF_UBUS_VCM_REC_START, audio_if_vcm_rec_start, vcm_play_rec_policy),
UBUS_METHOD_NOARG(AUDIO_IF_UBUS_VCM_REC_STOP, audio_if_vcm_rec_stop),
UBUS_METHOD(AUDIO_IF_UBUS_VCM_PLAY_START, audio_if_vcm_play_start, vcm_play_rec_policy),
UBUS_METHOD_NOARG(AUDIO_IF_UBUS_VCM_PLAY_STOP, audio_if_vcm_play_stop),
UBUS_METHOD(AUDIO_IF_UBUS_CP_LOOPBACK_ENABLE, audio_if_cp_loopback_enable, cp_loopback_enable_policy),
UBUS_METHOD_NOARG(AUDIO_IF_UBUS_CP_LOOPBACK_DISABLE, audio_if_cp_loopback_disable),
UBUS_METHOD(AUDIO_IF_UBUS_VCM_CONFIG, audio_if_vcm_configure, vcm_config_policy),
UBUS_METHOD(AUDIO_IF_UBUS_DTMFDETECTION, audio_if_DTMFDetection, int_policy),
UBUS_METHOD(AUDIO_IF_UBUS_PCMLOOPBACK_START, audio_if_pcmloopback_start, vcm_play_rec_policy),
UBUS_METHOD_NOARG(AUDIO_IF_UBUS_PCMLOOPBACK_STOP, audio_if_pcmloopback_stop),
UBUS_METHOD(AUDIO_IF_UBUS_CONFIG_PCM, audio_if_config_pcm, config_pcm_policy),
UBUS_METHOD(AUDIO_IF_UBUS_CONFIG_DSPGAIN, audio_if_config_dspgain, config_dspgain_policy),
UBUS_METHOD(AUDIO_IF_UBUS_CONFIG_PCMEXPERT, audio_if_config_pcmexpert, config_pcmexpert_policy),
UBUS_METHOD(AUDIO_IF_UBUS_DTMFCONTROL, audio_if_DTMFControl, vcm_dtmfcontrol_policy),
UBUS_METHOD(AUDIO_IF_UBUS_REPORT_VOICE_STATUS, audio_if_report_voice_status, int_policy),
UBUS_METHOD(AUDIO_IF_UBUS_RELOAD_NVM, audio_if_reload_nvm, int_policy),
UBUS_METHOD(AUDIO_IF_UBUS_CONFIG_PA, audio_if_config_pa, config_pa_policy),
#ifdef TARGET_mmp_asr1901_KSTR901
UBUS_METHOD(AUDIO_IF_UBUS_ADSP_SET, audio_if_adsp_set, adsp_set_policy),
UBUS_METHOD_NOARG(AUDIO_IF_UBUS_ADSP_SEND_VE, audio_if_adsp_send_ve),
UBUS_METHOD(AUDIO_IF_UBUS_ADSP_DUMP_FULL_DDR, audio_if_adsp_dump_full_ddr, int_policy),
#endif
};
static struct ubus_object_type server_object_type =
UBUS_OBJECT_TYPE(AUDIO_IF_UBUS_ID, audio_if_methods);
static bool Codec_Enabled = FALSE;
/******************************************************************************
* Code
******************************************************************************/
void AudioIf_uBussubscribeCb(struct ubus_context *ctx, struct ubus_object *obj)
{
UNUSEDPARAM(ctx);
UNUSEDPARAM(obj);
AUDIO_IF_LOGD("has_subscribers:%s\n", __FUNCTION__, obj->has_subscribers?"true":"false");
}
/*******************************************************************************\
* Function: AUDIO_IF_CallActiveCount
* Description: Return active call count.
* Returns: active call count
\*******************************************************************************/
static int AUDIO_IF_CallActiveCount(void)
{
int i, cnt = 0;
for(i=0; i<AUDIO_IF_CALLMAX; i++)
{
if(AUDIO_IF_CallIndexState[i] == AUDIO_IF_CALLINDEX_ACTIVE)
{
AUDIO_IF_LOGD("%s, active call index=%d\n", __FUNCTION__, i);
cnt++;
}
}
AUDIO_IF_LOGD("%s, active call count=%d\n", __FUNCTION__, cnt);
return cnt;
}
/*******************************************************************************\
* Function: AUDIO_IF_CallHoldCount
* Description: Return hold call count.
* Returns: hold call count
\*******************************************************************************/
static int AUDIO_IF_CallHoldCount(void)
{
int i, cnt = 0;
for(i=0; i<AUDIO_IF_CALLMAX; i++)
{
if(AUDIO_IF_CallIndexState[i] == AUDIO_IF_CALLINDEX_HOLD)
{
AUDIO_IF_LOGD("%s, hold call index=%d\n", __FUNCTION__, i);
cnt++;
}
}
AUDIO_IF_LOGD("%s, hold call count=%d\n", __FUNCTION__, cnt);
return cnt;
}
/*******************************************************************************\
* Function: AUDIO_IF_CallAlertingCount
* Description: Return alerting call count.
* Returns: alerting call count
\*******************************************************************************/
static int AUDIO_IF_CallAlertingCount(void)
{
int i, cnt = 0;
for(i=0; i<AUDIO_IF_CALLMAX; i++)
{
if(AUDIO_IF_CallIndexState[i] == AUDIO_IF_CALLINDEX_ALERTING)
{
AUDIO_IF_LOGD("%s, alerting call index=%d\n", __FUNCTION__, i);
cnt++;
}
}
AUDIO_IF_LOGD("%s, alerting call count=%d\n", __FUNCTION__, cnt);
return cnt;
}
/*******************************************************************************\
* Function: AUDIO_IF_CallWaitingCount
* Description: Return waiting call count.
* Returns: waiting call count
\*******************************************************************************/
static int AUDIO_IF_CallWaitingCount(void)
{
int i, cnt = 0;
for(i=0; i<AUDIO_IF_CALLMAX; i++)
{
if(AUDIO_IF_CallIndexState[i] == AUDIO_IF_CALLINDEX_WAITING)
{
AUDIO_IF_LOGD("%s, waiting call index=%d\n", __FUNCTION__, i);
cnt++;
}
}
AUDIO_IF_LOGD("%s, waiting call count=%d\n", __FUNCTION__, cnt);
return cnt;
}
/*******************************************************************************\
* Function: AudioIf_uBusInd_RIL
* Description: This function is called upon RIL incoming indication.
* Returns: 0 on success
\*******************************************************************************/
static int AudioIf_uBusInd_RIL(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
unsigned int requestid;
unsigned int rilerrno;
void *data = NULL;
int datalen;
int ret;
int callID = 0;
int active_cnt = 0, hold_cnt = 0, alerting_cnt = 0, waiting_cnt = 0;
RIL_CallState call_state = RIL_CALL_DISCONNECTED;
UNUSEDPARAM(ctx);
UNUSEDPARAM(obj);
UNUSEDPARAM(req);
UNUSEDPARAM(method);
ret = rilutil_parseResponse(msg, &requestid, &rilerrno, &data, &datalen);
if (ret) {
AUDIO_IF_LOGE("parse msg error\n");
goto end;
}
if (rilerrno) {
AUDIO_IF_LOGE("unsolicited id %d, error code %d\n", requestid, rilerrno);
ret = -1;
goto end;
}
/*
* RIL indication relevant for audio_if
* to be implemented in audio_if/audio_if_api.c
*/
switch (requestid)
{
case RIL_UNSOL_CALL_STATUS_INFO: /*"CC" 1530*/
{
RIL_Call_Ext *rilCall_Ext = (RIL_Call_Ext *)data;
callID = rilCall_Ext->index;
call_state = rilCall_Ext->state;
AUDIO_IF_LOGD("%s: id %d=RIL_UNSOL_CALL_STATUS_INFO (len=%d) (state=%s), call index=%d\n",
__FUNCTION__, requestid, datalen,RIL_MessageMap[(int)rilCall_Ext->state], callID);
switch (rilCall_Ext->state)
{
//Call connected, for MO & MT both
case RIL_CALL_ACTIVE:
if(callID < AUDIO_IF_CALLMAX)
{
AUDIO_IF_LOGD("%s, call index=%d connected!!\n", __FUNCTION__, callID);
AUDIO_IF_CallIndexState[callID] = AUDIO_IF_CALLINDEX_ACTIVE;
}
break;
//MT call only
case RIL_CALL_INCOMING:
break;
//MO call only
case RIL_CALL_ALERTING:
if(callID < AUDIO_IF_CALLMAX)
{
AUDIO_IF_LOGD("%s, call index=%d alerting!!\n", __FUNCTION__, callID);
AUDIO_IF_CallIndexState[callID] = AUDIO_IF_CALLINDEX_ALERTING;
}
break;
//MT call only
case RIL_CALL_WAITING:
if(callID < AUDIO_IF_CALLMAX)
{
AUDIO_IF_LOGD("%s, call index=%d waiting!!\n", __FUNCTION__, callID);
AUDIO_IF_CallIndexState[callID] = AUDIO_IF_CALLINDEX_WAITING;
}
break;
case RIL_CALL_DISCONNECTED:
if(callID < AUDIO_IF_CALLMAX)
{
AUDIO_IF_LOGD("%s, call index=%d disconnected!!\n", __FUNCTION__, callID);
AUDIO_IF_CallIndexState[callID] = AUDIO_IF_CALLINDEX_IDLE;
}
break;
case RIL_CALL_HOLDING:
if(callID < AUDIO_IF_CALLMAX)
{//Call hold
AUDIO_IF_LOGD("%s, call index=%d hold!!\n", __FUNCTION__, callID);
AUDIO_IF_CallIndexState[callID] = AUDIO_IF_CALLINDEX_HOLD;
}
break;
case RIL_CALL_DIALING: //MO call only
case RIL_CALL_OFFERING:
case RIL_CALL_DISCONNECTING:
default:
AUDIO_IF_LOGD("%s, state=%s ignored!!\n", __FUNCTION__, RIL_MessageMap[(int)rilCall_Ext->state]);
break;
}
}
break;
case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED_EXT: /*"CC" 1510*/
{
RIL_Call *rilCall = (RIL_Call *)data;
callID = rilCall->index;
call_state = rilCall->state;
AUDIO_IF_LOGD("%s: id %d=RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED_EXT (len=%d) (state=%s), call index=%d\n",
__FUNCTION__, requestid, datalen,RIL_MessageMap[(int)rilCall->state], callID);
switch (rilCall->state)
{
//Call connected, for MO & MT both
case RIL_CALL_ACTIVE:
if(callID < AUDIO_IF_CALLMAX)
{
AUDIO_IF_LOGD("%s, call index=%d connected!!\n", __FUNCTION__, callID);
AUDIO_IF_CallIndexState[callID] = AUDIO_IF_CALLINDEX_ACTIVE;
}
break;
//MT call only
case RIL_CALL_INCOMING:
break;
//MO call only
case RIL_CALL_ALERTING:
if(callID < AUDIO_IF_CALLMAX)
{
AUDIO_IF_LOGD("%s, call index=%d alerting!!\n", __FUNCTION__, callID);
AUDIO_IF_CallIndexState[callID] = AUDIO_IF_CALLINDEX_ALERTING;
}
break;
case RIL_CALL_WAITING: //MT call only
if(callID < AUDIO_IF_CALLMAX)
{
AUDIO_IF_LOGD("%s, call index=%d waiting!!\n", __FUNCTION__, callID);
AUDIO_IF_CallIndexState[callID] = AUDIO_IF_CALLINDEX_WAITING;
}
break;
case RIL_CALL_DISCONNECTED:
if(callID < AUDIO_IF_CALLMAX)
{
AUDIO_IF_LOGD("%s, call index=%d disconnected!!\n", __FUNCTION__, callID);
AUDIO_IF_CallIndexState[callID] = AUDIO_IF_CALLINDEX_IDLE;
}
break;
case RIL_CALL_HOLDING:
if(callID < AUDIO_IF_CALLMAX)
{//Call hold
AUDIO_IF_LOGD("%s, call index=%d hold!!\n", __FUNCTION__, callID);
AUDIO_IF_CallIndexState[callID] = AUDIO_IF_CALLINDEX_HOLD;
}
break;
case RIL_CALL_DIALING: //MO call only
case RIL_CALL_OFFERING:
case RIL_CALL_DISCONNECTING:
default:
AUDIO_IF_LOGD("%s, state=%s ignored!!\n", __FUNCTION__, RIL_MessageMap[(int)rilCall->state]);
break;
}
}
break;
case RIL_UNSOL_CALL_NO_CARRIER_EXT: /*"CC" 1511*/
AUDIO_IF_LOGD("%s: id %d=RIL_UNSOL_CALL_NO_CARRIER_EXT (len=%d)\n",
__FUNCTION__, requestid, datalen);
break;
case RIL_UNSOL_CALL_RING: /*"CC" 1018*/
AUDIO_IF_LOGD("%s: id %d=RIL_UNSOL_CALL_RING (len=%d), ignored!!\n",
__FUNCTION__, requestid, datalen);
break;
case RIL_UNSOL_DISCONNECT_CALLID: /*"CC" 1538*/
AUDIO_IF_LOGD("%s: id %d=RIL_UNSOL_DISCONNECT_CALLID (len=%d), call index=%d!\n",
__FUNCTION__, requestid, datalen, *(int *)data);
callID = *(int *)data;
if(callID < AUDIO_IF_CALLMAX)
{
AUDIO_IF_CallIndexState[callID] = AUDIO_IF_CALLINDEX_IDLE;
}
break;
default:
AUDIO_IF_LOGD("%s: id %d (len=%d), ignored!!\n", __FUNCTION__, requestid, datalen); //1505...
break;
}
active_cnt = AUDIO_IF_CallActiveCount();
hold_cnt = AUDIO_IF_CallHoldCount();
alerting_cnt = AUDIO_IF_CallAlertingCount();
waiting_cnt = AUDIO_IF_CallWaitingCount();
AUDIO_IF_LOGD("%s: id=%d, (state=%s), call index=%d, active_cnt=%d, hold_cnt=%d, alerting_cnt=%d, waiting_cnt=%d!\n",
__FUNCTION__, requestid, RIL_MessageMap[(int)call_state], callID,
active_cnt, hold_cnt, alerting_cnt, waiting_cnt);
switch (requestid)
{
case RIL_UNSOL_CALL_STATUS_INFO: /*"CC" 1530*/
case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED_EXT: /*"CC" 1510*/
{
RIL_CallState state = *(RIL_CallState *)data;
AUDIO_IF_LOGD("%s: id=%d(len=%d), state=%d(%s)", __FUNCTION__, requestid, datalen,state, RIL_MessageMap[(int)state]);
switch (state)
{
case RIL_CALL_DIALING: /* MO call only */
case RIL_CALL_INCOMING: /* MT call only */
if(FALSE == Codec_Enabled)
{
AUDIO_IF_LOGD("%s: open codec voice path, out_device=%d, madev->in_call=%d, madev->in_hfp=%d, madev->mode=%d",
__FUNCTION__, mrvl_ahw_dev_ubus->out_device, mrvl_ahw_dev_ubus->in_call, mrvl_ahw_dev_ubus->in_hfp, mrvl_ahw_dev_ubus->mode);
pthread_mutex_lock(&AudioIf_mutex);
mrvl_ahw_dev_ubus->device.set_mode(ahw_dev_ubus, AUDIO_MODE_IN_CALL);
if(AUDIO_DEVICE_OUT_EARPIECE == mrvl_ahw_dev_ubus->out_device
|| AUDIO_DEVICE_OUT_SPEAKER == mrvl_ahw_dev_ubus->out_device) {
audio_pa_enable(AUDIO_PA_VOICE);
}
/*Set Volume after starting call just like doing in APSE (android)*/
mrvl_ahw_dev_ubus->device.set_voice_volume(ahw_dev_ubus, mrvl_ahw_dev_ubus->voice_volume);
pthread_mutex_unlock(&AudioIf_mutex);
Codec_Enabled = TRUE;
}
break;
case RIL_CALL_ALERTING:
case RIL_CALL_ACTIVE:
case RIL_CALL_HOLDING:
case RIL_CALL_WAITING:
case RIL_CALL_OFFERING:
case RIL_CALL_DISCONNECTING:
case RIL_CALL_DISCONNECTED:
default:
AUDIO_IF_LOGD("%s: state=%d(%s) ignored!!\n", __FUNCTION__, state, RIL_MessageMap[(int)state]);
break;
}
}
break;
case RIL_UNSOL_CALL_NO_CARRIER_EXT: /*"CC" 1511*/
if ((0 == active_cnt) && (0 == hold_cnt) && (0 == waiting_cnt))
{
if(TRUE == Codec_Enabled)
{
AUDIO_IF_LOGD("%s: id=%d(len=%d), close codec voice path, out_device=%d, madev->in_call=%d, madev->in_hfp=%d, madev->mode=%d",
__FUNCTION__, requestid, datalen, mrvl_ahw_dev_ubus->out_device, mrvl_ahw_dev_ubus->in_call, mrvl_ahw_dev_ubus->in_hfp, mrvl_ahw_dev_ubus->mode);
pthread_mutex_lock(&AudioIf_mutex);
if(AUDIO_DEVICE_OUT_EARPIECE == mrvl_ahw_dev_ubus->out_device
|| AUDIO_DEVICE_OUT_SPEAKER == mrvl_ahw_dev_ubus->out_device) {
audio_pa_disable(AUDIO_PA_VOICE);
}
mrvl_ahw_dev_ubus->device.set_mode(ahw_dev_ubus, AUDIO_MODE_INVALID);
pthread_mutex_unlock(&AudioIf_mutex);
Codec_Enabled = FALSE;
}
}
break;
default:
AUDIO_IF_LOGD("%s: id=%d(len=%d) ignored ", __FUNCTION__, requestid, datalen); //1505...
break;
}
end:
if (data)
rilutil_freeResponseData(requestid, data, datalen);
return ret;
}
int AudioIf_uBusSubscribeEvents(char isSubscribe)
{
if (audioIfUbusDb.ind_enabled != isSubscribe) {
audioIfUbusDb.ind_enabled = isSubscribe;
if (isSubscribe) {
AUDIO_IF_UBUS_SUBSCRIBE_EVENT(audioIfUbusDb, "ril.unsol.cc");
} else {
AUDIO_IF_UBUS_UNSUBSCRIBE_EVENT(audioIfUbusDb, "ril.unsol.cc");
}
}
return 0;
}
static int AudioIf_uBusRegisterNotifications(void)
{
int ret;
ret = ubus_register_subscriber(audioIfUbusDb.ctx, &audioIfUbusDb.ind_event);
if (ret) {
AUDIO_IF_LOGE("Failed to add watch handler: %s\n", ubus_strerror(ret));
return -1;
}
audioIfUbusDb.ind_event.cb = AudioIf_uBusInd_RIL;
return 0;
}
int AudioIf_uBusInit(void)
{
pthread_mutexattr_t oAttr;
pthread_mutexattr_t *pAttr = NULL;
memset(&audioIfUbusDb, 0, sizeof(audioIfUbusDb_t));
memset(&audioIfReqDb.reqdata, 0, sizeof(audioIfReqDb.reqdata));
audioIfReqDb.pMutexLock = &req_data_mutex;
if (!pthread_mutexattr_init(&oAttr) && !pthread_mutexattr_settype(&oAttr, PTHREAD_MUTEX_RECURSIVE)) {
pAttr = &oAttr;
}
if (pthread_mutex_init(audioIfReqDb.pMutexLock, pAttr))
ALOGE("init mutex fail \n");
pthread_mutex_lock(audioIfReqDb.pMutexLock);
audioIfReqDb.occupy = 0;
pthread_mutex_unlock(audioIfReqDb.pMutexLock);
uloop_init();
audioIfUbusDb.ctx = ubus_connect(NULL);
if (audioIfUbusDb.ctx == NULL) {
AUDIO_IF_LOGE("Failed to connect to ubus");
return -1;
}
ubus_add_uloop(audioIfUbusDb.ctx);
/*set server object*/
audioIfUbusDb.server_obj.name = AUDIO_IF_UBUS_ID;
audioIfUbusDb.server_obj.type = &server_object_type;
audioIfUbusDb.server_obj.methods = audio_if_methods;
audioIfUbusDb.server_obj.n_methods = ARRAY_SIZE(audio_if_methods);
audioIfUbusDb.server_obj.subscribe_cb = AudioIf_uBussubscribeCb;
/*add audio_if server object*/
if (ubus_add_object(audioIfUbusDb.ctx, &audioIfUbusDb.server_obj)) {
AUDIO_IF_LOGE("Failed to add server");
ubus_free(audioIfUbusDb.ctx);
uloop_done();
return -1;
}
/* lookup fail if ril is not ready */
while(1)
{
/*look for RIL id */
if (ubus_lookup_id(audioIfUbusDb.ctx, RIL_UBUS_ID, &audioIfUbusDb.ril_subscriber_id)) {
AUDIO_IF_LOGE("Failed to look up RILD object");
usleep(600000); //600ms
} else {
break;
}
}
AUDIO_IF_LOGD("%s, ubus_lookup_id(%s) OK\n", __FUNCTION__, RIL_UBUS_ID);
/*subscribe for RIL notifications*/
if (AudioIf_uBusRegisterNotifications() != 0)
return -1;
AUDIO_IF_LOGD("AudioIf_uBusInit done!\n");
return 0;
}
void audio_if_recv(struct uloop_fd *u, unsigned int events)
{
UNUSEDPARAM(events);
AudioIf_ReadFromDevice(u->fd);
}
void AudioIf_uBusFdAdd(int fd)
{
int ret;
audio_if_fd.cb = audio_if_recv;
audio_if_fd.fd = fd;
ret = uloop_fd_add(&audio_if_fd, ULOOP_READ);
AUDIO_IF_LOGD("%s: uloop_fd_add returned %d", __FUNCTION__, ret);
}
void AudioIf_uBusUloopRun(void)
{
uloop_run();
}