From bc52af5471a404277b1d74a3c5128528bf0b3223 Mon Sep 17 00:00:00 2001 From: "Christopher N. Hesse" Date: Fri, 10 Feb 2017 21:20:30 +0100 Subject: [PATCH] audio: Add ril_interface to talk to radio This is based on previous work for tuna, i9300, i9500 and many other devices. Change-Id: Ie94f12ee7940ffae84aec5e409a2a831b34d616f --- audio/Android.mk | 7 +- audio/ril_interface.c | 257 ++++++++++++++++++++++++++++++++++++++++++ audio/ril_interface.h | 57 ++++++++++ 3 files changed, 319 insertions(+), 2 deletions(-) create mode 100644 audio/ril_interface.c create mode 100644 audio/ril_interface.h diff --git a/audio/Android.mk b/audio/Android.mk index c858d789..8b306131 100644 --- a/audio/Android.mk +++ b/audio/Android.mk @@ -22,7 +22,8 @@ LOCAL_ARM_MODE := arm LOCAL_SRC_FILES := \ audio_hw.c \ - compress_offload.c + compress_offload.c \ + ril_interface.c # TODO: remove resampler if possible when AudioFlinger supports downsampling from 48 to 8 LOCAL_SHARED_LIBRARIES := \ @@ -32,13 +33,15 @@ LOCAL_SHARED_LIBRARIES := \ libtinyalsa \ libtinycompress \ libaudioroute \ - libdl + libdl \ + libsecril-client LOCAL_C_INCLUDES += \ $(LOCAL_PATH)/include \ external/tinyalsa/include \ external/tinycompress/include \ + hardware/samsung/ril/libsecril-client \ $(call include-path-for, audio-utils) \ $(call include-path-for, audio-route) \ $(call include-path-for, audio-effects) diff --git a/audio/ril_interface.c b/audio/ril_interface.c new file mode 100644 index 00000000..179e1200 --- /dev/null +++ b/audio/ril_interface.c @@ -0,0 +1,257 @@ +/* + * Copyright (C) 2013 The CyanogenMod Project + * Copyright (C) 2017 Andreas Schneider + * + * 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 +#include +#include +#include + +#include +#include + +#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("Connect_RILD() failed"); + 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; +} diff --git a/audio/ril_interface.h b/audio/ril_interface.h new file mode 100644 index 00000000..d68c6b4e --- /dev/null +++ b/audio/ril_interface.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2013 The CyanogenMod 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. + */ + +#ifndef RIL_INTERFACE_H +#define RIL_INTERFACE_H + +#include +#include + +typedef void (*ril_wb_amr_callback)(void *data, int enable); + +struct ril_handle +{ + void *client; + int volume_steps_max; +}; + + +/* Function prototypes */ +int ril_open(struct ril_handle *ril); + +int ril_close(struct ril_handle *ril); + +int ril_set_call_volume(struct ril_handle *ril, + enum _SoundType sound_type, + float volume); + +int ril_set_call_audio_path(struct ril_handle *ril, + enum _AudioPath path); + +int ril_set_call_clock_sync(struct ril_handle *ril, + enum _SoundClockCondition condition); + +int ril_set_mute(struct ril_handle *ril, enum _MuteCondition condition); + +int ril_set_two_mic_control(struct ril_handle *ril, + enum __TwoMicSolDevice device, + enum __TwoMicSolReport report); + +int ril_set_wb_amr_callback(struct ril_handle *ril, + ril_wb_amr_callback fn, + void *data); + +#endif