blob: f0832cb8af7afa2026d162b465c3b40286542d9a [file] [log] [blame]
Christopher N. Hessebc52af52017-02-10 21:20:30 +01001/*
2 * Copyright (C) 2013 The CyanogenMod Project
3 * Copyright (C) 2017 Andreas Schneider <asn@cryptomilk.org>
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#define LOG_TAG "audio_hw_ril"
19/*#define LOG_NDEBUG 0*/
20
21#include <errno.h>
22#include <dlfcn.h>
23#include <stdlib.h>
24#include <string.h>
25
26#include <utils/Log.h>
27#include <cutils/properties.h>
28
29#include "ril_interface.h"
30
31#define VOLUME_STEPS_DEFAULT "5"
32#define VOLUME_STEPS_PROPERTY "ro.config.vc_call_vol_steps"
33
34/* Audio WB AMR callback */
35/*
36 * TODO:
37 * struct audio_device {
38 * HRilClient client;
39 * void *data
40 * }
41 * static struct audio_device _audio_devices[64];
42 *
43 * When registering a call back we should store it in the array and when
44 * the callback is triggered find the data pointer based on the client
45 * passed in.
46 */
47static ril_wb_amr_callback _wb_amr_callback;
48static void *_wb_amr_data = NULL;
49
50/* This is the callback function that the RIL uses to
51set the wideband AMR state */
52static int ril_internal_wb_amr_callback(HRilClient client __unused,
53 const void *data,
54 size_t datalen)
55{
Andreas Schneider49b9dcb2017-02-13 17:15:07 +010056 int wb_amr_type = 0;
Christopher N. Hessebc52af52017-02-10 21:20:30 +010057
58 if (_wb_amr_data == NULL || _wb_amr_callback == NULL) {
59 return -1;
60 }
61
62 if (datalen != 1) {
63 return -1;
64 }
65
Andreas Schneider49b9dcb2017-02-13 17:15:07 +010066 wb_amr_type = *((int *)data);
Christopher N. Hessebc52af52017-02-10 21:20:30 +010067
Andreas Schneider49b9dcb2017-02-13 17:15:07 +010068 _wb_amr_callback(_wb_amr_data, wb_amr_type);
Christopher N. Hessebc52af52017-02-10 21:20:30 +010069
70 return 0;
71}
72
73static int ril_connect_if_required(struct ril_handle *ril)
74{
75 int ok;
76 int rc;
77
78 if (ril->client == NULL) {
79 ALOGE("ril->client is NULL");
80 return -1;
81 }
82
83 ok = isConnected_RILD(ril->client);
84 if (ok) {
85 return 0;
86 }
87
88 rc = Connect_RILD(ril->client);
89 if (rc != RIL_CLIENT_ERR_SUCCESS) {
Andreas Schneider9c195612017-02-08 19:27:46 +010090 ALOGE("FATAL: Failed to connect to RILD: %s",
91 strerror(errno));
Christopher N. Hessebc52af52017-02-10 21:20:30 +010092 return -1;
93 }
94
95 return 0;
96}
97
98int ril_open(struct ril_handle *ril)
99{
100 char property[PROPERTY_VALUE_MAX];
101
102 if (ril == NULL) {
103 return -1;
104 }
105
106 ril->client = OpenClient_RILD();
107 if (ril->client == NULL) {
108 ALOGE("OpenClient_RILD() failed");
109 return -1;
110 }
111
112 property_get(VOLUME_STEPS_PROPERTY, property, VOLUME_STEPS_DEFAULT);
113 ril->volume_steps_max = atoi(property);
114
115 /*
116 * This catches the case where VOLUME_STEPS_PROPERTY does not contain
117 * an integer
118 */
119 if (ril->volume_steps_max == 0) {
120 ril->volume_steps_max = atoi(VOLUME_STEPS_DEFAULT);
121 }
122
123 return 0;
124}
125
126int ril_close(struct ril_handle *ril)
127{
128 int rc;
129
130 if (ril == NULL || ril->client == NULL) {
131 return -1;
132 }
133
134 rc = Disconnect_RILD(ril->client);
135 if (rc != RIL_CLIENT_ERR_SUCCESS) {
136 ALOGE("Disconnect_RILD failed");
137 return -1;
138 }
139
140 rc = CloseClient_RILD(ril->client);
141 if (rc != RIL_CLIENT_ERR_SUCCESS) {
142 ALOGE("CloseClient_RILD() failed");
143 return -1;
144 }
145 ril->client = NULL;
146
147 return 0;
148}
149
150int ril_set_wb_amr_callback(struct ril_handle *ril,
151 ril_wb_amr_callback fn,
152 void *data)
153{
154 int rc;
155
156 if (fn == NULL || data == NULL) {
157 return -1;
158 }
159
160 _wb_amr_callback = fn;
161 _wb_amr_data = data;
162
163 ALOGV("%s: RegisterUnsolicitedHandler(%d, %p)",
164 __func__,
165 RIL_UNSOL_SNDMGR_WB_AMR_REPORT,
166 ril_set_wb_amr_callback);
167
168 /* register the wideband AMR callback */
169 rc = RegisterUnsolicitedHandler(ril->client,
170 RIL_UNSOL_SNDMGR_WB_AMR_REPORT,
171 (RilOnUnsolicited)ril_internal_wb_amr_callback);
172 if (rc != RIL_CLIENT_ERR_SUCCESS) {
173 ALOGE("%s: Failed to register WB_AMR callback", __func__);
174 ril_close(ril);
175 return -1;
176 }
177
178 return 0;
179}
180
181int ril_set_call_volume(struct ril_handle *ril,
182 enum _SoundType sound_type,
183 float volume)
184{
185 int rc;
186
187 rc = ril_connect_if_required(ril);
188 if (rc != 0) {
Christopher N. Hessea13e5172017-02-25 14:33:10 +0100189 ALOGE("%s: Failed to connect to RIL (%s)", __func__, strerror(rc));
Christopher N. Hessebc52af52017-02-10 21:20:30 +0100190 return 0;
191 }
192
193 rc = SetCallVolume(ril->client,
194 sound_type,
195 (int)(volume * ril->volume_steps_max));
Christopher N. Hessea13e5172017-02-25 14:33:10 +0100196 if (rc != 0) {
197 ALOGE("%s: SetCallVolume() failed, rc=%d", __func__, rc);
198 }
Christopher N. Hessebc52af52017-02-10 21:20:30 +0100199
200 return rc;
201}
202
203int ril_set_call_audio_path(struct ril_handle *ril, enum _AudioPath path)
204{
205 int rc;
206
207 rc = ril_connect_if_required(ril);
208 if (rc != 0) {
Christopher N. Hessea13e5172017-02-25 14:33:10 +0100209 ALOGE("%s: Failed to connect to RIL (%s)", __func__, strerror(rc));
Christopher N. Hessebc52af52017-02-10 21:20:30 +0100210 return 0;
211 }
212
213 rc = SetCallAudioPath(ril->client, path);
Christopher N. Hessea13e5172017-02-25 14:33:10 +0100214 if (rc != 0) {
215 ALOGE("%s: SetCallAudioPath() failed, rc=%d", __func__, rc);
216 }
Christopher N. Hessebc52af52017-02-10 21:20:30 +0100217
218 return rc;
219}
220
221int ril_set_call_clock_sync(struct ril_handle *ril,
222 enum _SoundClockCondition condition)
223{
224 int rc;
225
226 rc = ril_connect_if_required(ril);
227 if (rc != 0) {
Christopher N. Hessea13e5172017-02-25 14:33:10 +0100228 ALOGE("%s: Failed to connect to RIL (%s)", __func__, strerror(rc));
Christopher N. Hessebc52af52017-02-10 21:20:30 +0100229 return 0;
230 }
231
232 rc = SetCallClockSync(ril->client, condition);
Christopher N. Hessea13e5172017-02-25 14:33:10 +0100233 if (rc != 0) {
234 ALOGE("%s: SetCallClockSync() failed, rc=%d", __func__, rc);
235 }
Christopher N. Hessebc52af52017-02-10 21:20:30 +0100236
237 return rc;
238}
239
240int ril_set_mute(struct ril_handle *ril, enum _MuteCondition condition)
241{
242 int rc;
243
244 rc = ril_connect_if_required(ril);
245 if (rc != 0) {
Christopher N. Hessea13e5172017-02-25 14:33:10 +0100246 ALOGE("%s: Failed to connect to RIL (%s)", __func__, strerror(rc));
Christopher N. Hessebc52af52017-02-10 21:20:30 +0100247 return 0;
248 }
249
250 rc = SetMute(ril->client, condition);
Christopher N. Hessea13e5172017-02-25 14:33:10 +0100251 if (rc != 0) {
252 ALOGE("%s: SetMute() failed, rc=%d", __func__, rc);
253 }
Christopher N. Hessebc52af52017-02-10 21:20:30 +0100254
255 return rc;
256}
257
258int ril_set_two_mic_control(struct ril_handle *ril,
259 enum __TwoMicSolDevice device,
260 enum __TwoMicSolReport report)
261{
262 int rc;
263
264 rc = ril_connect_if_required(ril);
265 if (rc != 0) {
Christopher N. Hessea13e5172017-02-25 14:33:10 +0100266 ALOGE("%s: Failed to connect to RIL (%s)", __func__, strerror(rc));
Christopher N. Hessebc52af52017-02-10 21:20:30 +0100267 return 0;
268 }
269
270 rc = SetTwoMicControl(ril->client, device, report);
Christopher N. Hessea13e5172017-02-25 14:33:10 +0100271 if (rc != 0) {
272 ALOGE("%s: SetTwoMicControl() failed, rc=%d", __func__, rc);
273 }
Christopher N. Hessebc52af52017-02-10 21:20:30 +0100274
275 return rc;
276}