blob: f0832cb8af7afa2026d162b465c3b40286542d9a [file] [log] [blame]
/*
* 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 wb_amr_type = 0;
if (_wb_amr_data == NULL || _wb_amr_callback == NULL) {
return -1;
}
if (datalen != 1) {
return -1;
}
wb_amr_type = *((int *)data);
_wb_amr_callback(_wb_amr_data, wb_amr_type);
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) {
ALOGE("%s: Failed to connect to RIL (%s)", __func__, strerror(rc));
return 0;
}
rc = SetCallVolume(ril->client,
sound_type,
(int)(volume * ril->volume_steps_max));
if (rc != 0) {
ALOGE("%s: SetCallVolume() failed, rc=%d", __func__, rc);
}
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) {
ALOGE("%s: Failed to connect to RIL (%s)", __func__, strerror(rc));
return 0;
}
rc = SetCallAudioPath(ril->client, path);
if (rc != 0) {
ALOGE("%s: SetCallAudioPath() failed, rc=%d", __func__, rc);
}
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) {
ALOGE("%s: Failed to connect to RIL (%s)", __func__, strerror(rc));
return 0;
}
rc = SetCallClockSync(ril->client, condition);
if (rc != 0) {
ALOGE("%s: SetCallClockSync() failed, rc=%d", __func__, rc);
}
return rc;
}
int ril_set_mute(struct ril_handle *ril, enum _MuteCondition condition)
{
int rc;
rc = ril_connect_if_required(ril);
if (rc != 0) {
ALOGE("%s: Failed to connect to RIL (%s)", __func__, strerror(rc));
return 0;
}
rc = SetMute(ril->client, condition);
if (rc != 0) {
ALOGE("%s: SetMute() failed, rc=%d", __func__, rc);
}
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) {
ALOGE("%s: Failed to connect to RIL (%s)", __func__, strerror(rc));
return 0;
}
rc = SetTwoMicControl(ril->client, device, report);
if (rc != 0) {
ALOGE("%s: SetTwoMicControl() failed, rc=%d", __func__, rc);
}
return rc;
}