diff options
Diffstat (limited to 'audio/hw/ril_interface.c')
-rw-r--r-- | audio/hw/ril_interface.c | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/audio/hw/ril_interface.c b/audio/hw/ril_interface.c new file mode 100644 index 0000000..1df5932 --- /dev/null +++ b/audio/hw/ril_interface.c | |||
@@ -0,0 +1,224 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #define LOG_TAG "audio_hw_primary" | ||
18 | /*#define LOG_NDEBUG 0*/ | ||
19 | /*#define LOG_NDEBUG_FUNCTION*/ | ||
20 | #ifndef LOG_NDEBUG_FUNCTION | ||
21 | #define LOGFUNC(...) ((void)0) | ||
22 | #else | ||
23 | #define LOGFUNC(...) (ALOGV(__VA_ARGS__)) | ||
24 | #endif | ||
25 | |||
26 | #include <dlfcn.h> | ||
27 | #include <stdlib.h> | ||
28 | |||
29 | #include <utils/Log.h> | ||
30 | #include <cutils/properties.h> | ||
31 | |||
32 | #include "ril_interface.h" | ||
33 | |||
34 | #define VOLUME_STEPS_DEFAULT "5" | ||
35 | #define VOLUME_STEPS_PROPERTY "ro.config.vc_call_vol_steps" | ||
36 | |||
37 | /* Function pointers */ | ||
38 | void *(*_ril_open_client)(int, char **); | ||
39 | int (*_ril_close_client)(void *); | ||
40 | int (*_ril_connect)(void *); | ||
41 | int (*_ril_is_connected)(void *); | ||
42 | int (*_ril_disconnect)(void *); | ||
43 | int (*_ril_set_call_volume)(void *, enum ril_sound_type, int); | ||
44 | int (*_ril_set_call_audio_path)(void *, enum ril_audio_path); | ||
45 | int (*_ril_set_call_clock_sync)(void *, enum ril_clock_state); | ||
46 | int (*_ril_register_unsolicited_handler)(void *, int, void *); | ||
47 | |||
48 | /* Audio WB AMR callback */ | ||
49 | void (*_audio_set_wb_amr_callback)(void *, int); | ||
50 | void *callback_data = NULL; | ||
51 | |||
52 | void ril_register_set_wb_amr_callback(void *function, void *data) | ||
53 | { | ||
54 | _audio_set_wb_amr_callback = function; | ||
55 | callback_data = data; | ||
56 | } | ||
57 | |||
58 | /* This is the callback function that the RIL uses to | ||
59 | set the wideband AMR state */ | ||
60 | static int ril_set_wb_amr_callback(void *ril_client, | ||
61 | const void *data, | ||
62 | size_t datalen) | ||
63 | { | ||
64 | int enable = ((int *)data)[0]; | ||
65 | |||
66 | if (!callback_data || !_audio_set_wb_amr_callback) | ||
67 | return -1; | ||
68 | |||
69 | _audio_set_wb_amr_callback(callback_data, enable); | ||
70 | |||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | static int make_argv(char * args, char ** argv) | ||
75 | { | ||
76 | int count = 0; | ||
77 | char *tok; | ||
78 | char *s = args; | ||
79 | |||
80 | while ((tok = strtok(s, " \0"))) { | ||
81 | argv[count] = tok; | ||
82 | s = NULL; | ||
83 | count++; | ||
84 | } | ||
85 | return count; | ||
86 | } | ||
87 | |||
88 | static int ril_connect_if_required(struct ril_handle *ril) | ||
89 | { | ||
90 | LOGFUNC("%s(%p)", __FUNCTION__, ril); | ||
91 | |||
92 | if (_ril_is_connected(ril->client)) | ||
93 | return 0; | ||
94 | |||
95 | if (_ril_connect(ril->client) != RIL_CLIENT_ERR_SUCCESS) { | ||
96 | ALOGE("ril_connect() failed"); | ||
97 | return -1; | ||
98 | } | ||
99 | return 0; | ||
100 | } | ||
101 | |||
102 | int ril_open(struct ril_handle *ril) | ||
103 | { | ||
104 | char property[PROPERTY_VALUE_MAX]; | ||
105 | char **ril_client_argv; | ||
106 | int ril_client_argc; | ||
107 | static char *new_argv[RIL_CLIENT_MAX_LIB_ARGS]; | ||
108 | |||
109 | LOGFUNC("%s(%p)", __FUNCTION__, ril); | ||
110 | |||
111 | if (!ril) | ||
112 | return -1; | ||
113 | |||
114 | if (!property_get(RIL_CLIENT_PATH_PROPERTY, property, NULL)) { | ||
115 | ALOGE("Cannot find '%s' property", RIL_CLIENT_PATH_PROPERTY); | ||
116 | goto none; | ||
117 | } | ||
118 | |||
119 | ril->handle = dlopen(property, RTLD_NOW); | ||
120 | |||
121 | if (!ril->handle) { | ||
122 | ALOGE("Cannot open '%s'", property); | ||
123 | goto none; | ||
124 | } | ||
125 | |||
126 | _ril_open_client = dlsym(ril->handle, "OpenClient_RILD"); | ||
127 | _ril_close_client = dlsym(ril->handle, "CloseClient_RILD"); | ||
128 | _ril_connect = dlsym(ril->handle, "Connect_RILD"); | ||
129 | _ril_is_connected = dlsym(ril->handle, "isConnected_RILD"); | ||
130 | _ril_disconnect = dlsym(ril->handle, "Disconnect_RILD"); | ||
131 | _ril_set_call_volume = dlsym(ril->handle, "SetCallVolume"); | ||
132 | _ril_set_call_audio_path = dlsym(ril->handle, "SetCallAudioPath"); | ||
133 | _ril_set_call_clock_sync = dlsym(ril->handle, "SetCallClockSync"); | ||
134 | _ril_register_unsolicited_handler = dlsym(ril->handle, | ||
135 | "RegisterUnsolicitedHandler"); | ||
136 | |||
137 | if (!_ril_open_client || !_ril_close_client || !_ril_connect || | ||
138 | !_ril_is_connected || !_ril_disconnect || !_ril_set_call_volume || | ||
139 | !_ril_set_call_audio_path || !_ril_set_call_clock_sync || | ||
140 | !_ril_register_unsolicited_handler) { | ||
141 | ALOGE("Cannot get symbols from '%s'", property); | ||
142 | dlclose(ril->handle); | ||
143 | goto none; | ||
144 | } | ||
145 | |||
146 | ril_client_argv = new_argv; | ||
147 | property_get(RIL_CLIENT_ARGS_PROPERTY, property, ""); | ||
148 | ril_client_argc = make_argv(property, ril_client_argv); | ||
149 | |||
150 | ril->client = _ril_open_client(ril_client_argc, ril_client_argv); | ||
151 | if (!ril->client) { | ||
152 | ALOGE("ril_open_client() failed"); | ||
153 | dlclose(ril->handle); | ||
154 | goto none; | ||
155 | } | ||
156 | |||
157 | /* register the wideband AMR callback */ | ||
158 | _ril_register_unsolicited_handler(ril->client, RIL_UNSOL_WB_AMR_STATE, | ||
159 | ril_set_wb_amr_callback); | ||
160 | |||
161 | property_get(VOLUME_STEPS_PROPERTY, property, VOLUME_STEPS_DEFAULT); | ||
162 | ril->volume_steps_max = atoi(property); | ||
163 | /* this catches the case where VOLUME_STEPS_PROPERTY does not contain | ||
164 | an integer */ | ||
165 | if (ril->volume_steps_max == 0) | ||
166 | ril->volume_steps_max = atoi(VOLUME_STEPS_DEFAULT); | ||
167 | |||
168 | return 0; | ||
169 | |||
170 | none: | ||
171 | while(1) { | ||
172 | ALOGE("ril_open failed"); | ||
173 | sleep(10); | ||
174 | } | ||
175 | } | ||
176 | |||
177 | int ril_close(struct ril_handle *ril) | ||
178 | { | ||
179 | LOGFUNC("%s(%p)", __FUNCTION__, ril); | ||
180 | |||
181 | if (!ril || !ril->handle || !ril->client) | ||
182 | return -1; | ||
183 | |||
184 | if ((_ril_disconnect(ril->client) != RIL_CLIENT_ERR_SUCCESS) || | ||
185 | (_ril_close_client(ril->client) != RIL_CLIENT_ERR_SUCCESS)) { | ||
186 | ALOGE("ril_disconnect() or ril_close_client() failed"); | ||
187 | return -1; | ||
188 | } | ||
189 | |||
190 | dlclose(ril->handle); | ||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | int ril_set_call_volume(struct ril_handle *ril, enum ril_sound_type sound_type, | ||
195 | float volume) | ||
196 | { | ||
197 | LOGFUNC("%s(%p, %d, %f)", __FUNCTION__, ril, sound_type, volume); | ||
198 | |||
199 | if (ril_connect_if_required(ril)) | ||
200 | return 0; | ||
201 | |||
202 | return _ril_set_call_volume(ril->client, sound_type, | ||
203 | (int)(volume * ril->volume_steps_max)); | ||
204 | } | ||
205 | |||
206 | int ril_set_call_audio_path(struct ril_handle *ril, enum ril_audio_path path) | ||
207 | { | ||
208 | LOGFUNC("%s(%p, %d)", __FUNCTION__, ril, path); | ||
209 | |||
210 | if (ril_connect_if_required(ril)) | ||
211 | return 0; | ||
212 | |||
213 | return _ril_set_call_audio_path(ril->client, path); | ||
214 | } | ||
215 | |||
216 | int ril_set_call_clock_sync(struct ril_handle *ril, enum ril_clock_state state) | ||
217 | { | ||
218 | LOGFUNC("%s(%p, %d)", __FUNCTION__, ril, state); | ||
219 | |||
220 | if (ril_connect_if_required(ril)) | ||
221 | return 0; | ||
222 | |||
223 | return _ril_set_call_clock_sync(ril->client, state); | ||
224 | } | ||