|
|
|
/*
|
|
|
|
* Copyright (C) 2013 The CyanogenMod Project
|
|
|
|
* Copyright (C) 2017 Andreas Schneider <asn@cryptomilk.org>
|
|
|
|
*
|
|
|
|
* 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 "audio_hw_ril"
|
|
|
|
/*#define LOG_NDEBUG 0*/
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
#include <dlfcn.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include <utils/Log.h>
|
|
|
|
#include <cutils/properties.h>
|
|
|
|
|
|
|
|
#include "ril_interface.h"
|
|
|
|
|
|
|
|
#define VOLUME_STEPS_DEFAULT "5"
|
|
|
|
#define VOLUME_STEPS_PROPERTY "ro.config.vc_call_vol_steps"
|
|
|
|
|
|
|
|
/* Audio WB AMR callback */
|
|
|
|
/*
|
|
|
|
* TODO:
|
|
|
|
* struct audio_device {
|
|
|
|
* HRilClient client;
|
|
|
|
* void *data
|
|
|
|
* }
|
|
|
|
* static struct audio_device _audio_devices[64];
|
|
|
|
*
|
|
|
|
* When registering a call back we should store it in the array and when
|
|
|
|
* the callback is triggered find the data pointer based on the client
|
|
|
|
* passed in.
|
|
|
|
*/
|
|
|
|
static ril_wb_amr_callback _wb_amr_callback;
|
|
|
|
static void *_wb_amr_data = NULL;
|
|
|
|
|
|
|
|
/* This is the callback function that the RIL uses to
|
|
|
|
set the wideband AMR state */
|
|
|
|
static int ril_internal_wb_amr_callback(HRilClient client __unused,
|
|
|
|
const void *data,
|
|
|
|
size_t datalen)
|
|
|
|
{
|
|
|
|
int enable = 0;
|
|
|
|
|
|
|
|
if (_wb_amr_data == NULL || _wb_amr_callback == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (datalen != 1) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*((int *)data) != 0) {
|
|
|
|
enable = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
_wb_amr_callback(_wb_amr_data, enable);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ril_connect_if_required(struct ril_handle *ril)
|
|
|
|
{
|
|
|
|
int ok;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
if (ril->client == NULL) {
|
|
|
|
ALOGE("ril->client is NULL");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
ok = isConnected_RILD(ril->client);
|
|
|
|
if (ok) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = Connect_RILD(ril->client);
|
|
|
|
if (rc != RIL_CLIENT_ERR_SUCCESS) {
|
|
|
|
ALOGE("FATAL: Failed to connect to RILD: %s",
|
|
|
|
strerror(errno));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ril_open(struct ril_handle *ril)
|
|
|
|
{
|
|
|
|
char property[PROPERTY_VALUE_MAX];
|
|
|
|
|
|
|
|
if (ril == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
ril->client = OpenClient_RILD();
|
|
|
|
if (ril->client == NULL) {
|
|
|
|
ALOGE("OpenClient_RILD() failed");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
property_get(VOLUME_STEPS_PROPERTY, property, VOLUME_STEPS_DEFAULT);
|
|
|
|
ril->volume_steps_max = atoi(property);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This catches the case where VOLUME_STEPS_PROPERTY does not contain
|
|
|
|
* an integer
|
|
|
|
*/
|
|
|
|
if (ril->volume_steps_max == 0) {
|
|
|
|
ril->volume_steps_max = atoi(VOLUME_STEPS_DEFAULT);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ril_close(struct ril_handle *ril)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
if (ril == NULL || ril->client == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = Disconnect_RILD(ril->client);
|
|
|
|
if (rc != RIL_CLIENT_ERR_SUCCESS) {
|
|
|
|
ALOGE("Disconnect_RILD failed");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = CloseClient_RILD(ril->client);
|
|
|
|
if (rc != RIL_CLIENT_ERR_SUCCESS) {
|
|
|
|
ALOGE("CloseClient_RILD() failed");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
ril->client = NULL;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ril_set_wb_amr_callback(struct ril_handle *ril,
|
|
|
|
ril_wb_amr_callback fn,
|
|
|
|
void *data)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
if (fn == NULL || data == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
_wb_amr_callback = fn;
|
|
|
|
_wb_amr_data = data;
|
|
|
|
|
|
|
|
ALOGV("%s: RegisterUnsolicitedHandler(%d, %p)",
|
|
|
|
__func__,
|
|
|
|
RIL_UNSOL_SNDMGR_WB_AMR_REPORT,
|
|
|
|
ril_set_wb_amr_callback);
|
|
|
|
|
|
|
|
/* register the wideband AMR callback */
|
|
|
|
rc = RegisterUnsolicitedHandler(ril->client,
|
|
|
|
RIL_UNSOL_SNDMGR_WB_AMR_REPORT,
|
|
|
|
(RilOnUnsolicited)ril_internal_wb_amr_callback);
|
|
|
|
if (rc != RIL_CLIENT_ERR_SUCCESS) {
|
|
|
|
ALOGE("%s: Failed to register WB_AMR callback", __func__);
|
|
|
|
ril_close(ril);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ril_set_call_volume(struct ril_handle *ril,
|
|
|
|
enum _SoundType sound_type,
|
|
|
|
float volume)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
rc = ril_connect_if_required(ril);
|
|
|
|
if (rc != 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = SetCallVolume(ril->client,
|
|
|
|
sound_type,
|
|
|
|
(int)(volume * ril->volume_steps_max));
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ril_set_call_audio_path(struct ril_handle *ril, enum _AudioPath path)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
rc = ril_connect_if_required(ril);
|
|
|
|
if (rc != 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = SetCallAudioPath(ril->client, path);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ril_set_call_clock_sync(struct ril_handle *ril,
|
|
|
|
enum _SoundClockCondition condition)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
rc = ril_connect_if_required(ril);
|
|
|
|
if (rc != 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = SetCallClockSync(ril->client, condition);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ril_set_mute(struct ril_handle *ril, enum _MuteCondition condition)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
rc = ril_connect_if_required(ril);
|
|
|
|
if (rc != 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = SetMute(ril->client, condition);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ril_set_two_mic_control(struct ril_handle *ril,
|
|
|
|
enum __TwoMicSolDevice device,
|
|
|
|
enum __TwoMicSolReport report)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
rc = ril_connect_if_required(ril);
|
|
|
|
if (rc != 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = SetTwoMicControl(ril->client, device, report);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|