blob: cffbbe6bcf772af3dd430982319595d023c211de [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) {
189 return 0;
190 }
191
192 rc = SetCallVolume(ril->client,
193 sound_type,
194 (int)(volume * ril->volume_steps_max));
195
196 return rc;
197}
198
199int ril_set_call_audio_path(struct ril_handle *ril, enum _AudioPath path)
200{
201 int rc;
202
203 rc = ril_connect_if_required(ril);
204 if (rc != 0) {
205 return 0;
206 }
207
208 rc = SetCallAudioPath(ril->client, path);
209
210 return rc;
211}
212
213int ril_set_call_clock_sync(struct ril_handle *ril,
214 enum _SoundClockCondition condition)
215{
216 int rc;
217
218 rc = ril_connect_if_required(ril);
219 if (rc != 0) {
220 return 0;
221 }
222
223 rc = SetCallClockSync(ril->client, condition);
224
225 return rc;
226}
227
228int ril_set_mute(struct ril_handle *ril, enum _MuteCondition condition)
229{
230 int rc;
231
232 rc = ril_connect_if_required(ril);
233 if (rc != 0) {
234 return 0;
235 }
236
237 rc = SetMute(ril->client, condition);
238
239 return rc;
240}
241
242int ril_set_two_mic_control(struct ril_handle *ril,
243 enum __TwoMicSolDevice device,
244 enum __TwoMicSolReport report)
245{
246 int rc;
247
248 rc = ril_connect_if_required(ril);
249 if (rc != 0) {
250 return 0;
251 }
252
253 rc = SetTwoMicControl(ril->client, device, report);
254
255 return rc;
256}