blob: ffb249469e29a2efded8707bb4238066d9a8d0fd [file] [log] [blame]
codeworkxf1587a32012-08-03 23:32:29 +02001/**
2 * @file secril-client.cpp
3 *
4 * @author Myeongcheol Kim (mcmount.kim@samsung.com)
5 *
6 * @brief RIL client library for multi-client support
7 */
8
9#define LOG_TAG "RILClient"
Andreas Schneidera3660112017-02-06 18:23:19 +010010/*#define LOG_NDEBUG 0*/
codeworkxf1587a32012-08-03 23:32:29 +020011
12#include <binder/Parcel.h>
13#include <telephony/ril.h>
14#include <cutils/record_stream.h>
15
16#include <unistd.h>
17#include <errno.h>
18#include <cutils/sockets.h>
19#include <netinet/in.h>
20#include <sys/types.h>
21#include <string.h>
22#include <fcntl.h>
23#include <utils/Log.h>
24#include <pthread.h>
25#include "secril-client.h"
26#include <hardware_legacy/power.h> // For wakelock
27
28
29#define RIL_CLIENT_WAKE_LOCK "client-interface"
30
31namespace android {
32
33//---------------------------------------------------------------------------
34// Defines
35//---------------------------------------------------------------------------
codeworkxf1587a32012-08-03 23:32:29 +020036#define RILD_PORT 7777
37#define MULTI_CLIENT_SOCKET_NAME "Multiclient"
38#define MULTI_CLIENT_Q_SOCKET_NAME "QMulticlient"
39#if defined(SEC_PRODUCT_FEATURE_RIL_CALL_DUALMODE_CDMAGSM)
40#define MULTI_CLIENT_SOCKET_NAME_2 "Multiclient2"
41#endif
42
43#define MAX_COMMAND_BYTES (8 * 1024)
44#define REQ_POOL_SIZE 32
45#define TOKEN_POOL_SIZE 32
46
47// Constants for response types
48#define RESPONSE_SOLICITED 0
49#define RESPONSE_UNSOLICITED 1
50
51#define max(a, b) ((a) > (b) ? (a) : (b))
52
53#define REQ_OEM_HOOK_RAW RIL_REQUEST_OEM_HOOK_RAW
54#define REQ_SET_CALL_VOLUME 101
55#define REQ_SET_AUDIO_PATH 102
56#define REQ_SET_CALL_CLOCK_SYNC 103
57#define REQ_SET_CALL_RECORDING 104
58#define REQ_SET_CALL_MUTE 105
59#define REQ_GET_CALL_MUTE 106
60#define REQ_SET_CALL_VT_CTRL 107
61#define REQ_SET_TWO_MIC_CTRL 108
62#define REQ_SET_DHA_CTRL 109
63#define REQ_SET_LOOPBACK 110
64
65// OEM request function ID
66#define OEM_FUNC_SOUND 0x08
67
68// OEM request sub function ID
69#define OEM_SND_SET_VOLUME_CTRL 0x03
70#define OEM_SND_SET_AUDIO_PATH 0x05
71#define OEM_SND_GET_AUDIO_PATH 0x06
72#define OEM_SND_SET_VIDEO_CALL_CTRL 0x07
73#define OEM_SND_SET_LOOPBACK_CTRL 0x08
74#define OEM_SND_SET_VOICE_RECORDING_CTRL 0x09
75#define OEM_SND_SET_CLOCK_CTRL 0x0A
76#define OEM_SND_SET_MUTE 0x0B
77#define OEM_SND_GET_MUTE 0x0C
78#define OEM_SND_SET_TWO_MIC_CTL 0x0D
79#define OEM_SND_SET_DHA_CTL 0x0E
80
81#define OEM_SND_TYPE_VOICE 0x01 // Receiver(0x00) + Voice(0x01)
82#define OEM_SND_TYPE_SPEAKER 0x11 // SpeakerPhone(0x10) + Voice(0x01)
83#define OEM_SND_TYPE_HEADSET 0x31 // Headset(0x30) + Voice(0x01)
84#define OEM_SND_TYPE_BTVOICE 0x41 // BT(0x40) + Voice(0x01)
85
Christopher N. Hesse57eacca2016-03-08 15:50:23 +010086#ifdef SAMSUNG_NEXT_GEN_MODEM
Andreas Schneidere0058812017-02-14 17:24:02 +010087#define OEM_SND_AUDIO_PATH_EARPIECE 0x01
Andreas Schneider6b9cd5f2015-01-23 22:41:22 +010088#define OEM_SND_AUDIO_PATH_HEADSET 0x02
89#define OEM_SND_AUDIO_PATH_HFK 0x06
90#define OEM_SND_AUDIO_PATH_BLUETOOTH 0x04
91#define OEM_SND_AUDIO_PATH_STEREO_BLUETOOTH 0x05
92#define OEM_SND_AUDIO_PATH_SPEAKER 0x07
93#define OEM_SND_AUDIO_PATH_HEADPHONE 0x08
94#define OEM_SND_AUDIO_PATH_BT_NSEC_OFF 0x09
95#define OEM_SND_AUDIO_PATH_MIC1 0x0A
96#define OEM_SND_AUDIO_PATH_MIC2 0x0B
97#define OEM_SND_AUDIO_PATH_BT_WB 0x0C
98#define OEM_SND_AUDIO_PATH_BT_WB_NSEC_OFF 0x0D
99#else
Andreas Schneidere0058812017-02-14 17:24:02 +0100100#define OEM_SND_AUDIO_PATH_EARPIECE 0x01
codeworkxf1587a32012-08-03 23:32:29 +0200101#define OEM_SND_AUDIO_PATH_HEADSET 0x02
102#define OEM_SND_AUDIO_PATH_HFK 0x03
103#define OEM_SND_AUDIO_PATH_BLUETOOTH 0x04
104#define OEM_SND_AUDIO_PATH_STEREO_BLUETOOTH 0x05
105#define OEM_SND_AUDIO_PATH_SPEAKER 0x06
106#define OEM_SND_AUDIO_PATH_HEADPHONE 0x07
107#define OEM_SND_AUDIO_PATH_BT_NSEC_OFF 0x08
108#define OEM_SND_AUDIO_PATH_MIC1 0x09
109#define OEM_SND_AUDIO_PATH_MIC2 0x0A
110#define OEM_SND_AUDIO_PATH_BT_WB 0x0B
111#define OEM_SND_AUDIO_PATH_BT_WB_NSEC_OFF 0x0C
Andreas Schneider6b9cd5f2015-01-23 22:41:22 +0100112#endif
codeworkxf1587a32012-08-03 23:32:29 +0200113
114//---------------------------------------------------------------------------
115// Type definitions
116//---------------------------------------------------------------------------
117typedef struct _ReqHistory {
118 int token; // token used for request
119 uint32_t id; // request ID
120} ReqHistory;
121
122typedef struct _ReqRespHandler {
123 uint32_t id; // request ID
124 RilOnComplete handler; // handler function
125} ReqRespHandler;
126
127typedef struct _UnsolHandler {
128 uint32_t id; // unsolicited response ID
129 RilOnUnsolicited handler; // handler function
130} UnsolHandler;
131
132typedef struct _RilClientPrv {
133 HRilClient parent;
134 uint8_t b_connect; // connected to server?
135 int sock; // socket
136 int pipefd[2];
137 fd_set sock_rfds; // for read with select()
138 RecordStream *p_rs;
139 uint32_t token_pool; // each bit in token_pool used for token.
140 // so, pool size is 32.
141 pthread_t tid_reader; // socket reader thread id
142 ReqHistory history[TOKEN_POOL_SIZE]; // request history
143 ReqRespHandler req_handlers[REQ_POOL_SIZE]; // request response handler list
144 UnsolHandler unsol_handlers[REQ_POOL_SIZE]; // unsolicited response handler list
145 RilOnError err_cb; // error callback
146 void *err_cb_data; // error callback data
147 uint8_t b_del_handler;
148} RilClientPrv;
149
150
151//---------------------------------------------------------------------------
152// Local static function prototypes
153//---------------------------------------------------------------------------
154static void * RxReaderFunc(void *param);
155static int processRxBuffer(RilClientPrv *prv, void *buffer, size_t buflen);
156static uint32_t AllocateToken(uint32_t *token_pool);
157static void FreeToken(uint32_t *token_pool, uint32_t token);
158static uint8_t IsValidToken(uint32_t *token_pool, uint32_t token);
159static void DeallocateToken(uint32_t *token_pool, uint32_t token);
160static int blockingWrite(int fd, const void *buffer, size_t len);
161static int RecordReqHistory(RilClientPrv *prv, int token, uint32_t id);
162static void ClearReqHistory(RilClientPrv *prv, int token);
163static RilOnComplete FindReqHandler(RilClientPrv *prv, int token, uint32_t *id);
164static RilOnUnsolicited FindUnsolHandler(RilClientPrv *prv, uint32_t id);
165static int SendOemRequestHookRaw(HRilClient client, int req_id, char *data, size_t len);
166static bool isValidSoundType(SoundType type);
167static bool isValidAudioPath(AudioPath path);
168static bool isValidSoundClockCondition(SoundClockCondition condition);
169static bool isValidCallRecCondition(CallRecCondition condition);
170static bool isValidMuteCondition(MuteCondition condition);
171static bool isValidTwoMicCtrl(TwoMicSolDevice device, TwoMicSolReport report);
172static char ConvertSoundType(SoundType type);
173static char ConvertAudioPath(AudioPath path);
174
175
176/**
177 * @fn int RegisterUnsolicitedHandler(HRilClient client, uint32_t id, RilOnUnsolicited handler)
178 *
179 * @params client: Client handle.
180 * id: Unsolicited response ID to which handler is registered.
181 * handler: Unsolicited handler. NULL for deregistration.
182 *
183 * @return 0 on success or error code.
184 */
185extern "C"
186int RegisterUnsolicitedHandler(HRilClient client, uint32_t id, RilOnUnsolicited handler) {
187 RilClientPrv *client_prv;
188 int match_slot = -1;
189 int first_empty_slot = -1;
190 int i;
191
192 if (client == NULL || client->prv == NULL)
193 return RIL_CLIENT_ERR_INVAL;
194
195 client_prv = (RilClientPrv *)(client->prv);
196
197 for (i = 0; i < REQ_POOL_SIZE; i++) {
198 // Check if there is matched handler.
199 if (id == client_prv->unsol_handlers[i].id) {
200 match_slot = i;
201 }
202 // Find first empty handler slot.
203 if (first_empty_slot == -1 && client_prv->unsol_handlers[i].id == 0) {
204 first_empty_slot = i;
205 }
206 }
207
208 if (handler == NULL) { // Unregister.
209 if (match_slot >= 0) {
210 memset(&(client_prv->unsol_handlers[match_slot]), 0, sizeof(UnsolHandler));
211 return RIL_CLIENT_ERR_SUCCESS;
212 }
213 else {
214 return RIL_CLIENT_ERR_SUCCESS;
215 }
216 }
217 else {// Register.
218 if (match_slot >= 0) {
219 client_prv->unsol_handlers[match_slot].handler = handler; // Just update.
220 }
221 else if (first_empty_slot >= 0) {
222 client_prv->unsol_handlers[first_empty_slot].id = id;
223 client_prv->unsol_handlers[first_empty_slot].handler = handler;
224 }
225 else {
226 return RIL_CLIENT_ERR_RESOURCE;
227 }
228 }
229
230 return RIL_CLIENT_ERR_SUCCESS;
231}
232
233
234/**
235 * @fn int RegisterRequestCompleteHandler(HRilClient client, uint32_t id, RilOnComplete handler)
236 *
237 * @params client: Client handle.
238 * id: Request ID to which handler is registered.
239 * handler: Request complete handler. NULL for deregistration.
240 *
241 * @return 0 on success or error code.
242 */
243extern "C"
244int RegisterRequestCompleteHandler(HRilClient client, uint32_t id, RilOnComplete handler) {
245 RilClientPrv *client_prv;
246 int match_slot = -1;
247 int first_empty_slot = -1;
248 int i;
249
250 if (client == NULL || client->prv == NULL)
251 return RIL_CLIENT_ERR_INVAL;
252
253 client_prv = (RilClientPrv *)(client->prv);
254
255 for (i = 0; i < REQ_POOL_SIZE; i++) {
256 // Check if there is matched handler.
257 if (id == client_prv->req_handlers[i].id) {
258 match_slot = i;
259 }
260 // Find first empty handler slot.
261 if (first_empty_slot == -1 && client_prv->req_handlers[i].id == 0) {
262 first_empty_slot = i;
263 }
264 }
265
266 if (handler == NULL) { // Unregister.
267 if (match_slot >= 0) {
268 memset(&(client_prv->req_handlers[match_slot]), 0, sizeof(ReqRespHandler));
269 return RIL_CLIENT_ERR_SUCCESS;
270 }
271 else {
272 return RIL_CLIENT_ERR_SUCCESS;
273 }
274 }
275 else { // Register.
276 if (match_slot >= 0) {
277 client_prv->req_handlers[match_slot].handler = handler; // Just update.
278 }
279 else if (first_empty_slot >= 0) {
280 client_prv->req_handlers[first_empty_slot].id = id;
281 client_prv->req_handlers[first_empty_slot].handler = handler;
282 }
283 else {
284 return RIL_CLIENT_ERR_RESOURCE;
285 }
286 }
287
288 return RIL_CLIENT_ERR_SUCCESS;
289}
290
291
292/**
293 * @fn int RegisterErrorCallback(HRilClient client, RilOnError cb, void *data)
294 *
295 * @params client: Client handle.
296 * cb: Error callback. NULL for unregistration.
297 * data: Callback data.
298 *
299 * @return 0 for success or error code.
300 */
301extern "C"
302int RegisterErrorCallback(HRilClient client, RilOnError cb, void *data) {
303 RilClientPrv *client_prv;
304
305 if (client == NULL || client->prv == NULL)
306 return RIL_CLIENT_ERR_INVAL;
307
308 client_prv = (RilClientPrv *)(client->prv);
309
310 client_prv->err_cb = cb;
311 client_prv->err_cb_data = data;
312
313 return RIL_CLIENT_ERR_SUCCESS;
314}
315
316
317/**
318 * @fn HRilClient OpenClient_RILD(void)
319 *
320 * @params None.
321 *
322 * @return Client handle, NULL on error.
323 */
324extern "C"
325HRilClient OpenClient_RILD(void) {
326 HRilClient client = (HRilClient)malloc(sizeof(struct RilClient));
327 if (client == NULL)
328 return NULL;
329
330 client->prv = (RilClientPrv *)malloc(sizeof(RilClientPrv));
331 if (client->prv == NULL) {
332 free(client);
333 return NULL;
334 }
335
336 memset(client->prv, 0, sizeof(RilClientPrv));
337
338 ((RilClientPrv *)(client->prv))->parent = client;
339 ((RilClientPrv *)(client->prv))->sock = -1;
340
341 return client;
342}
343
344
345/**
346 * @fn int Connect_RILD(void)
347 *
348 * @params client: Client handle.
349 *
350 * @return 0, or error code.
351 */
352extern "C"
353int Connect_RILD(HRilClient client) {
354 RilClientPrv *client_prv;
355
356 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100357 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200358 return RIL_CLIENT_ERR_INVAL;
359 }
360
361 client_prv = (RilClientPrv *)(client->prv);
362
363 // Open client socket and connect to server.
364 //client_prv->sock = socket_loopback_client(RILD_PORT, SOCK_STREAM);
365 client_prv->sock = socket_local_client(MULTI_CLIENT_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM );
366
367 if (client_prv->sock < 0) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100368 RLOGE("%s: Connecting failed. %s(%d)", __FUNCTION__, strerror(errno), errno);
codeworkxf1587a32012-08-03 23:32:29 +0200369 return RIL_CLIENT_ERR_CONNECT;
370 }
371
372 client_prv->b_connect = 1;
373
374 if (fcntl(client_prv->sock, F_SETFL, O_NONBLOCK) < 0) {
375 close(client_prv->sock);
376 return RIL_CLIENT_ERR_IO;
377 }
378
379 client_prv->p_rs = record_stream_new(client_prv->sock, MAX_COMMAND_BYTES);
380
381 if (pipe(client_prv->pipefd) < 0) {
382 close(client_prv->sock);
Andreas Schneider560e37a2017-02-06 18:19:39 +0100383 RLOGE("%s: Creating command pipe failed. %s(%d)", __FUNCTION__, strerror(errno), errno);
codeworkxf1587a32012-08-03 23:32:29 +0200384 return RIL_CLIENT_ERR_IO;
385 }
386
387 if (fcntl(client_prv->pipefd[0], F_SETFL, O_NONBLOCK) < 0) {
388 close(client_prv->sock);
389 close(client_prv->pipefd[0]);
390 close(client_prv->pipefd[1]);
391 return RIL_CLIENT_ERR_IO;
392 }
393
394 // Start socket read thread.
395 if (pthread_create(&(client_prv->tid_reader), NULL, RxReaderFunc, (void *)client_prv) != 0) {
396 close(client_prv->sock);
397 close(client_prv->pipefd[0]);
398 close(client_prv->pipefd[1]);
399
400 memset(client_prv, 0, sizeof(RilClientPrv));
401 client_prv->sock = -1;
Andreas Schneider560e37a2017-02-06 18:19:39 +0100402 RLOGE("%s: Can't create Reader thread. %s(%d)", __FUNCTION__, strerror(errno), errno);
codeworkxf1587a32012-08-03 23:32:29 +0200403 return RIL_CLIENT_ERR_CONNECT;
404 }
405
406 return RIL_CLIENT_ERR_SUCCESS;
407}
408
409/**
410 * @fn int Connect_QRILD(void)
411 *
412 * @params client: Client handle.
413 *
414 * @return 0, or error code.
415 */
416extern "C"
417int Connect_QRILD(HRilClient client) {
418 RilClientPrv *client_prv;
419
420 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100421 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200422 return RIL_CLIENT_ERR_INVAL;
423 }
424
425 client_prv = (RilClientPrv *)(client->prv);
426
427 // Open client socket and connect to server.
428 //client_prv->sock = socket_loopback_client(RILD_PORT, SOCK_STREAM);
429 client_prv->sock = socket_local_client(MULTI_CLIENT_Q_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM );
430
431 if (client_prv->sock < 0) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100432 RLOGE("%s: Connecting failed. %s(%d)", __FUNCTION__, strerror(errno), errno);
codeworkxf1587a32012-08-03 23:32:29 +0200433 return RIL_CLIENT_ERR_CONNECT;
434 }
435
436 client_prv->b_connect = 1;
437
438 if (fcntl(client_prv->sock, F_SETFL, O_NONBLOCK) < 0) {
439 close(client_prv->sock);
440 return RIL_CLIENT_ERR_IO;
441 }
442
443 client_prv->p_rs = record_stream_new(client_prv->sock, MAX_COMMAND_BYTES);
444
445 if (pipe(client_prv->pipefd) < 0) {
446 close(client_prv->sock);
Andreas Schneider560e37a2017-02-06 18:19:39 +0100447 RLOGE("%s: Creating command pipe failed. %s(%d)", __FUNCTION__, strerror(errno), errno);
codeworkxf1587a32012-08-03 23:32:29 +0200448 return RIL_CLIENT_ERR_IO;
449 }
450
451 if (fcntl(client_prv->pipefd[0], F_SETFL, O_NONBLOCK) < 0) {
452 close(client_prv->sock);
453 close(client_prv->pipefd[0]);
454 close(client_prv->pipefd[1]);
455 return RIL_CLIENT_ERR_IO;
456 }
457
458 // Start socket read thread.
459 if (pthread_create(&(client_prv->tid_reader), NULL, RxReaderFunc, (void *)client_prv) != 0) {
460 close(client_prv->sock);
461 close(client_prv->pipefd[0]);
462 close(client_prv->pipefd[1]);
463
464 memset(client_prv, 0, sizeof(RilClientPrv));
465 client_prv->sock = -1;
Andreas Schneider560e37a2017-02-06 18:19:39 +0100466 RLOGE("%s: Can't create Reader thread. %s(%d)", __FUNCTION__, strerror(errno), errno);
codeworkxf1587a32012-08-03 23:32:29 +0200467 return RIL_CLIENT_ERR_CONNECT;
468 }
469
470 return RIL_CLIENT_ERR_SUCCESS;
471}
472
473#if defined(SEC_PRODUCT_FEATURE_RIL_CALL_DUALMODE_CDMAGSM) // mook_120209 Enable multiclient
474/**
475 * @fn int Connect_RILD_Second(void)
476 *
477 * @params client: Client handle.
478 *
479 * @return 0, or error code.
480 */
481extern "C"
482int Connect_RILD_Second(HRilClient client) {
483 RilClientPrv *client_prv;
484
485 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100486 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200487 return RIL_CLIENT_ERR_INVAL;
488 }
489
490 client_prv = (RilClientPrv *)(client->prv);
491
492 // Open client socket and connect to server.
493 //client_prv->sock = socket_loopback_client(RILD_PORT, SOCK_STREAM);
494 client_prv->sock = socket_local_client(MULTI_CLIENT_SOCKET_NAME_2, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM );
495
496 if (client_prv->sock < 0) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100497 RLOGE("%s: Connecting failed. %s(%d)", __FUNCTION__, strerror(errno), errno);
codeworkxf1587a32012-08-03 23:32:29 +0200498 return RIL_CLIENT_ERR_CONNECT;
499 }
500
501 client_prv->b_connect = 1;
502
503 if (fcntl(client_prv->sock, F_SETFL, O_NONBLOCK) < 0) {
504 close(client_prv->sock);
505 return RIL_CLIENT_ERR_IO;
506 }
507
508 client_prv->p_rs = record_stream_new(client_prv->sock, MAX_COMMAND_BYTES);
509
510 if (pipe(client_prv->pipefd) < 0) {
511 close(client_prv->sock);
Andreas Schneider560e37a2017-02-06 18:19:39 +0100512 RLOGE("%s: Creating command pipe failed. %s(%d)", __FUNCTION__, strerror(errno), errno);
codeworkxf1587a32012-08-03 23:32:29 +0200513 return RIL_CLIENT_ERR_IO;
514 }
515
516 if (fcntl(client_prv->pipefd[0], F_SETFL, O_NONBLOCK) < 0) {
517 close(client_prv->sock);
518 close(client_prv->pipefd[0]);
519 close(client_prv->pipefd[1]);
520 return RIL_CLIENT_ERR_IO;
521 }
522
523 // Start socket read thread.
524 if (pthread_create(&(client_prv->tid_reader), NULL, RxReaderFunc, (void *)client_prv) != 0) {
525 close(client_prv->sock);
526 close(client_prv->pipefd[0]);
527 close(client_prv->pipefd[1]);
528
529 memset(client_prv, 0, sizeof(RilClientPrv));
530 client_prv->sock = -1;
Andreas Schneider560e37a2017-02-06 18:19:39 +0100531 RLOGE("%s: Can't create Reader thread. %s(%d)", __FUNCTION__, strerror(errno), errno);
codeworkxf1587a32012-08-03 23:32:29 +0200532 return RIL_CLIENT_ERR_CONNECT;
533 }
534
535 return RIL_CLIENT_ERR_SUCCESS;
536}
537#endif
538
539/**
540 * @fn int isConnected_RILD(HRilClient client)
541 *
542 * @params client: Client handle.
543 *
544 * @return 0, or 1.
545 */
546extern "C"
547int isConnected_RILD(HRilClient client) {
548 RilClientPrv *client_prv;
549
550 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100551 RLOGE("%s: invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200552 return RIL_CLIENT_ERR_INVAL;
553 }
554
555 client_prv = (RilClientPrv *)(client->prv);
556
557 return client_prv->b_connect == 1;
558}
559
560/**
561 * @fn int Disconnect_RILD(HRilClient client)
562 *
563 * @params client: Client handle.
564 *
565 * @return 0 on success, or error code.
566 */
567extern "C"
568int Disconnect_RILD(HRilClient client) {
569 RilClientPrv *client_prv;
570 int ret = 0;
571
572 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100573 RLOGE("%s: invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200574 return RIL_CLIENT_ERR_INVAL;
575 }
576
577 client_prv = (RilClientPrv *)(client->prv);
578
579 if (client_prv->sock == -1)
580 return RIL_CLIENT_ERR_SUCCESS;
581
582 printf("[*] %s(): sock=%d\n", __FUNCTION__, client_prv->sock);
583
584 if (client_prv->sock > 0) {
585 do {
586 ret = write(client_prv->pipefd[1], "close", strlen("close"));
587 } while (ret < 0 && errno == EINTR);
588 }
589
590 client_prv->b_connect = 0;
591
592 pthread_join(client_prv->tid_reader, NULL);
593
594 return RIL_CLIENT_ERR_SUCCESS;
595}
596
597
598/**
599 * @fn int CloseClient_RILD(HRilClient client)
600 *
601 * @params client: Client handle.
602 *
603 * @return 0 on success, or error code.
604 */
605extern "C"
606int CloseClient_RILD(HRilClient client) {
607 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100608 RLOGE("%s: invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200609 return RIL_CLIENT_ERR_INVAL;
610 }
611
612 Disconnect_RILD(client);
613
614 free(client->prv);
615 free(client);
616
617 return RIL_CLIENT_ERR_SUCCESS;
618}
619
620
621/**
622 * Set in-call volume.
623 */
624extern "C"
625int SetCallVolume(HRilClient client, SoundType type, int vol_level) {
626 RilClientPrv *client_prv;
627 int ret;
628 char data[6] = {0,};
629
630 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100631 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200632 return RIL_CLIENT_ERR_INVAL;
633 }
634
635 client_prv = (RilClientPrv *)(client->prv);
636
637 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100638 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200639 return RIL_CLIENT_ERR_CONNECT;
640 }
641
642 if (isValidSoundType(type) == false) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100643 RLOGE("%s: Invalid sound type", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200644 return RIL_CLIENT_ERR_INVAL;
645 }
646
647 // Make raw data
648 data[0] = OEM_FUNC_SOUND;
649 data[1] = OEM_SND_SET_VOLUME_CTRL;
650 data[2] = 0x00; // data length
651 data[3] = 0x06; // data length
652 data[4] = ConvertSoundType(type); // volume type
653 data[5] = vol_level; // volume level
654
655 RegisterRequestCompleteHandler(client, REQ_SET_CALL_VOLUME, NULL);
656
657 ret = SendOemRequestHookRaw(client, REQ_SET_CALL_VOLUME, data, sizeof(data));
658 if (ret != RIL_CLIENT_ERR_SUCCESS) {
659 RegisterRequestCompleteHandler(client, REQ_SET_CALL_VOLUME, NULL);
660 }
661
662 return ret;
663}
664
665
666/**
667 * Set external sound device path for noise reduction.
668 */
669extern "C"
Android-Andi40afadb2016-01-07 11:51:38 +0100670#ifdef RIL_CALL_AUDIO_PATH_EXTRAVOLUME
Andreas Schneider94275102015-08-24 19:55:42 +0200671int SetCallAudioPath(HRilClient client, AudioPath path, ExtraVolume mode)
672#else
673int SetCallAudioPath(HRilClient client, AudioPath path)
674#endif
675{
codeworkxf1587a32012-08-03 23:32:29 +0200676 RilClientPrv *client_prv;
677 int ret;
678 char data[6] = {0,};
679
680 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100681 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200682 return RIL_CLIENT_ERR_INVAL;
683 }
684
685 client_prv = (RilClientPrv *)(client->prv);
686
687 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100688 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200689 return RIL_CLIENT_ERR_CONNECT;
690 }
691
692 if (isValidAudioPath(path) == false) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100693 RLOGE("%s: Invalid audio path", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200694 return RIL_CLIENT_ERR_INVAL;
695 }
696
697 // Make raw data
698 data[0] = OEM_FUNC_SOUND;
699 data[1] = OEM_SND_SET_AUDIO_PATH;
700 data[2] = 0x00; // data length
701 data[3] = 0x06; // data length
702 data[4] = ConvertAudioPath(path); // audio path
Android-Andi40afadb2016-01-07 11:51:38 +0100703#ifdef RIL_CALL_AUDIO_PATH_EXTRAVOLUME
codeworkxf1587a32012-08-03 23:32:29 +0200704 data[5] = mode; // ExtraVolume
Andreas Schneider94275102015-08-24 19:55:42 +0200705#endif
codeworkxf1587a32012-08-03 23:32:29 +0200706
707 RegisterRequestCompleteHandler(client, REQ_SET_AUDIO_PATH, NULL);
708
709 ret = SendOemRequestHookRaw(client, REQ_SET_AUDIO_PATH, data, sizeof(data));
710 if (ret != RIL_CLIENT_ERR_SUCCESS) {
711 RegisterRequestCompleteHandler(client, REQ_SET_AUDIO_PATH, NULL);
712 }
713
714 return ret;
715}
716
717
718/**
719 * Set modem clock to master or slave.
720 */
721extern "C"
722int SetCallClockSync(HRilClient client, SoundClockCondition condition) {
723 RilClientPrv *client_prv;
724 int ret;
725 char data[5] = {0,};
726
727 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100728 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200729 return RIL_CLIENT_ERR_INVAL;
730 }
731
732 client_prv = (RilClientPrv *)(client->prv);
733
734 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100735 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200736 return RIL_CLIENT_ERR_CONNECT;
737 }
738
739 if (isValidSoundClockCondition(condition) == false) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100740 RLOGE("%s: Invalid sound clock condition", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200741 return RIL_CLIENT_ERR_INVAL;
742 }
743
744 // Make raw data
745 data[0] = OEM_FUNC_SOUND;
746 data[1] = OEM_SND_SET_CLOCK_CTRL;
747 data[2] = 0x00; // data length
748 data[3] = 0x05; // data length
749 data[4] = condition;
750
751 RegisterRequestCompleteHandler(client, REQ_SET_CALL_CLOCK_SYNC, NULL);
752
753 ret = SendOemRequestHookRaw(client, REQ_SET_CALL_CLOCK_SYNC, data, sizeof(data));
754 if (ret != RIL_CLIENT_ERR_SUCCESS) {
755 RegisterRequestCompleteHandler(client, REQ_SET_CALL_CLOCK_SYNC, NULL);
756 }
757
758 return ret;
759}
760
761/**
762 * Set modem VTCall clock to master or slave.
763 */
764extern "C"
765int SetVideoCallClockSync(HRilClient client, SoundClockCondition condition) {
766 RilClientPrv *client_prv;
767 int ret;
768 char data[5] = {0,};
769
770 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100771 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200772 return RIL_CLIENT_ERR_INVAL;
773 }
774
775 client_prv = (RilClientPrv *)(client->prv);
776
777 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100778 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200779 return RIL_CLIENT_ERR_CONNECT;
780 }
781
782 if (isValidSoundClockCondition(condition) == false) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100783 RLOGE("%s: Invalid sound clock condition", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200784 return RIL_CLIENT_ERR_INVAL;
785 }
786
787 // Make raw data
788 data[0] = OEM_FUNC_SOUND;
789 data[1] = OEM_SND_SET_VIDEO_CALL_CTRL;
790 data[2] = 0x00; // data length
791 data[3] = 0x05; // data length
792 data[4] = condition;
793
794 RegisterRequestCompleteHandler(client, REQ_SET_CALL_VT_CTRL, NULL);
795
796 ret = SendOemRequestHookRaw(client, REQ_SET_CALL_VT_CTRL, data, sizeof(data));
797 if (ret != RIL_CLIENT_ERR_SUCCESS) {
798 RegisterRequestCompleteHandler(client, REQ_SET_CALL_VT_CTRL, NULL);
799 }
800
801 return ret;
802}
803
804/**
805 * Set voice recording.
806 */
807extern "C"
808int SetCallRecord(HRilClient client, CallRecCondition condition) {
809 RilClientPrv *client_prv;
810 int ret;
811 char data[5] = {0,};
812
813 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100814 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200815 return RIL_CLIENT_ERR_INVAL;
816 }
817
818 client_prv = (RilClientPrv *)(client->prv);
819
820 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100821 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200822 return RIL_CLIENT_ERR_CONNECT;
823 }
824
825 if (isValidCallRecCondition(condition) == false) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100826 RLOGE("%s: Invalid sound clock condition", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200827 return RIL_CLIENT_ERR_INVAL;
828 }
829
830 // Make raw data
831 data[0] = OEM_FUNC_SOUND;
832 data[1] = OEM_SND_SET_VOICE_RECORDING_CTRL;
833 data[2] = 0x00; // data length
834 data[3] = 0x05; // data length
835 data[4] = condition;
836
837 RegisterRequestCompleteHandler(client, REQ_SET_CALL_RECORDING, NULL);
838
839 ret = SendOemRequestHookRaw(client, REQ_SET_CALL_RECORDING, data, sizeof(data));
840 if (ret != RIL_CLIENT_ERR_SUCCESS) {
841 RegisterRequestCompleteHandler(client, REQ_SET_CALL_RECORDING, NULL);
842 }
843
844 return ret;
845}
846
847/**
848 * Set mute or unmute.
849 */
850extern "C"
851int SetMute(HRilClient client, MuteCondition condition) {
852 RilClientPrv *client_prv;
853 int ret;
854 char data[5] = {0,};
855
856 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100857 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200858 return RIL_CLIENT_ERR_INVAL;
859 }
860
861 client_prv = (RilClientPrv *)(client->prv);
862
863 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100864 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200865 return RIL_CLIENT_ERR_CONNECT;
866 }
867
868 if (isValidMuteCondition(condition) == false) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100869 RLOGE("%s: Invalid sound clock condition", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200870 return RIL_CLIENT_ERR_INVAL;
871 }
872
873 // Make raw data
874 data[0] = OEM_FUNC_SOUND;
875 data[1] = OEM_SND_SET_MUTE;
876 data[2] = 0x00; // data length
877 data[3] = 0x05; // data length
878 data[4] = condition;
879
880 RegisterRequestCompleteHandler(client, REQ_SET_CALL_MUTE, NULL);
881
882 ret = SendOemRequestHookRaw(client, REQ_SET_CALL_MUTE, data, sizeof(data));
883 if (ret != RIL_CLIENT_ERR_SUCCESS) {
884 RegisterRequestCompleteHandler(client, REQ_SET_CALL_MUTE, NULL);
885 }
886
887 return ret;
888}
889
890/**
891 * Get mute state.
892 */
893extern "C"
894int GetMute(HRilClient client, RilOnComplete handler) {
895 RilClientPrv *client_prv;
896 int ret;
897 char data[4] = {0,};
898
899 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100900 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200901 return RIL_CLIENT_ERR_INVAL;
902 }
903
904 client_prv = (RilClientPrv *)(client->prv);
905
906 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100907 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200908 return RIL_CLIENT_ERR_CONNECT;
909 }
910
911 client_prv->b_del_handler = 1;
912
913 // Make raw data
914 data[0] = OEM_FUNC_SOUND;
915 data[1] = OEM_SND_GET_MUTE;
916 data[2] = 0x00; // data length
917 data[3] = 0x04; // data length
918
919 RegisterRequestCompleteHandler(client, REQ_GET_CALL_MUTE, handler);
920
921 ret = SendOemRequestHookRaw(client, REQ_GET_CALL_MUTE, data, sizeof(data));
922 if (ret != RIL_CLIENT_ERR_SUCCESS) {
923 RegisterRequestCompleteHandler(client, REQ_GET_CALL_MUTE, NULL);
924 }
925
926 return ret;
927}
928
929extern "C"
930int SetTwoMicControl(HRilClient client, TwoMicSolDevice device, TwoMicSolReport report) {
931 RilClientPrv *client_prv;
932 int ret;
933 char data[6] = {0,};
934
Andreas Schneider928ddca2017-02-08 16:52:54 +0100935 RLOGV(" + %s", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200936
937 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100938 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200939 return RIL_CLIENT_ERR_INVAL;
940 }
941
942 client_prv = (RilClientPrv *)(client->prv);
943
944 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100945 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200946 return RIL_CLIENT_ERR_CONNECT;
947 }
948
949 if (isValidTwoMicCtrl(device, report) == false) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100950 RLOGE("%s: Invalid sound set two params", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200951 return RIL_CLIENT_ERR_INVAL;
952 }
953
954 // Make raw data
955 data[0] = OEM_FUNC_SOUND;
956 data[1] = OEM_SND_SET_TWO_MIC_CTL;
957 data[2] = 0x00; // data length
958 data[3] = 0x06; // data length
959 data[4] = device;
960 data[5] = report;
961
962 RegisterRequestCompleteHandler(client, REQ_SET_TWO_MIC_CTRL, NULL);
963
964 ret = SendOemRequestHookRaw(client, REQ_SET_TWO_MIC_CTRL, data, sizeof(data));
965 if (ret != RIL_CLIENT_ERR_SUCCESS) {
966 RegisterRequestCompleteHandler(client, REQ_SET_TWO_MIC_CTRL, NULL);
967 }
968
Andreas Schneider928ddca2017-02-08 16:52:54 +0100969 RLOGV(" - %s", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200970
971 return ret;
972}
973
974extern "C"
975int SetDhaSolution(HRilClient client, DhaSolMode mode, DhaSolSelect select, char *parameter) {
976 RilClientPrv *client_prv;
977 int ret;
978 char data[30] = {0,};
979 char tempPara[24]={0,};
980
981 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100982 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200983 return RIL_CLIENT_ERR_INVAL;
984 }
985
986 client_prv = (RilClientPrv *)(client->prv);
987
988 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100989 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200990 return RIL_CLIENT_ERR_CONNECT;
991 }
992
Andreas Schneider560e37a2017-02-06 18:19:39 +0100993 RLOGE("%s: DHA mode=%d, select=%d", __FUNCTION__,mode, select);
codeworkxf1587a32012-08-03 23:32:29 +0200994
995 // Make raw data
996 data[0] = OEM_FUNC_SOUND;
997 data[1] = OEM_SND_SET_DHA_CTL;
998 data[2] = 0x00; // data length
999 data[3] = 0x1E; // data length
1000 data[4] = mode;
1001 data[5] = select;
1002
1003 memcpy(tempPara, parameter, 24);
1004 for(int i=0; i<24; i++)
1005 data[6+i]= tempPara[i];
1006
1007 RegisterRequestCompleteHandler(client, REQ_SET_DHA_CTRL, NULL);
1008
1009 ret = SendOemRequestHookRaw(client, REQ_SET_DHA_CTRL, data, sizeof(data));
1010 if (ret != RIL_CLIENT_ERR_SUCCESS) {
1011 RegisterRequestCompleteHandler(client, REQ_SET_DHA_CTRL, NULL);
1012 }
1013
1014 return ret;
1015}
1016
1017/**
1018 * Set LoopbackTest mode, path.
1019 */
1020extern "C"
1021int SetLoopbackTest(HRilClient client, LoopbackMode mode, AudioPath path) {
1022 RilClientPrv *client_prv;
1023 int ret;
1024 char data[6] = {0,};
1025
1026 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001027 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +02001028 return RIL_CLIENT_ERR_INVAL;
1029 }
1030
1031 client_prv = (RilClientPrv *)(client->prv);
1032
1033 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001034 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +02001035 return RIL_CLIENT_ERR_CONNECT;
1036 }
1037
1038 // Make raw data
1039 data[0] = OEM_FUNC_SOUND;
1040 data[1] = OEM_SND_SET_LOOPBACK_CTRL;
1041 data[2] = 0x00; // data length
1042 data[3] = 0x06; // data length
1043 data[4] = mode; // Loopback Mode
1044 data[5] = ConvertAudioPath(path); // Loopback path
1045
1046 RegisterRequestCompleteHandler(client, REQ_SET_LOOPBACK, NULL);
1047
1048 ret = SendOemRequestHookRaw(client, REQ_SET_LOOPBACK, data, sizeof(data));
1049 if (ret != RIL_CLIENT_ERR_SUCCESS) {
1050 RegisterRequestCompleteHandler(client, REQ_SET_LOOPBACK, NULL);
1051 }
1052
1053 return ret;
1054}
1055
1056
1057/**
1058 * @fn int InvokeOemRequestHookRaw(HRilClient client, char *data, size_t len)
1059 *
1060 * @params client: Client handle.
1061 * data: Request data.
1062 * len: Request data length.
1063 *
1064 * @return 0 for success or error code. On receiving RIL_CLIENT_ERR_AGAIN,
1065 * caller should retry.
1066 */
1067extern "C"
1068int InvokeOemRequestHookRaw(HRilClient client, char *data, size_t len) {
1069 RilClientPrv *client_prv;
1070
1071 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001072 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +02001073 return RIL_CLIENT_ERR_INVAL;
1074 }
1075
1076 client_prv = (RilClientPrv *)(client->prv);
1077
1078 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001079 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +02001080 return RIL_CLIENT_ERR_CONNECT;
1081 }
1082
1083 return SendOemRequestHookRaw(client, REQ_OEM_HOOK_RAW, data, len);
1084}
1085
1086
1087static int SendOemRequestHookRaw(HRilClient client, int req_id, char *data, size_t len) {
1088 int token = 0;
1089 int ret = 0;
1090 uint32_t header = 0;
1091 android::Parcel p;
1092 RilClientPrv *client_prv;
1093 int maxfd = -1;
1094
1095 client_prv = (RilClientPrv *)(client->prv);
1096
1097 // Allocate a token.
1098 token = AllocateToken(&(client_prv->token_pool));
1099 if (token == 0) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001100 RLOGE("%s: No token.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +02001101 return RIL_CLIENT_ERR_AGAIN;
1102 }
1103
1104 // Record token for the request sent.
1105 if (RecordReqHistory(client_prv, token, req_id) != RIL_CLIENT_ERR_SUCCESS) {
1106 goto error;
1107 }
1108
1109 // Make OEM request data.
1110 p.writeInt32(RIL_REQUEST_OEM_HOOK_RAW);
1111 p.writeInt32(token);
1112 p.writeInt32(len);
1113 p.write((void *)data, len);
1114
1115 // DO TX: header(size).
1116 header = htonl(p.dataSize());
1117
Andreas Schneider928ddca2017-02-08 16:52:54 +01001118 RLOGV("%s(): token = %d\n", __FUNCTION__, token);
codeworkxf1587a32012-08-03 23:32:29 +02001119
1120 ret = blockingWrite(client_prv->sock, (void *)&header, sizeof(header));
1121 if (ret < 0) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001122 RLOGE("%s: send request header failed. (%d)", __FUNCTION__, ret);
codeworkxf1587a32012-08-03 23:32:29 +02001123 goto error;
1124 }
1125
1126 // Do TX: response data.
1127 ret = blockingWrite(client_prv->sock, p.data(), p.dataSize());
1128 if (ret < 0) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001129 RLOGE("%s: send request data failed. (%d)", __FUNCTION__, ret);
codeworkxf1587a32012-08-03 23:32:29 +02001130 goto error;
1131 }
1132
1133 return RIL_CLIENT_ERR_SUCCESS;
1134
1135error:
1136 FreeToken(&(client_prv->token_pool), token);
1137 ClearReqHistory(client_prv, token);
1138
1139 return RIL_CLIENT_ERR_UNKNOWN;
1140}
1141
1142
1143static bool isValidSoundType(SoundType type) {
1144 return (type >= SOUND_TYPE_VOICE && type <= SOUND_TYPE_BTVOICE);
1145}
1146
1147
1148static bool isValidAudioPath(AudioPath path) {
Andreas Schneidere0058812017-02-14 17:24:02 +01001149 return (path >= SOUND_AUDIO_PATH_EARPIECE && path <= OEM_SND_AUDIO_PATH_BT_WB_NSEC_OFF);
codeworkxf1587a32012-08-03 23:32:29 +02001150}
1151
1152
1153static bool isValidSoundClockCondition(SoundClockCondition condition) {
1154 return (condition >= SOUND_CLOCK_STOP && condition <= SOUND_CLOCK_START);
1155}
1156
1157static bool isValidCallRecCondition(CallRecCondition condition) {
1158 return (condition >= CALL_REC_STOP && condition <= CALL_REC_START);
1159}
1160
1161static bool isValidMuteCondition(MuteCondition condition) {
1162 return (condition >= TX_UNMUTE && condition <= RXTX_MUTE);
1163}
1164
1165static bool isValidTwoMicCtrl(TwoMicSolDevice device, TwoMicSolReport report) {
1166 return (device >= AUDIENCE && device <= FORTEMEDIA && report >= TWO_MIC_SOLUTION_OFF && report <= TWO_MIC_SOLUTION_ON );
1167}
1168
1169
1170static char ConvertSoundType(SoundType type) {
1171 switch (type) {
1172 case SOUND_TYPE_VOICE:
1173 return OEM_SND_TYPE_VOICE;
1174 case SOUND_TYPE_SPEAKER:
1175 return OEM_SND_TYPE_SPEAKER;
1176 case SOUND_TYPE_HEADSET:
1177 return OEM_SND_TYPE_HEADSET;
1178 case SOUND_TYPE_BTVOICE:
1179 return OEM_SND_TYPE_BTVOICE;
1180 default:
1181 return OEM_SND_TYPE_VOICE;
1182 }
1183}
1184
1185
1186static char ConvertAudioPath(AudioPath path) {
1187 switch (path) {
Andreas Schneidere0058812017-02-14 17:24:02 +01001188 case SOUND_AUDIO_PATH_EARPIECE:
1189 return OEM_SND_AUDIO_PATH_EARPIECE;
codeworkxf1587a32012-08-03 23:32:29 +02001190 case SOUND_AUDIO_PATH_HEADSET:
1191 return OEM_SND_AUDIO_PATH_HEADSET;
1192 case SOUND_AUDIO_PATH_SPEAKER:
1193 return OEM_SND_AUDIO_PATH_SPEAKER;
1194 case SOUND_AUDIO_PATH_BLUETOOTH:
1195 return OEM_SND_AUDIO_PATH_BLUETOOTH;
1196 case SOUND_AUDIO_PATH_STEREO_BT:
1197 return OEM_SND_AUDIO_PATH_STEREO_BLUETOOTH;
1198 case SOUND_AUDIO_PATH_HEADPHONE:
1199 return OEM_SND_AUDIO_PATH_HEADPHONE;
1200 case SOUND_AUDIO_PATH_BLUETOOTH_NO_NR:
1201 return OEM_SND_AUDIO_PATH_BT_NSEC_OFF;
1202 case SOUND_AUDIO_PATH_MIC1:
1203 return OEM_SND_AUDIO_PATH_MIC1;
1204 case SOUND_AUDIO_PATH_MIC2:
1205 return OEM_SND_AUDIO_PATH_MIC2;
1206 case SOUND_AUDIO_PATH_BLUETOOTH_WB:
1207 return OEM_SND_AUDIO_PATH_BT_WB;
1208 case SOUND_AUDIO_PATH_BLUETOOTH_WB_NO_NR:
1209 return OEM_SND_AUDIO_PATH_BT_WB_NSEC_OFF;
1210
1211 default:
Andreas Schneidere0058812017-02-14 17:24:02 +01001212 return OEM_SND_AUDIO_PATH_EARPIECE;
codeworkxf1587a32012-08-03 23:32:29 +02001213 }
1214}
1215
1216
1217static void * RxReaderFunc(void *param) {
1218 RilClientPrv *client_prv = (RilClientPrv *)param;
1219 int maxfd = 0;
1220 int token = 0;
1221 void *p_record = NULL;
1222 size_t recordlen = 0;
1223 int ret = 0;
1224 int n;
1225
1226 if (client_prv == NULL)
1227 return NULL;
1228
1229 maxfd = max(client_prv->sock, client_prv->pipefd[0]) + 1;
1230
1231 printf("[*] %s() b_connect=%d, maxfd=%d\n", __FUNCTION__, client_prv->b_connect, maxfd);
1232 while (client_prv->b_connect) {
1233 FD_ZERO(&(client_prv->sock_rfds));
1234
1235 FD_SET(client_prv->sock, &(client_prv->sock_rfds));
1236 FD_SET(client_prv->pipefd[0], &(client_prv->sock_rfds));
1237
Andreas Schneider928ddca2017-02-08 16:52:54 +01001238 RLOGV("[*] %s() b_connect=%d\n", __FUNCTION__, client_prv->b_connect);
codeworkxf1587a32012-08-03 23:32:29 +02001239 if (select(maxfd, &(client_prv->sock_rfds), NULL, NULL, NULL) > 0) {
1240 if (FD_ISSET(client_prv->sock, &(client_prv->sock_rfds))) {
1241 // Read incoming data
1242 for (;;) {
1243 // loop until EAGAIN/EINTR, end of stream, or other error
1244 ret = record_stream_get_next(client_prv->p_rs, &p_record, &recordlen);
1245 if (ret == 0 && p_record == NULL) { // end-of-stream
1246 break;
1247 }
1248 else if (ret < 0) {
1249 break;
1250 }
1251 else if (ret == 0) { // && p_record != NULL
1252 n = processRxBuffer(client_prv, p_record, recordlen);
1253 if (n != RIL_CLIENT_ERR_SUCCESS) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001254 RLOGE("%s: processRXBuffer returns %d", __FUNCTION__, n);
codeworkxf1587a32012-08-03 23:32:29 +02001255 }
1256 }
1257 else {
1258 printf("[*] %s()\n", __FUNCTION__);
1259 }
1260 }
1261
1262 if (ret == 0 || !(errno == EAGAIN || errno == EINTR)) {
1263 // fatal error or end-of-stream
1264 if (client_prv->sock > 0) {
1265 close(client_prv->sock);
1266 client_prv->sock = -1;
1267 client_prv->b_connect = 0;
1268 }
1269
1270 if (client_prv->p_rs)
1271 record_stream_free(client_prv->p_rs);
1272
1273 // EOS
1274 if (client_prv->err_cb) {
1275 client_prv->err_cb(client_prv->err_cb_data, RIL_CLIENT_ERR_CONNECT);
1276 return NULL;
1277 }
1278
1279 break;
1280 }
1281 }
1282 if (FD_ISSET(client_prv->pipefd[0], &(client_prv->sock_rfds))) {
1283 char end_cmd[10];
1284
Andreas Schneider928ddca2017-02-08 16:52:54 +01001285 RLOGV("%s(): close\n", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +02001286
1287 if (read(client_prv->pipefd[0], end_cmd, sizeof(end_cmd)) > 0) {
1288 close(client_prv->sock);
1289 close(client_prv->pipefd[0]);
1290 close(client_prv->pipefd[1]);
1291
1292 client_prv->sock = -1;
1293 client_prv->b_connect = 0;
1294 }
1295 }
1296 }
1297 }
1298
1299 return NULL;
1300}
1301
1302
1303static int processUnsolicited(RilClientPrv *prv, Parcel &p) {
1304 int32_t resp_id, len;
1305 status_t status;
1306 const void *data = NULL;
1307 RilOnUnsolicited unsol_func = NULL;
1308
1309 status = p.readInt32(&resp_id);
1310 if (status != NO_ERROR) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001311 RLOGE("%s: read resp_id failed.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +02001312 return RIL_CLIENT_ERR_IO;
1313 }
1314
1315 status = p.readInt32(&len);
1316 if (status != NO_ERROR) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001317 //RLOGE("%s: read length failed. assume zero length.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +02001318 len = 0;
1319 }
1320
Andreas Schneider560e37a2017-02-06 18:19:39 +01001321 RLOGD("%s(): resp_id (%d), len(%d)\n", __FUNCTION__, resp_id, len);
codeworkxf1587a32012-08-03 23:32:29 +02001322
1323 if (len)
1324 data = p.readInplace(len);
1325
1326 // Find unsolicited response handler.
1327 unsol_func = FindUnsolHandler(prv, (uint32_t)resp_id);
1328 if (unsol_func) {
1329 unsol_func(prv->parent, data, len);
1330 }
1331
1332 return RIL_CLIENT_ERR_SUCCESS;
1333}
1334
1335
1336static int processSolicited(RilClientPrv *prv, Parcel &p) {
1337 int32_t token, err, len;
1338 status_t status;
1339 const void *data = NULL;
1340 RilOnComplete req_func = NULL;
1341 int ret = RIL_CLIENT_ERR_SUCCESS;
1342 uint32_t req_id = 0;
1343
Andreas Schneider928ddca2017-02-08 16:52:54 +01001344 RLOGV("%s()", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +02001345
1346 status = p.readInt32(&token);
1347 if (status != NO_ERROR) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001348 RLOGE("%s: Read token fail. Status %d\n", __FUNCTION__, status);
codeworkxf1587a32012-08-03 23:32:29 +02001349 return RIL_CLIENT_ERR_IO;
1350 }
1351
1352 if (IsValidToken(&(prv->token_pool), token) == 0) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001353 RLOGE("%s: Invalid Token", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +02001354 return RIL_CLIENT_ERR_INVAL; // Invalid token.
1355 }
1356
1357 status = p.readInt32(&err);
1358 if (status != NO_ERROR) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001359 RLOGE("%s: Read err fail. Status %d\n", __FUNCTION__, status);
codeworkxf1587a32012-08-03 23:32:29 +02001360 ret = RIL_CLIENT_ERR_IO;
1361 goto error;
1362 }
1363
1364 // Don't go further for error response.
1365 if (err != RIL_CLIENT_ERR_SUCCESS) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001366 RLOGE("%s: Error %d\n", __FUNCTION__, err);
codeworkxf1587a32012-08-03 23:32:29 +02001367 if (prv->err_cb)
1368 prv->err_cb(prv->err_cb_data, err);
1369 ret = RIL_CLIENT_ERR_SUCCESS;
1370 goto error;
1371 }
1372
1373 status = p.readInt32(&len);
1374 if (status != NO_ERROR) {
1375 /* no length field */
1376 len = 0;
1377 }
1378
1379 if (len)
1380 data = p.readInplace(len);
1381
1382 // Find request handler for the token.
1383 // First, FindReqHandler() searches request history with the token
1384 // and finds out a request ID. Then, it search request handler table
1385 // with the request ID.
1386 req_func = FindReqHandler(prv, token, &req_id);
1387 if (req_func)
1388 {
Andreas Schneider928ddca2017-02-08 16:52:54 +01001389 RLOGV("[*] Call handler");
codeworkxf1587a32012-08-03 23:32:29 +02001390 req_func(prv->parent, data, len);
1391
1392 if(prv->b_del_handler) {
1393 prv->b_del_handler = 0;
1394 RegisterRequestCompleteHandler(prv->parent, req_id, NULL);
1395 }
1396 } else {
Andreas Schneider928ddca2017-02-08 16:52:54 +01001397 RLOGV("%s: No handler for token %d\n", __FUNCTION__, token);
codeworkxf1587a32012-08-03 23:32:29 +02001398 }
1399
1400error:
1401 FreeToken(&(prv->token_pool), token);
1402 ClearReqHistory(prv, token);
1403 return ret;
1404}
1405
1406
1407static int processRxBuffer(RilClientPrv *prv, void *buffer, size_t buflen) {
1408 Parcel p;
1409 int32_t response_type;
1410 status_t status;
1411 int ret = RIL_CLIENT_ERR_SUCCESS;
1412
1413 acquire_wake_lock(PARTIAL_WAKE_LOCK, RIL_CLIENT_WAKE_LOCK);
1414
1415 p.setData((uint8_t *)buffer, buflen);
1416
1417 status = p.readInt32(&response_type);
Andreas Schneider928ddca2017-02-08 16:52:54 +01001418 RLOGV("%s: status %d response_type %d", __FUNCTION__, status, response_type);
codeworkxf1587a32012-08-03 23:32:29 +02001419
1420 if (status != NO_ERROR) {
1421 ret = RIL_CLIENT_ERR_IO;
1422 goto EXIT;
1423 }
1424
1425 // FOr unsolicited response.
1426 if (response_type == RESPONSE_UNSOLICITED) {
1427 ret = processUnsolicited(prv, p);
1428 }
1429 // For solicited response.
1430 else if (response_type == RESPONSE_SOLICITED) {
1431 ret = processSolicited(prv, p);
1432 if (ret != RIL_CLIENT_ERR_SUCCESS && prv->err_cb) {
1433 prv->err_cb(prv->err_cb_data, ret);
1434 }
1435 }
1436 else {
1437 ret = RIL_CLIENT_ERR_INVAL;
1438 }
1439
1440EXIT:
1441 release_wake_lock(RIL_CLIENT_WAKE_LOCK);
1442 return ret;
1443}
1444
1445
1446static uint32_t AllocateToken(uint32_t *token_pool) {
1447 int i;
1448
1449 // Token pool is full.
1450 if (*token_pool == 0xFFFFFFFF)
1451 return 0;
1452
1453 for (i = 0; i < 32; i++) {
1454 uint32_t new_token = 0x00000001 << i;
1455
1456 if ((*token_pool & new_token) == 0) {
1457 *token_pool |= new_token;
1458 return new_token;
1459 }
1460 }
1461
1462 return 0;
1463}
1464
1465
1466static void FreeToken(uint32_t *token_pool, uint32_t token) {
1467 *token_pool &= ~token;
1468}
1469
1470
1471static uint8_t IsValidToken(uint32_t *token_pool, uint32_t token) {
1472 if (token == 0)
1473 return 0;
1474
1475 if ((*token_pool & token) == token)
1476 return 1;
1477 else
1478 return 0;
1479}
1480
1481
1482static int RecordReqHistory(RilClientPrv *prv, int token, uint32_t id) {
1483 int i = 0;
1484
Andreas Schneider928ddca2017-02-08 16:52:54 +01001485 RLOGV("[*] %s(): token(%d), ID(%d)\n", __FUNCTION__, token, id);
codeworkxf1587a32012-08-03 23:32:29 +02001486 for (i = 0; i < TOKEN_POOL_SIZE; i++) {
1487 if (prv->history[i].token == 0) {
1488 prv->history[i].token = token;
1489 prv->history[i].id = id;
1490
Andreas Schneider928ddca2017-02-08 16:52:54 +01001491 RLOGV("[*] %s(): token(%d), ID(%d)\n", __FUNCTION__, token, id);
codeworkxf1587a32012-08-03 23:32:29 +02001492
1493 return RIL_CLIENT_ERR_SUCCESS;
1494 }
1495 }
1496
Andreas Schneider560e37a2017-02-06 18:19:39 +01001497 RLOGE("%s: No free record for token %d", __FUNCTION__, token);
codeworkxf1587a32012-08-03 23:32:29 +02001498
1499 return RIL_CLIENT_ERR_RESOURCE;
1500}
1501
1502static void ClearReqHistory(RilClientPrv *prv, int token) {
1503 int i = 0;
1504
Andreas Schneider928ddca2017-02-08 16:52:54 +01001505 RLOGV("[*] %s(): token(%d)\n", __FUNCTION__, token);
codeworkxf1587a32012-08-03 23:32:29 +02001506 for (i = 0; i < TOKEN_POOL_SIZE; i++) {
1507 if (prv->history[i].token == token) {
1508 memset(&(prv->history[i]), 0, sizeof(ReqHistory));
1509 break;
1510 }
1511 }
1512}
1513
1514
1515static RilOnUnsolicited FindUnsolHandler(RilClientPrv *prv, uint32_t id) {
1516 int i;
1517
1518 // Search unsolicited handler table.
1519 for (i = 0; i < REQ_POOL_SIZE; i++) {
1520 if (prv->unsol_handlers[i].id == id)
1521 return prv->unsol_handlers[i].handler;
1522 }
1523
1524 return (RilOnUnsolicited)NULL;
1525}
1526
1527
1528static RilOnComplete FindReqHandler(RilClientPrv *prv, int token, uint32_t *id) {
1529 int i = 0;
1530 int j = 0;
1531
Andreas Schneider928ddca2017-02-08 16:52:54 +01001532 RLOGV("[*] %s(): token(%d)\n", __FUNCTION__, token);
codeworkxf1587a32012-08-03 23:32:29 +02001533
1534 // Search request history.
1535 for (i = 0; i < TOKEN_POOL_SIZE; i++) {
1536 printf("[*] %s(): history_token(%d)\n", __FUNCTION__, prv->history[i].token);
1537 if (prv->history[i].token == token) {
1538 // Search request handler with request ID found.
1539 for (j = 0; j < REQ_POOL_SIZE; j++) {
1540 printf("[*] %s(): token(%d), req_id(%d), history_id(%d)\n", __FUNCTION__, token, prv->history[i].id, prv->history[i].id);
1541 if (prv->req_handlers[j].id == prv->history[i].id) {
1542 *id = prv->req_handlers[j].id;
1543 return prv->req_handlers[j].handler;
1544 }
1545 }
1546 }
1547 }
1548
1549 return NULL;
1550}
1551
1552
1553static void DeallocateToken(uint32_t *token_pool, uint32_t token) {
1554 *token_pool &= !token;
1555}
1556
1557
1558static int blockingWrite(int fd, const void *buffer, size_t len) {
1559 size_t writeOffset = 0;
1560 const uint8_t *toWrite;
1561 ssize_t written = 0;
1562
1563 if (buffer == NULL)
1564 return -1;
1565
1566 toWrite = (const uint8_t *)buffer;
1567
1568 while (writeOffset < len) {
1569 do
1570 {
1571 written = write(fd, toWrite + writeOffset, len - writeOffset);
1572 } while (written < 0 && errno == EINTR);
1573
1574 if (written >= 0) {
1575 writeOffset += written;
1576 }
1577 else {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001578 RLOGE ("RIL Response: unexpected error on write errno:%d", errno);
codeworkxf1587a32012-08-03 23:32:29 +02001579 printf("RIL Response: unexpected error on write errno:%d\n", errno);
1580 close(fd);
1581 return -1;
1582 }
1583 }
1584
1585 return 0;
1586}
1587
1588} // namespace android
1589
1590// end of file
1591