blob: e2cd87885ec0f1278b519b6ca9a0a262d2a07b91 [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>
Sean hoyt7ef59ce2017-08-23 12:05:55 +000024#include <android/log.h>
codeworkxf1587a32012-08-03 23:32:29 +020025#include <pthread.h>
26#include "secril-client.h"
27#include <hardware_legacy/power.h> // For wakelock
28
29
30#define RIL_CLIENT_WAKE_LOCK "client-interface"
31
32namespace android {
33
34//---------------------------------------------------------------------------
35// Defines
36//---------------------------------------------------------------------------
codeworkxf1587a32012-08-03 23:32:29 +020037#define RILD_PORT 7777
38#define MULTI_CLIENT_SOCKET_NAME "Multiclient"
39#define MULTI_CLIENT_Q_SOCKET_NAME "QMulticlient"
codeworkxf1587a32012-08-03 23:32:29 +020040#define MULTI_CLIENT_SOCKET_NAME_2 "Multiclient2"
codeworkxf1587a32012-08-03 23:32:29 +020041
42#define MAX_COMMAND_BYTES (8 * 1024)
43#define REQ_POOL_SIZE 32
44#define TOKEN_POOL_SIZE 32
45
46// Constants for response types
47#define RESPONSE_SOLICITED 0
48#define RESPONSE_UNSOLICITED 1
49
50#define max(a, b) ((a) > (b) ? (a) : (b))
51
52#define REQ_OEM_HOOK_RAW RIL_REQUEST_OEM_HOOK_RAW
53#define REQ_SET_CALL_VOLUME 101
54#define REQ_SET_AUDIO_PATH 102
55#define REQ_SET_CALL_CLOCK_SYNC 103
56#define REQ_SET_CALL_RECORDING 104
57#define REQ_SET_CALL_MUTE 105
58#define REQ_GET_CALL_MUTE 106
59#define REQ_SET_CALL_VT_CTRL 107
60#define REQ_SET_TWO_MIC_CTRL 108
61#define REQ_SET_DHA_CTRL 109
62#define REQ_SET_LOOPBACK 110
63
64// OEM request function ID
65#define OEM_FUNC_SOUND 0x08
66
67// OEM request sub function ID
68#define OEM_SND_SET_VOLUME_CTRL 0x03
69#define OEM_SND_SET_AUDIO_PATH 0x05
70#define OEM_SND_GET_AUDIO_PATH 0x06
71#define OEM_SND_SET_VIDEO_CALL_CTRL 0x07
72#define OEM_SND_SET_LOOPBACK_CTRL 0x08
73#define OEM_SND_SET_VOICE_RECORDING_CTRL 0x09
74#define OEM_SND_SET_CLOCK_CTRL 0x0A
75#define OEM_SND_SET_MUTE 0x0B
76#define OEM_SND_GET_MUTE 0x0C
77#define OEM_SND_SET_TWO_MIC_CTL 0x0D
78#define OEM_SND_SET_DHA_CTL 0x0E
79
80#define OEM_SND_TYPE_VOICE 0x01 // Receiver(0x00) + Voice(0x01)
81#define OEM_SND_TYPE_SPEAKER 0x11 // SpeakerPhone(0x10) + Voice(0x01)
82#define OEM_SND_TYPE_HEADSET 0x31 // Headset(0x30) + Voice(0x01)
83#define OEM_SND_TYPE_BTVOICE 0x41 // BT(0x40) + Voice(0x01)
84
Christopher N. Hesse57eacca2016-03-08 15:50:23 +010085#ifdef SAMSUNG_NEXT_GEN_MODEM
Andreas Schneidere0058812017-02-14 17:24:02 +010086#define OEM_SND_AUDIO_PATH_EARPIECE 0x01
Andreas Schneider6b9cd5f2015-01-23 22:41:22 +010087#define OEM_SND_AUDIO_PATH_HEADSET 0x02
88#define OEM_SND_AUDIO_PATH_HFK 0x06
89#define OEM_SND_AUDIO_PATH_BLUETOOTH 0x04
90#define OEM_SND_AUDIO_PATH_STEREO_BLUETOOTH 0x05
91#define OEM_SND_AUDIO_PATH_SPEAKER 0x07
92#define OEM_SND_AUDIO_PATH_HEADPHONE 0x08
93#define OEM_SND_AUDIO_PATH_BT_NSEC_OFF 0x09
94#define OEM_SND_AUDIO_PATH_MIC1 0x0A
95#define OEM_SND_AUDIO_PATH_MIC2 0x0B
96#define OEM_SND_AUDIO_PATH_BT_WB 0x0C
97#define OEM_SND_AUDIO_PATH_BT_WB_NSEC_OFF 0x0D
98#else
Andreas Schneidere0058812017-02-14 17:24:02 +010099#define OEM_SND_AUDIO_PATH_EARPIECE 0x01
codeworkxf1587a32012-08-03 23:32:29 +0200100#define OEM_SND_AUDIO_PATH_HEADSET 0x02
101#define OEM_SND_AUDIO_PATH_HFK 0x03
102#define OEM_SND_AUDIO_PATH_BLUETOOTH 0x04
103#define OEM_SND_AUDIO_PATH_STEREO_BLUETOOTH 0x05
104#define OEM_SND_AUDIO_PATH_SPEAKER 0x06
105#define OEM_SND_AUDIO_PATH_HEADPHONE 0x07
106#define OEM_SND_AUDIO_PATH_BT_NSEC_OFF 0x08
107#define OEM_SND_AUDIO_PATH_MIC1 0x09
108#define OEM_SND_AUDIO_PATH_MIC2 0x0A
109#define OEM_SND_AUDIO_PATH_BT_WB 0x0B
110#define OEM_SND_AUDIO_PATH_BT_WB_NSEC_OFF 0x0C
Andreas Schneider6b9cd5f2015-01-23 22:41:22 +0100111#endif
codeworkxf1587a32012-08-03 23:32:29 +0200112
113//---------------------------------------------------------------------------
114// Type definitions
115//---------------------------------------------------------------------------
116typedef struct _ReqHistory {
117 int token; // token used for request
118 uint32_t id; // request ID
119} ReqHistory;
120
121typedef struct _ReqRespHandler {
122 uint32_t id; // request ID
123 RilOnComplete handler; // handler function
124} ReqRespHandler;
125
126typedef struct _UnsolHandler {
127 uint32_t id; // unsolicited response ID
128 RilOnUnsolicited handler; // handler function
129} UnsolHandler;
130
131typedef struct _RilClientPrv {
132 HRilClient parent;
133 uint8_t b_connect; // connected to server?
134 int sock; // socket
135 int pipefd[2];
136 fd_set sock_rfds; // for read with select()
137 RecordStream *p_rs;
138 uint32_t token_pool; // each bit in token_pool used for token.
139 // so, pool size is 32.
140 pthread_t tid_reader; // socket reader thread id
141 ReqHistory history[TOKEN_POOL_SIZE]; // request history
142 ReqRespHandler req_handlers[REQ_POOL_SIZE]; // request response handler list
143 UnsolHandler unsol_handlers[REQ_POOL_SIZE]; // unsolicited response handler list
144 RilOnError err_cb; // error callback
145 void *err_cb_data; // error callback data
146 uint8_t b_del_handler;
147} RilClientPrv;
148
149
150//---------------------------------------------------------------------------
151// Local static function prototypes
152//---------------------------------------------------------------------------
153static void * RxReaderFunc(void *param);
154static int processRxBuffer(RilClientPrv *prv, void *buffer, size_t buflen);
155static uint32_t AllocateToken(uint32_t *token_pool);
156static void FreeToken(uint32_t *token_pool, uint32_t token);
157static uint8_t IsValidToken(uint32_t *token_pool, uint32_t token);
codeworkxf1587a32012-08-03 23:32:29 +0200158static int blockingWrite(int fd, const void *buffer, size_t len);
159static int RecordReqHistory(RilClientPrv *prv, int token, uint32_t id);
160static void ClearReqHistory(RilClientPrv *prv, int token);
161static RilOnComplete FindReqHandler(RilClientPrv *prv, int token, uint32_t *id);
162static RilOnUnsolicited FindUnsolHandler(RilClientPrv *prv, uint32_t id);
163static int SendOemRequestHookRaw(HRilClient client, int req_id, char *data, size_t len);
164static bool isValidSoundType(SoundType type);
165static bool isValidAudioPath(AudioPath path);
166static bool isValidSoundClockCondition(SoundClockCondition condition);
167static bool isValidCallRecCondition(CallRecCondition condition);
168static bool isValidMuteCondition(MuteCondition condition);
169static bool isValidTwoMicCtrl(TwoMicSolDevice device, TwoMicSolReport report);
170static char ConvertSoundType(SoundType type);
171static char ConvertAudioPath(AudioPath path);
172
173
174/**
175 * @fn int RegisterUnsolicitedHandler(HRilClient client, uint32_t id, RilOnUnsolicited handler)
176 *
177 * @params client: Client handle.
178 * id: Unsolicited response ID to which handler is registered.
179 * handler: Unsolicited handler. NULL for deregistration.
180 *
181 * @return 0 on success or error code.
182 */
183extern "C"
184int RegisterUnsolicitedHandler(HRilClient client, uint32_t id, RilOnUnsolicited handler) {
185 RilClientPrv *client_prv;
186 int match_slot = -1;
187 int first_empty_slot = -1;
188 int i;
189
190 if (client == NULL || client->prv == NULL)
191 return RIL_CLIENT_ERR_INVAL;
192
193 client_prv = (RilClientPrv *)(client->prv);
194
195 for (i = 0; i < REQ_POOL_SIZE; i++) {
196 // Check if there is matched handler.
197 if (id == client_prv->unsol_handlers[i].id) {
198 match_slot = i;
199 }
200 // Find first empty handler slot.
201 if (first_empty_slot == -1 && client_prv->unsol_handlers[i].id == 0) {
202 first_empty_slot = i;
203 }
204 }
205
206 if (handler == NULL) { // Unregister.
207 if (match_slot >= 0) {
208 memset(&(client_prv->unsol_handlers[match_slot]), 0, sizeof(UnsolHandler));
209 return RIL_CLIENT_ERR_SUCCESS;
210 }
211 else {
212 return RIL_CLIENT_ERR_SUCCESS;
213 }
214 }
215 else {// Register.
216 if (match_slot >= 0) {
217 client_prv->unsol_handlers[match_slot].handler = handler; // Just update.
218 }
219 else if (first_empty_slot >= 0) {
220 client_prv->unsol_handlers[first_empty_slot].id = id;
221 client_prv->unsol_handlers[first_empty_slot].handler = handler;
222 }
223 else {
224 return RIL_CLIENT_ERR_RESOURCE;
225 }
226 }
227
228 return RIL_CLIENT_ERR_SUCCESS;
229}
230
231
232/**
233 * @fn int RegisterRequestCompleteHandler(HRilClient client, uint32_t id, RilOnComplete handler)
234 *
235 * @params client: Client handle.
236 * id: Request ID to which handler is registered.
237 * handler: Request complete handler. NULL for deregistration.
238 *
239 * @return 0 on success or error code.
240 */
241extern "C"
242int RegisterRequestCompleteHandler(HRilClient client, uint32_t id, RilOnComplete handler) {
243 RilClientPrv *client_prv;
244 int match_slot = -1;
245 int first_empty_slot = -1;
246 int i;
247
248 if (client == NULL || client->prv == NULL)
249 return RIL_CLIENT_ERR_INVAL;
250
251 client_prv = (RilClientPrv *)(client->prv);
252
253 for (i = 0; i < REQ_POOL_SIZE; i++) {
254 // Check if there is matched handler.
255 if (id == client_prv->req_handlers[i].id) {
256 match_slot = i;
257 }
258 // Find first empty handler slot.
259 if (first_empty_slot == -1 && client_prv->req_handlers[i].id == 0) {
260 first_empty_slot = i;
261 }
262 }
263
264 if (handler == NULL) { // Unregister.
265 if (match_slot >= 0) {
266 memset(&(client_prv->req_handlers[match_slot]), 0, sizeof(ReqRespHandler));
267 return RIL_CLIENT_ERR_SUCCESS;
268 }
269 else {
270 return RIL_CLIENT_ERR_SUCCESS;
271 }
272 }
273 else { // Register.
274 if (match_slot >= 0) {
275 client_prv->req_handlers[match_slot].handler = handler; // Just update.
276 }
277 else if (first_empty_slot >= 0) {
278 client_prv->req_handlers[first_empty_slot].id = id;
279 client_prv->req_handlers[first_empty_slot].handler = handler;
280 }
281 else {
282 return RIL_CLIENT_ERR_RESOURCE;
283 }
284 }
285
286 return RIL_CLIENT_ERR_SUCCESS;
287}
288
289
290/**
291 * @fn int RegisterErrorCallback(HRilClient client, RilOnError cb, void *data)
292 *
293 * @params client: Client handle.
294 * cb: Error callback. NULL for unregistration.
295 * data: Callback data.
296 *
297 * @return 0 for success or error code.
298 */
299extern "C"
300int RegisterErrorCallback(HRilClient client, RilOnError cb, void *data) {
301 RilClientPrv *client_prv;
302
303 if (client == NULL || client->prv == NULL)
304 return RIL_CLIENT_ERR_INVAL;
305
306 client_prv = (RilClientPrv *)(client->prv);
307
308 client_prv->err_cb = cb;
309 client_prv->err_cb_data = data;
310
311 return RIL_CLIENT_ERR_SUCCESS;
312}
313
314
315/**
316 * @fn HRilClient OpenClient_RILD(void)
317 *
318 * @params None.
319 *
320 * @return Client handle, NULL on error.
321 */
322extern "C"
323HRilClient OpenClient_RILD(void) {
324 HRilClient client = (HRilClient)malloc(sizeof(struct RilClient));
325 if (client == NULL)
326 return NULL;
327
328 client->prv = (RilClientPrv *)malloc(sizeof(RilClientPrv));
329 if (client->prv == NULL) {
330 free(client);
331 return NULL;
332 }
333
334 memset(client->prv, 0, sizeof(RilClientPrv));
335
336 ((RilClientPrv *)(client->prv))->parent = client;
337 ((RilClientPrv *)(client->prv))->sock = -1;
338
339 return client;
340}
341
342
343/**
344 * @fn int Connect_RILD(void)
345 *
346 * @params client: Client handle.
347 *
348 * @return 0, or error code.
349 */
350extern "C"
351int Connect_RILD(HRilClient client) {
352 RilClientPrv *client_prv;
353
354 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100355 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200356 return RIL_CLIENT_ERR_INVAL;
357 }
358
359 client_prv = (RilClientPrv *)(client->prv);
360
361 // Open client socket and connect to server.
362 //client_prv->sock = socket_loopback_client(RILD_PORT, SOCK_STREAM);
363 client_prv->sock = socket_local_client(MULTI_CLIENT_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM );
364
365 if (client_prv->sock < 0) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100366 RLOGE("%s: Connecting failed. %s(%d)", __FUNCTION__, strerror(errno), errno);
codeworkxf1587a32012-08-03 23:32:29 +0200367 return RIL_CLIENT_ERR_CONNECT;
368 }
369
370 client_prv->b_connect = 1;
371
372 if (fcntl(client_prv->sock, F_SETFL, O_NONBLOCK) < 0) {
373 close(client_prv->sock);
374 return RIL_CLIENT_ERR_IO;
375 }
376
377 client_prv->p_rs = record_stream_new(client_prv->sock, MAX_COMMAND_BYTES);
378
379 if (pipe(client_prv->pipefd) < 0) {
380 close(client_prv->sock);
Andreas Schneider560e37a2017-02-06 18:19:39 +0100381 RLOGE("%s: Creating command pipe failed. %s(%d)", __FUNCTION__, strerror(errno), errno);
codeworkxf1587a32012-08-03 23:32:29 +0200382 return RIL_CLIENT_ERR_IO;
383 }
384
385 if (fcntl(client_prv->pipefd[0], F_SETFL, O_NONBLOCK) < 0) {
386 close(client_prv->sock);
387 close(client_prv->pipefd[0]);
388 close(client_prv->pipefd[1]);
389 return RIL_CLIENT_ERR_IO;
390 }
391
392 // Start socket read thread.
393 if (pthread_create(&(client_prv->tid_reader), NULL, RxReaderFunc, (void *)client_prv) != 0) {
394 close(client_prv->sock);
395 close(client_prv->pipefd[0]);
396 close(client_prv->pipefd[1]);
397
398 memset(client_prv, 0, sizeof(RilClientPrv));
399 client_prv->sock = -1;
Andreas Schneider560e37a2017-02-06 18:19:39 +0100400 RLOGE("%s: Can't create Reader thread. %s(%d)", __FUNCTION__, strerror(errno), errno);
codeworkxf1587a32012-08-03 23:32:29 +0200401 return RIL_CLIENT_ERR_CONNECT;
402 }
403
404 return RIL_CLIENT_ERR_SUCCESS;
405}
406
407/**
408 * @fn int Connect_QRILD(void)
409 *
410 * @params client: Client handle.
411 *
412 * @return 0, or error code.
413 */
414extern "C"
415int Connect_QRILD(HRilClient client) {
416 RilClientPrv *client_prv;
417
418 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100419 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200420 return RIL_CLIENT_ERR_INVAL;
421 }
422
423 client_prv = (RilClientPrv *)(client->prv);
424
425 // Open client socket and connect to server.
426 //client_prv->sock = socket_loopback_client(RILD_PORT, SOCK_STREAM);
427 client_prv->sock = socket_local_client(MULTI_CLIENT_Q_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM );
428
429 if (client_prv->sock < 0) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100430 RLOGE("%s: Connecting failed. %s(%d)", __FUNCTION__, strerror(errno), errno);
codeworkxf1587a32012-08-03 23:32:29 +0200431 return RIL_CLIENT_ERR_CONNECT;
432 }
433
434 client_prv->b_connect = 1;
435
436 if (fcntl(client_prv->sock, F_SETFL, O_NONBLOCK) < 0) {
437 close(client_prv->sock);
438 return RIL_CLIENT_ERR_IO;
439 }
440
441 client_prv->p_rs = record_stream_new(client_prv->sock, MAX_COMMAND_BYTES);
442
443 if (pipe(client_prv->pipefd) < 0) {
444 close(client_prv->sock);
Andreas Schneider560e37a2017-02-06 18:19:39 +0100445 RLOGE("%s: Creating command pipe failed. %s(%d)", __FUNCTION__, strerror(errno), errno);
codeworkxf1587a32012-08-03 23:32:29 +0200446 return RIL_CLIENT_ERR_IO;
447 }
448
449 if (fcntl(client_prv->pipefd[0], F_SETFL, O_NONBLOCK) < 0) {
450 close(client_prv->sock);
451 close(client_prv->pipefd[0]);
452 close(client_prv->pipefd[1]);
453 return RIL_CLIENT_ERR_IO;
454 }
455
456 // Start socket read thread.
457 if (pthread_create(&(client_prv->tid_reader), NULL, RxReaderFunc, (void *)client_prv) != 0) {
458 close(client_prv->sock);
459 close(client_prv->pipefd[0]);
460 close(client_prv->pipefd[1]);
461
462 memset(client_prv, 0, sizeof(RilClientPrv));
463 client_prv->sock = -1;
Andreas Schneider560e37a2017-02-06 18:19:39 +0100464 RLOGE("%s: Can't create Reader thread. %s(%d)", __FUNCTION__, strerror(errno), errno);
codeworkxf1587a32012-08-03 23:32:29 +0200465 return RIL_CLIENT_ERR_CONNECT;
466 }
467
468 return RIL_CLIENT_ERR_SUCCESS;
469}
470
codeworkxf1587a32012-08-03 23:32:29 +0200471/**
472 * @fn int Connect_RILD_Second(void)
473 *
474 * @params client: Client handle.
475 *
476 * @return 0, or error code.
477 */
478extern "C"
479int Connect_RILD_Second(HRilClient client) {
480 RilClientPrv *client_prv;
481
482 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100483 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200484 return RIL_CLIENT_ERR_INVAL;
485 }
486
487 client_prv = (RilClientPrv *)(client->prv);
488
489 // Open client socket and connect to server.
490 //client_prv->sock = socket_loopback_client(RILD_PORT, SOCK_STREAM);
491 client_prv->sock = socket_local_client(MULTI_CLIENT_SOCKET_NAME_2, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM );
492
493 if (client_prv->sock < 0) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100494 RLOGE("%s: Connecting failed. %s(%d)", __FUNCTION__, strerror(errno), errno);
codeworkxf1587a32012-08-03 23:32:29 +0200495 return RIL_CLIENT_ERR_CONNECT;
496 }
497
498 client_prv->b_connect = 1;
499
500 if (fcntl(client_prv->sock, F_SETFL, O_NONBLOCK) < 0) {
501 close(client_prv->sock);
502 return RIL_CLIENT_ERR_IO;
503 }
504
505 client_prv->p_rs = record_stream_new(client_prv->sock, MAX_COMMAND_BYTES);
506
507 if (pipe(client_prv->pipefd) < 0) {
508 close(client_prv->sock);
Andreas Schneider560e37a2017-02-06 18:19:39 +0100509 RLOGE("%s: Creating command pipe failed. %s(%d)", __FUNCTION__, strerror(errno), errno);
codeworkxf1587a32012-08-03 23:32:29 +0200510 return RIL_CLIENT_ERR_IO;
511 }
512
513 if (fcntl(client_prv->pipefd[0], F_SETFL, O_NONBLOCK) < 0) {
514 close(client_prv->sock);
515 close(client_prv->pipefd[0]);
516 close(client_prv->pipefd[1]);
517 return RIL_CLIENT_ERR_IO;
518 }
519
520 // Start socket read thread.
521 if (pthread_create(&(client_prv->tid_reader), NULL, RxReaderFunc, (void *)client_prv) != 0) {
522 close(client_prv->sock);
523 close(client_prv->pipefd[0]);
524 close(client_prv->pipefd[1]);
525
526 memset(client_prv, 0, sizeof(RilClientPrv));
527 client_prv->sock = -1;
Andreas Schneider560e37a2017-02-06 18:19:39 +0100528 RLOGE("%s: Can't create Reader thread. %s(%d)", __FUNCTION__, strerror(errno), errno);
codeworkxf1587a32012-08-03 23:32:29 +0200529 return RIL_CLIENT_ERR_CONNECT;
530 }
531
532 return RIL_CLIENT_ERR_SUCCESS;
533}
codeworkxf1587a32012-08-03 23:32:29 +0200534
535/**
536 * @fn int isConnected_RILD(HRilClient client)
537 *
538 * @params client: Client handle.
539 *
540 * @return 0, or 1.
541 */
542extern "C"
543int isConnected_RILD(HRilClient client) {
544 RilClientPrv *client_prv;
545
546 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100547 RLOGE("%s: invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200548 return RIL_CLIENT_ERR_INVAL;
549 }
550
551 client_prv = (RilClientPrv *)(client->prv);
552
553 return client_prv->b_connect == 1;
554}
555
556/**
557 * @fn int Disconnect_RILD(HRilClient client)
558 *
559 * @params client: Client handle.
560 *
561 * @return 0 on success, or error code.
562 */
563extern "C"
564int Disconnect_RILD(HRilClient client) {
565 RilClientPrv *client_prv;
566 int ret = 0;
567
568 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100569 RLOGE("%s: invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200570 return RIL_CLIENT_ERR_INVAL;
571 }
572
573 client_prv = (RilClientPrv *)(client->prv);
574
575 if (client_prv->sock == -1)
576 return RIL_CLIENT_ERR_SUCCESS;
577
578 printf("[*] %s(): sock=%d\n", __FUNCTION__, client_prv->sock);
579
580 if (client_prv->sock > 0) {
581 do {
582 ret = write(client_prv->pipefd[1], "close", strlen("close"));
583 } while (ret < 0 && errno == EINTR);
584 }
585
586 client_prv->b_connect = 0;
587
588 pthread_join(client_prv->tid_reader, NULL);
589
590 return RIL_CLIENT_ERR_SUCCESS;
591}
592
593
594/**
595 * @fn int CloseClient_RILD(HRilClient client)
596 *
597 * @params client: Client handle.
598 *
599 * @return 0 on success, or error code.
600 */
601extern "C"
602int CloseClient_RILD(HRilClient client) {
603 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100604 RLOGE("%s: invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200605 return RIL_CLIENT_ERR_INVAL;
606 }
607
608 Disconnect_RILD(client);
609
610 free(client->prv);
611 free(client);
612
613 return RIL_CLIENT_ERR_SUCCESS;
614}
615
616
617/**
618 * Set in-call volume.
619 */
620extern "C"
621int SetCallVolume(HRilClient client, SoundType type, int vol_level) {
622 RilClientPrv *client_prv;
623 int ret;
624 char data[6] = {0,};
625
626 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100627 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200628 return RIL_CLIENT_ERR_INVAL;
629 }
630
631 client_prv = (RilClientPrv *)(client->prv);
632
633 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100634 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200635 return RIL_CLIENT_ERR_CONNECT;
636 }
637
638 if (isValidSoundType(type) == false) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100639 RLOGE("%s: Invalid sound type", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200640 return RIL_CLIENT_ERR_INVAL;
641 }
642
643 // Make raw data
644 data[0] = OEM_FUNC_SOUND;
645 data[1] = OEM_SND_SET_VOLUME_CTRL;
646 data[2] = 0x00; // data length
647 data[3] = 0x06; // data length
648 data[4] = ConvertSoundType(type); // volume type
649 data[5] = vol_level; // volume level
650
651 RegisterRequestCompleteHandler(client, REQ_SET_CALL_VOLUME, NULL);
652
653 ret = SendOemRequestHookRaw(client, REQ_SET_CALL_VOLUME, data, sizeof(data));
654 if (ret != RIL_CLIENT_ERR_SUCCESS) {
655 RegisterRequestCompleteHandler(client, REQ_SET_CALL_VOLUME, NULL);
656 }
657
658 return ret;
659}
660
661
662/**
663 * Set external sound device path for noise reduction.
664 */
665extern "C"
Android-Andi40afadb2016-01-07 11:51:38 +0100666#ifdef RIL_CALL_AUDIO_PATH_EXTRAVOLUME
Andreas Schneider94275102015-08-24 19:55:42 +0200667int SetCallAudioPath(HRilClient client, AudioPath path, ExtraVolume mode)
668#else
669int SetCallAudioPath(HRilClient client, AudioPath path)
670#endif
671{
codeworkxf1587a32012-08-03 23:32:29 +0200672 RilClientPrv *client_prv;
673 int ret;
674 char data[6] = {0,};
675
676 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100677 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200678 return RIL_CLIENT_ERR_INVAL;
679 }
680
681 client_prv = (RilClientPrv *)(client->prv);
682
683 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100684 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200685 return RIL_CLIENT_ERR_CONNECT;
686 }
687
688 if (isValidAudioPath(path) == false) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100689 RLOGE("%s: Invalid audio path", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200690 return RIL_CLIENT_ERR_INVAL;
691 }
692
693 // Make raw data
694 data[0] = OEM_FUNC_SOUND;
695 data[1] = OEM_SND_SET_AUDIO_PATH;
696 data[2] = 0x00; // data length
697 data[3] = 0x06; // data length
698 data[4] = ConvertAudioPath(path); // audio path
Android-Andi40afadb2016-01-07 11:51:38 +0100699#ifdef RIL_CALL_AUDIO_PATH_EXTRAVOLUME
codeworkxf1587a32012-08-03 23:32:29 +0200700 data[5] = mode; // ExtraVolume
Andreas Schneider94275102015-08-24 19:55:42 +0200701#endif
codeworkxf1587a32012-08-03 23:32:29 +0200702
703 RegisterRequestCompleteHandler(client, REQ_SET_AUDIO_PATH, NULL);
704
705 ret = SendOemRequestHookRaw(client, REQ_SET_AUDIO_PATH, data, sizeof(data));
706 if (ret != RIL_CLIENT_ERR_SUCCESS) {
707 RegisterRequestCompleteHandler(client, REQ_SET_AUDIO_PATH, NULL);
708 }
709
710 return ret;
711}
712
713
714/**
715 * Set modem clock to master or slave.
716 */
717extern "C"
718int SetCallClockSync(HRilClient client, SoundClockCondition condition) {
719 RilClientPrv *client_prv;
720 int ret;
721 char data[5] = {0,};
722
723 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100724 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200725 return RIL_CLIENT_ERR_INVAL;
726 }
727
728 client_prv = (RilClientPrv *)(client->prv);
729
730 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100731 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200732 return RIL_CLIENT_ERR_CONNECT;
733 }
734
735 if (isValidSoundClockCondition(condition) == false) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100736 RLOGE("%s: Invalid sound clock condition", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200737 return RIL_CLIENT_ERR_INVAL;
738 }
739
740 // Make raw data
741 data[0] = OEM_FUNC_SOUND;
742 data[1] = OEM_SND_SET_CLOCK_CTRL;
743 data[2] = 0x00; // data length
744 data[3] = 0x05; // data length
745 data[4] = condition;
746
747 RegisterRequestCompleteHandler(client, REQ_SET_CALL_CLOCK_SYNC, NULL);
748
749 ret = SendOemRequestHookRaw(client, REQ_SET_CALL_CLOCK_SYNC, data, sizeof(data));
750 if (ret != RIL_CLIENT_ERR_SUCCESS) {
751 RegisterRequestCompleteHandler(client, REQ_SET_CALL_CLOCK_SYNC, NULL);
752 }
753
754 return ret;
755}
756
757/**
758 * Set modem VTCall clock to master or slave.
759 */
760extern "C"
761int SetVideoCallClockSync(HRilClient client, SoundClockCondition condition) {
762 RilClientPrv *client_prv;
763 int ret;
764 char data[5] = {0,};
765
766 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100767 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200768 return RIL_CLIENT_ERR_INVAL;
769 }
770
771 client_prv = (RilClientPrv *)(client->prv);
772
773 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100774 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200775 return RIL_CLIENT_ERR_CONNECT;
776 }
777
778 if (isValidSoundClockCondition(condition) == false) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100779 RLOGE("%s: Invalid sound clock condition", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200780 return RIL_CLIENT_ERR_INVAL;
781 }
782
783 // Make raw data
784 data[0] = OEM_FUNC_SOUND;
785 data[1] = OEM_SND_SET_VIDEO_CALL_CTRL;
786 data[2] = 0x00; // data length
787 data[3] = 0x05; // data length
788 data[4] = condition;
789
790 RegisterRequestCompleteHandler(client, REQ_SET_CALL_VT_CTRL, NULL);
791
792 ret = SendOemRequestHookRaw(client, REQ_SET_CALL_VT_CTRL, data, sizeof(data));
793 if (ret != RIL_CLIENT_ERR_SUCCESS) {
794 RegisterRequestCompleteHandler(client, REQ_SET_CALL_VT_CTRL, NULL);
795 }
796
797 return ret;
798}
799
800/**
801 * Set voice recording.
802 */
803extern "C"
804int SetCallRecord(HRilClient client, CallRecCondition condition) {
805 RilClientPrv *client_prv;
806 int ret;
807 char data[5] = {0,};
808
809 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100810 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200811 return RIL_CLIENT_ERR_INVAL;
812 }
813
814 client_prv = (RilClientPrv *)(client->prv);
815
816 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100817 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200818 return RIL_CLIENT_ERR_CONNECT;
819 }
820
821 if (isValidCallRecCondition(condition) == false) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100822 RLOGE("%s: Invalid sound clock condition", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200823 return RIL_CLIENT_ERR_INVAL;
824 }
825
826 // Make raw data
827 data[0] = OEM_FUNC_SOUND;
828 data[1] = OEM_SND_SET_VOICE_RECORDING_CTRL;
829 data[2] = 0x00; // data length
830 data[3] = 0x05; // data length
831 data[4] = condition;
832
833 RegisterRequestCompleteHandler(client, REQ_SET_CALL_RECORDING, NULL);
834
835 ret = SendOemRequestHookRaw(client, REQ_SET_CALL_RECORDING, data, sizeof(data));
836 if (ret != RIL_CLIENT_ERR_SUCCESS) {
837 RegisterRequestCompleteHandler(client, REQ_SET_CALL_RECORDING, NULL);
838 }
839
840 return ret;
841}
842
843/**
844 * Set mute or unmute.
845 */
846extern "C"
847int SetMute(HRilClient client, MuteCondition condition) {
848 RilClientPrv *client_prv;
849 int ret;
850 char data[5] = {0,};
851
852 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100853 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200854 return RIL_CLIENT_ERR_INVAL;
855 }
856
857 client_prv = (RilClientPrv *)(client->prv);
858
859 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100860 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200861 return RIL_CLIENT_ERR_CONNECT;
862 }
863
864 if (isValidMuteCondition(condition) == false) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100865 RLOGE("%s: Invalid sound clock condition", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200866 return RIL_CLIENT_ERR_INVAL;
867 }
868
869 // Make raw data
870 data[0] = OEM_FUNC_SOUND;
871 data[1] = OEM_SND_SET_MUTE;
872 data[2] = 0x00; // data length
873 data[3] = 0x05; // data length
874 data[4] = condition;
875
876 RegisterRequestCompleteHandler(client, REQ_SET_CALL_MUTE, NULL);
877
878 ret = SendOemRequestHookRaw(client, REQ_SET_CALL_MUTE, data, sizeof(data));
879 if (ret != RIL_CLIENT_ERR_SUCCESS) {
880 RegisterRequestCompleteHandler(client, REQ_SET_CALL_MUTE, NULL);
881 }
882
883 return ret;
884}
885
886/**
887 * Get mute state.
888 */
889extern "C"
890int GetMute(HRilClient client, RilOnComplete handler) {
891 RilClientPrv *client_prv;
892 int ret;
893 char data[4] = {0,};
894
895 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100896 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200897 return RIL_CLIENT_ERR_INVAL;
898 }
899
900 client_prv = (RilClientPrv *)(client->prv);
901
902 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100903 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200904 return RIL_CLIENT_ERR_CONNECT;
905 }
906
907 client_prv->b_del_handler = 1;
908
909 // Make raw data
910 data[0] = OEM_FUNC_SOUND;
911 data[1] = OEM_SND_GET_MUTE;
912 data[2] = 0x00; // data length
913 data[3] = 0x04; // data length
914
915 RegisterRequestCompleteHandler(client, REQ_GET_CALL_MUTE, handler);
916
917 ret = SendOemRequestHookRaw(client, REQ_GET_CALL_MUTE, data, sizeof(data));
918 if (ret != RIL_CLIENT_ERR_SUCCESS) {
919 RegisterRequestCompleteHandler(client, REQ_GET_CALL_MUTE, NULL);
920 }
921
922 return ret;
923}
924
925extern "C"
926int SetTwoMicControl(HRilClient client, TwoMicSolDevice device, TwoMicSolReport report) {
927 RilClientPrv *client_prv;
928 int ret;
929 char data[6] = {0,};
930
Andreas Schneider928ddca2017-02-08 16:52:54 +0100931 RLOGV(" + %s", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200932
933 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100934 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200935 return RIL_CLIENT_ERR_INVAL;
936 }
937
938 client_prv = (RilClientPrv *)(client->prv);
939
940 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100941 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200942 return RIL_CLIENT_ERR_CONNECT;
943 }
944
945 if (isValidTwoMicCtrl(device, report) == false) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100946 RLOGE("%s: Invalid sound set two params", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200947 return RIL_CLIENT_ERR_INVAL;
948 }
949
950 // Make raw data
951 data[0] = OEM_FUNC_SOUND;
952 data[1] = OEM_SND_SET_TWO_MIC_CTL;
953 data[2] = 0x00; // data length
954 data[3] = 0x06; // data length
955 data[4] = device;
956 data[5] = report;
957
958 RegisterRequestCompleteHandler(client, REQ_SET_TWO_MIC_CTRL, NULL);
959
960 ret = SendOemRequestHookRaw(client, REQ_SET_TWO_MIC_CTRL, data, sizeof(data));
961 if (ret != RIL_CLIENT_ERR_SUCCESS) {
962 RegisterRequestCompleteHandler(client, REQ_SET_TWO_MIC_CTRL, NULL);
963 }
964
Andreas Schneider928ddca2017-02-08 16:52:54 +0100965 RLOGV(" - %s", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200966
967 return ret;
968}
969
970extern "C"
971int SetDhaSolution(HRilClient client, DhaSolMode mode, DhaSolSelect select, char *parameter) {
972 RilClientPrv *client_prv;
973 int ret;
974 char data[30] = {0,};
975 char tempPara[24]={0,};
976
977 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100978 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200979 return RIL_CLIENT_ERR_INVAL;
980 }
981
982 client_prv = (RilClientPrv *)(client->prv);
983
984 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100985 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200986 return RIL_CLIENT_ERR_CONNECT;
987 }
988
Andreas Schneider560e37a2017-02-06 18:19:39 +0100989 RLOGE("%s: DHA mode=%d, select=%d", __FUNCTION__,mode, select);
codeworkxf1587a32012-08-03 23:32:29 +0200990
991 // Make raw data
992 data[0] = OEM_FUNC_SOUND;
993 data[1] = OEM_SND_SET_DHA_CTL;
994 data[2] = 0x00; // data length
995 data[3] = 0x1E; // data length
996 data[4] = mode;
997 data[5] = select;
998
999 memcpy(tempPara, parameter, 24);
1000 for(int i=0; i<24; i++)
1001 data[6+i]= tempPara[i];
1002
1003 RegisterRequestCompleteHandler(client, REQ_SET_DHA_CTRL, NULL);
1004
1005 ret = SendOemRequestHookRaw(client, REQ_SET_DHA_CTRL, data, sizeof(data));
1006 if (ret != RIL_CLIENT_ERR_SUCCESS) {
1007 RegisterRequestCompleteHandler(client, REQ_SET_DHA_CTRL, NULL);
1008 }
1009
1010 return ret;
1011}
1012
1013/**
1014 * Set LoopbackTest mode, path.
1015 */
1016extern "C"
1017int SetLoopbackTest(HRilClient client, LoopbackMode mode, AudioPath path) {
1018 RilClientPrv *client_prv;
1019 int ret;
1020 char data[6] = {0,};
1021
1022 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001023 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +02001024 return RIL_CLIENT_ERR_INVAL;
1025 }
1026
1027 client_prv = (RilClientPrv *)(client->prv);
1028
1029 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001030 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +02001031 return RIL_CLIENT_ERR_CONNECT;
1032 }
1033
1034 // Make raw data
1035 data[0] = OEM_FUNC_SOUND;
1036 data[1] = OEM_SND_SET_LOOPBACK_CTRL;
1037 data[2] = 0x00; // data length
1038 data[3] = 0x06; // data length
1039 data[4] = mode; // Loopback Mode
1040 data[5] = ConvertAudioPath(path); // Loopback path
1041
1042 RegisterRequestCompleteHandler(client, REQ_SET_LOOPBACK, NULL);
1043
1044 ret = SendOemRequestHookRaw(client, REQ_SET_LOOPBACK, data, sizeof(data));
1045 if (ret != RIL_CLIENT_ERR_SUCCESS) {
1046 RegisterRequestCompleteHandler(client, REQ_SET_LOOPBACK, NULL);
1047 }
1048
1049 return ret;
1050}
1051
1052
1053/**
1054 * @fn int InvokeOemRequestHookRaw(HRilClient client, char *data, size_t len)
1055 *
1056 * @params client: Client handle.
1057 * data: Request data.
1058 * len: Request data length.
1059 *
1060 * @return 0 for success or error code. On receiving RIL_CLIENT_ERR_AGAIN,
1061 * caller should retry.
1062 */
1063extern "C"
1064int InvokeOemRequestHookRaw(HRilClient client, char *data, size_t len) {
1065 RilClientPrv *client_prv;
1066
1067 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001068 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +02001069 return RIL_CLIENT_ERR_INVAL;
1070 }
1071
1072 client_prv = (RilClientPrv *)(client->prv);
1073
1074 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001075 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +02001076 return RIL_CLIENT_ERR_CONNECT;
1077 }
1078
1079 return SendOemRequestHookRaw(client, REQ_OEM_HOOK_RAW, data, len);
1080}
1081
1082
1083static int SendOemRequestHookRaw(HRilClient client, int req_id, char *data, size_t len) {
1084 int token = 0;
1085 int ret = 0;
1086 uint32_t header = 0;
1087 android::Parcel p;
1088 RilClientPrv *client_prv;
codeworkxf1587a32012-08-03 23:32:29 +02001089
Basil Gello72aac792017-07-13 19:29:21 +03001090 unsigned int check_req_id = req_id;
1091
codeworkxf1587a32012-08-03 23:32:29 +02001092 client_prv = (RilClientPrv *)(client->prv);
1093
1094 // Allocate a token.
1095 token = AllocateToken(&(client_prv->token_pool));
1096 if (token == 0) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001097 RLOGE("%s: No token.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +02001098 return RIL_CLIENT_ERR_AGAIN;
1099 }
1100
1101 // Record token for the request sent.
1102 if (RecordReqHistory(client_prv, token, req_id) != RIL_CLIENT_ERR_SUCCESS) {
1103 goto error;
1104 }
1105
1106 // Make OEM request data.
1107 p.writeInt32(RIL_REQUEST_OEM_HOOK_RAW);
1108 p.writeInt32(token);
1109 p.writeInt32(len);
1110 p.write((void *)data, len);
1111
1112 // DO TX: header(size).
1113 header = htonl(p.dataSize());
1114
Andreas Schneider928ddca2017-02-08 16:52:54 +01001115 RLOGV("%s(): token = %d\n", __FUNCTION__, token);
codeworkxf1587a32012-08-03 23:32:29 +02001116
1117 ret = blockingWrite(client_prv->sock, (void *)&header, sizeof(header));
1118 if (ret < 0) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001119 RLOGE("%s: send request header failed. (%d)", __FUNCTION__, ret);
codeworkxf1587a32012-08-03 23:32:29 +02001120 goto error;
1121 }
1122
1123 // Do TX: response data.
1124 ret = blockingWrite(client_prv->sock, p.data(), p.dataSize());
1125 if (ret < 0) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001126 RLOGE("%s: send request data failed. (%d)", __FUNCTION__, ret);
codeworkxf1587a32012-08-03 23:32:29 +02001127 goto error;
1128 }
1129
Basil Gello72aac792017-07-13 19:29:21 +03001130 // check if the handler for specified event is NULL and deregister token
1131 // to prevent token pool overflow
1132 if(!FindReqHandler(client_prv, token, &check_req_id)) {
1133 FreeToken(&(client_prv->token_pool), token);
1134 ClearReqHistory(client_prv, token);
1135 }
1136
codeworkxf1587a32012-08-03 23:32:29 +02001137 return RIL_CLIENT_ERR_SUCCESS;
1138
1139error:
1140 FreeToken(&(client_prv->token_pool), token);
1141 ClearReqHistory(client_prv, token);
1142
Basil Gello2a400242017-07-18 22:00:01 +03001143 if (ret == -EPIPE || ret == -EBADFD) {
1144 close(client_prv->sock);
1145 client_prv->sock = -1;
1146 client_prv->b_connect = 0;
1147 }
1148
codeworkxf1587a32012-08-03 23:32:29 +02001149 return RIL_CLIENT_ERR_UNKNOWN;
1150}
1151
1152
1153static bool isValidSoundType(SoundType type) {
1154 return (type >= SOUND_TYPE_VOICE && type <= SOUND_TYPE_BTVOICE);
1155}
1156
1157
1158static bool isValidAudioPath(AudioPath path) {
Andreas Schneidere0058812017-02-14 17:24:02 +01001159 return (path >= SOUND_AUDIO_PATH_EARPIECE && path <= OEM_SND_AUDIO_PATH_BT_WB_NSEC_OFF);
codeworkxf1587a32012-08-03 23:32:29 +02001160}
1161
1162
1163static bool isValidSoundClockCondition(SoundClockCondition condition) {
1164 return (condition >= SOUND_CLOCK_STOP && condition <= SOUND_CLOCK_START);
1165}
1166
1167static bool isValidCallRecCondition(CallRecCondition condition) {
1168 return (condition >= CALL_REC_STOP && condition <= CALL_REC_START);
1169}
1170
1171static bool isValidMuteCondition(MuteCondition condition) {
1172 return (condition >= TX_UNMUTE && condition <= RXTX_MUTE);
1173}
1174
1175static bool isValidTwoMicCtrl(TwoMicSolDevice device, TwoMicSolReport report) {
1176 return (device >= AUDIENCE && device <= FORTEMEDIA && report >= TWO_MIC_SOLUTION_OFF && report <= TWO_MIC_SOLUTION_ON );
1177}
1178
1179
1180static char ConvertSoundType(SoundType type) {
1181 switch (type) {
1182 case SOUND_TYPE_VOICE:
1183 return OEM_SND_TYPE_VOICE;
1184 case SOUND_TYPE_SPEAKER:
1185 return OEM_SND_TYPE_SPEAKER;
1186 case SOUND_TYPE_HEADSET:
1187 return OEM_SND_TYPE_HEADSET;
1188 case SOUND_TYPE_BTVOICE:
1189 return OEM_SND_TYPE_BTVOICE;
1190 default:
1191 return OEM_SND_TYPE_VOICE;
1192 }
1193}
1194
1195
1196static char ConvertAudioPath(AudioPath path) {
1197 switch (path) {
Andreas Schneidere0058812017-02-14 17:24:02 +01001198 case SOUND_AUDIO_PATH_EARPIECE:
1199 return OEM_SND_AUDIO_PATH_EARPIECE;
codeworkxf1587a32012-08-03 23:32:29 +02001200 case SOUND_AUDIO_PATH_HEADSET:
1201 return OEM_SND_AUDIO_PATH_HEADSET;
1202 case SOUND_AUDIO_PATH_SPEAKER:
1203 return OEM_SND_AUDIO_PATH_SPEAKER;
1204 case SOUND_AUDIO_PATH_BLUETOOTH:
1205 return OEM_SND_AUDIO_PATH_BLUETOOTH;
1206 case SOUND_AUDIO_PATH_STEREO_BT:
1207 return OEM_SND_AUDIO_PATH_STEREO_BLUETOOTH;
1208 case SOUND_AUDIO_PATH_HEADPHONE:
1209 return OEM_SND_AUDIO_PATH_HEADPHONE;
1210 case SOUND_AUDIO_PATH_BLUETOOTH_NO_NR:
1211 return OEM_SND_AUDIO_PATH_BT_NSEC_OFF;
1212 case SOUND_AUDIO_PATH_MIC1:
1213 return OEM_SND_AUDIO_PATH_MIC1;
1214 case SOUND_AUDIO_PATH_MIC2:
1215 return OEM_SND_AUDIO_PATH_MIC2;
1216 case SOUND_AUDIO_PATH_BLUETOOTH_WB:
1217 return OEM_SND_AUDIO_PATH_BT_WB;
1218 case SOUND_AUDIO_PATH_BLUETOOTH_WB_NO_NR:
1219 return OEM_SND_AUDIO_PATH_BT_WB_NSEC_OFF;
1220
1221 default:
Andreas Schneidere0058812017-02-14 17:24:02 +01001222 return OEM_SND_AUDIO_PATH_EARPIECE;
codeworkxf1587a32012-08-03 23:32:29 +02001223 }
1224}
1225
1226
1227static void * RxReaderFunc(void *param) {
1228 RilClientPrv *client_prv = (RilClientPrv *)param;
1229 int maxfd = 0;
codeworkxf1587a32012-08-03 23:32:29 +02001230 void *p_record = NULL;
1231 size_t recordlen = 0;
1232 int ret = 0;
1233 int n;
1234
1235 if (client_prv == NULL)
1236 return NULL;
1237
1238 maxfd = max(client_prv->sock, client_prv->pipefd[0]) + 1;
1239
1240 printf("[*] %s() b_connect=%d, maxfd=%d\n", __FUNCTION__, client_prv->b_connect, maxfd);
1241 while (client_prv->b_connect) {
1242 FD_ZERO(&(client_prv->sock_rfds));
1243
1244 FD_SET(client_prv->sock, &(client_prv->sock_rfds));
1245 FD_SET(client_prv->pipefd[0], &(client_prv->sock_rfds));
1246
Andreas Schneider928ddca2017-02-08 16:52:54 +01001247 RLOGV("[*] %s() b_connect=%d\n", __FUNCTION__, client_prv->b_connect);
codeworkxf1587a32012-08-03 23:32:29 +02001248 if (select(maxfd, &(client_prv->sock_rfds), NULL, NULL, NULL) > 0) {
1249 if (FD_ISSET(client_prv->sock, &(client_prv->sock_rfds))) {
1250 // Read incoming data
1251 for (;;) {
1252 // loop until EAGAIN/EINTR, end of stream, or other error
1253 ret = record_stream_get_next(client_prv->p_rs, &p_record, &recordlen);
1254 if (ret == 0 && p_record == NULL) { // end-of-stream
1255 break;
1256 }
1257 else if (ret < 0) {
1258 break;
1259 }
1260 else if (ret == 0) { // && p_record != NULL
1261 n = processRxBuffer(client_prv, p_record, recordlen);
1262 if (n != RIL_CLIENT_ERR_SUCCESS) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001263 RLOGE("%s: processRXBuffer returns %d", __FUNCTION__, n);
codeworkxf1587a32012-08-03 23:32:29 +02001264 }
1265 }
1266 else {
1267 printf("[*] %s()\n", __FUNCTION__);
1268 }
1269 }
1270
1271 if (ret == 0 || !(errno == EAGAIN || errno == EINTR)) {
1272 // fatal error or end-of-stream
1273 if (client_prv->sock > 0) {
1274 close(client_prv->sock);
1275 client_prv->sock = -1;
1276 client_prv->b_connect = 0;
1277 }
1278
1279 if (client_prv->p_rs)
1280 record_stream_free(client_prv->p_rs);
1281
1282 // EOS
1283 if (client_prv->err_cb) {
1284 client_prv->err_cb(client_prv->err_cb_data, RIL_CLIENT_ERR_CONNECT);
1285 return NULL;
1286 }
1287
1288 break;
1289 }
1290 }
1291 if (FD_ISSET(client_prv->pipefd[0], &(client_prv->sock_rfds))) {
1292 char end_cmd[10];
1293
Andreas Schneider928ddca2017-02-08 16:52:54 +01001294 RLOGV("%s(): close\n", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +02001295
1296 if (read(client_prv->pipefd[0], end_cmd, sizeof(end_cmd)) > 0) {
1297 close(client_prv->sock);
1298 close(client_prv->pipefd[0]);
1299 close(client_prv->pipefd[1]);
1300
1301 client_prv->sock = -1;
1302 client_prv->b_connect = 0;
1303 }
1304 }
Basil Gello2a400242017-07-18 22:00:01 +03001305 } else {
1306 RLOGE("%s: select() returned %d\n", __FUNCTION__, -errno);
1307
1308 if (client_prv->sock > 0) {
1309 close(client_prv->sock);
1310 client_prv->sock = -1;
1311 client_prv->b_connect = 0;
1312 }
1313
1314 if (client_prv->p_rs)
1315 record_stream_free(client_prv->p_rs);
1316
1317 // EOS
1318 if (client_prv->err_cb) {
1319 client_prv->err_cb(client_prv->err_cb_data, RIL_CLIENT_ERR_CONNECT);
1320 return NULL;
1321 }
codeworkxf1587a32012-08-03 23:32:29 +02001322 }
1323 }
1324
1325 return NULL;
1326}
1327
1328
1329static int processUnsolicited(RilClientPrv *prv, Parcel &p) {
1330 int32_t resp_id, len;
1331 status_t status;
1332 const void *data = NULL;
1333 RilOnUnsolicited unsol_func = NULL;
1334
1335 status = p.readInt32(&resp_id);
1336 if (status != NO_ERROR) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001337 RLOGE("%s: read resp_id failed.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +02001338 return RIL_CLIENT_ERR_IO;
1339 }
1340
1341 status = p.readInt32(&len);
1342 if (status != NO_ERROR) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001343 //RLOGE("%s: read length failed. assume zero length.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +02001344 len = 0;
1345 }
1346
Andreas Schneider560e37a2017-02-06 18:19:39 +01001347 RLOGD("%s(): resp_id (%d), len(%d)\n", __FUNCTION__, resp_id, len);
codeworkxf1587a32012-08-03 23:32:29 +02001348
1349 if (len)
1350 data = p.readInplace(len);
1351
1352 // Find unsolicited response handler.
1353 unsol_func = FindUnsolHandler(prv, (uint32_t)resp_id);
1354 if (unsol_func) {
1355 unsol_func(prv->parent, data, len);
1356 }
1357
1358 return RIL_CLIENT_ERR_SUCCESS;
1359}
1360
1361
1362static int processSolicited(RilClientPrv *prv, Parcel &p) {
1363 int32_t token, err, len;
1364 status_t status;
1365 const void *data = NULL;
1366 RilOnComplete req_func = NULL;
1367 int ret = RIL_CLIENT_ERR_SUCCESS;
1368 uint32_t req_id = 0;
1369
Andreas Schneider928ddca2017-02-08 16:52:54 +01001370 RLOGV("%s()", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +02001371
1372 status = p.readInt32(&token);
1373 if (status != NO_ERROR) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001374 RLOGE("%s: Read token fail. Status %d\n", __FUNCTION__, status);
codeworkxf1587a32012-08-03 23:32:29 +02001375 return RIL_CLIENT_ERR_IO;
1376 }
1377
1378 if (IsValidToken(&(prv->token_pool), token) == 0) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001379 RLOGE("%s: Invalid Token", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +02001380 return RIL_CLIENT_ERR_INVAL; // Invalid token.
1381 }
1382
1383 status = p.readInt32(&err);
1384 if (status != NO_ERROR) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001385 RLOGE("%s: Read err fail. Status %d\n", __FUNCTION__, status);
codeworkxf1587a32012-08-03 23:32:29 +02001386 ret = RIL_CLIENT_ERR_IO;
1387 goto error;
1388 }
1389
1390 // Don't go further for error response.
1391 if (err != RIL_CLIENT_ERR_SUCCESS) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001392 RLOGE("%s: Error %d\n", __FUNCTION__, err);
codeworkxf1587a32012-08-03 23:32:29 +02001393 if (prv->err_cb)
1394 prv->err_cb(prv->err_cb_data, err);
1395 ret = RIL_CLIENT_ERR_SUCCESS;
1396 goto error;
1397 }
1398
1399 status = p.readInt32(&len);
1400 if (status != NO_ERROR) {
1401 /* no length field */
1402 len = 0;
1403 }
1404
1405 if (len)
1406 data = p.readInplace(len);
1407
1408 // Find request handler for the token.
1409 // First, FindReqHandler() searches request history with the token
1410 // and finds out a request ID. Then, it search request handler table
1411 // with the request ID.
1412 req_func = FindReqHandler(prv, token, &req_id);
1413 if (req_func)
1414 {
Andreas Schneider928ddca2017-02-08 16:52:54 +01001415 RLOGV("[*] Call handler");
codeworkxf1587a32012-08-03 23:32:29 +02001416 req_func(prv->parent, data, len);
1417
1418 if(prv->b_del_handler) {
1419 prv->b_del_handler = 0;
1420 RegisterRequestCompleteHandler(prv->parent, req_id, NULL);
1421 }
1422 } else {
Andreas Schneider928ddca2017-02-08 16:52:54 +01001423 RLOGV("%s: No handler for token %d\n", __FUNCTION__, token);
codeworkxf1587a32012-08-03 23:32:29 +02001424 }
1425
1426error:
1427 FreeToken(&(prv->token_pool), token);
1428 ClearReqHistory(prv, token);
1429 return ret;
1430}
1431
1432
1433static int processRxBuffer(RilClientPrv *prv, void *buffer, size_t buflen) {
1434 Parcel p;
1435 int32_t response_type;
1436 status_t status;
1437 int ret = RIL_CLIENT_ERR_SUCCESS;
1438
1439 acquire_wake_lock(PARTIAL_WAKE_LOCK, RIL_CLIENT_WAKE_LOCK);
1440
1441 p.setData((uint8_t *)buffer, buflen);
1442
1443 status = p.readInt32(&response_type);
Andreas Schneider928ddca2017-02-08 16:52:54 +01001444 RLOGV("%s: status %d response_type %d", __FUNCTION__, status, response_type);
codeworkxf1587a32012-08-03 23:32:29 +02001445
1446 if (status != NO_ERROR) {
1447 ret = RIL_CLIENT_ERR_IO;
1448 goto EXIT;
1449 }
1450
1451 // FOr unsolicited response.
1452 if (response_type == RESPONSE_UNSOLICITED) {
1453 ret = processUnsolicited(prv, p);
1454 }
1455 // For solicited response.
1456 else if (response_type == RESPONSE_SOLICITED) {
1457 ret = processSolicited(prv, p);
1458 if (ret != RIL_CLIENT_ERR_SUCCESS && prv->err_cb) {
1459 prv->err_cb(prv->err_cb_data, ret);
1460 }
1461 }
1462 else {
1463 ret = RIL_CLIENT_ERR_INVAL;
1464 }
1465
1466EXIT:
1467 release_wake_lock(RIL_CLIENT_WAKE_LOCK);
1468 return ret;
1469}
1470
1471
1472static uint32_t AllocateToken(uint32_t *token_pool) {
1473 int i;
1474
1475 // Token pool is full.
1476 if (*token_pool == 0xFFFFFFFF)
1477 return 0;
1478
1479 for (i = 0; i < 32; i++) {
1480 uint32_t new_token = 0x00000001 << i;
1481
1482 if ((*token_pool & new_token) == 0) {
1483 *token_pool |= new_token;
1484 return new_token;
1485 }
1486 }
1487
1488 return 0;
1489}
1490
1491
1492static void FreeToken(uint32_t *token_pool, uint32_t token) {
1493 *token_pool &= ~token;
1494}
1495
1496
1497static uint8_t IsValidToken(uint32_t *token_pool, uint32_t token) {
1498 if (token == 0)
1499 return 0;
1500
1501 if ((*token_pool & token) == token)
1502 return 1;
1503 else
1504 return 0;
1505}
1506
1507
1508static int RecordReqHistory(RilClientPrv *prv, int token, uint32_t id) {
1509 int i = 0;
1510
Andreas Schneider928ddca2017-02-08 16:52:54 +01001511 RLOGV("[*] %s(): token(%d), ID(%d)\n", __FUNCTION__, token, id);
codeworkxf1587a32012-08-03 23:32:29 +02001512 for (i = 0; i < TOKEN_POOL_SIZE; i++) {
1513 if (prv->history[i].token == 0) {
1514 prv->history[i].token = token;
1515 prv->history[i].id = id;
1516
Andreas Schneider928ddca2017-02-08 16:52:54 +01001517 RLOGV("[*] %s(): token(%d), ID(%d)\n", __FUNCTION__, token, id);
codeworkxf1587a32012-08-03 23:32:29 +02001518
1519 return RIL_CLIENT_ERR_SUCCESS;
1520 }
1521 }
1522
Andreas Schneider560e37a2017-02-06 18:19:39 +01001523 RLOGE("%s: No free record for token %d", __FUNCTION__, token);
codeworkxf1587a32012-08-03 23:32:29 +02001524
1525 return RIL_CLIENT_ERR_RESOURCE;
1526}
1527
1528static void ClearReqHistory(RilClientPrv *prv, int token) {
1529 int i = 0;
1530
Andreas Schneider928ddca2017-02-08 16:52:54 +01001531 RLOGV("[*] %s(): token(%d)\n", __FUNCTION__, token);
codeworkxf1587a32012-08-03 23:32:29 +02001532 for (i = 0; i < TOKEN_POOL_SIZE; i++) {
1533 if (prv->history[i].token == token) {
1534 memset(&(prv->history[i]), 0, sizeof(ReqHistory));
1535 break;
1536 }
1537 }
1538}
1539
1540
1541static RilOnUnsolicited FindUnsolHandler(RilClientPrv *prv, uint32_t id) {
1542 int i;
1543
1544 // Search unsolicited handler table.
1545 for (i = 0; i < REQ_POOL_SIZE; i++) {
1546 if (prv->unsol_handlers[i].id == id)
1547 return prv->unsol_handlers[i].handler;
1548 }
1549
1550 return (RilOnUnsolicited)NULL;
1551}
1552
1553
1554static RilOnComplete FindReqHandler(RilClientPrv *prv, int token, uint32_t *id) {
1555 int i = 0;
1556 int j = 0;
1557
Andreas Schneider928ddca2017-02-08 16:52:54 +01001558 RLOGV("[*] %s(): token(%d)\n", __FUNCTION__, token);
codeworkxf1587a32012-08-03 23:32:29 +02001559
1560 // Search request history.
1561 for (i = 0; i < TOKEN_POOL_SIZE; i++) {
1562 printf("[*] %s(): history_token(%d)\n", __FUNCTION__, prv->history[i].token);
1563 if (prv->history[i].token == token) {
1564 // Search request handler with request ID found.
1565 for (j = 0; j < REQ_POOL_SIZE; j++) {
1566 printf("[*] %s(): token(%d), req_id(%d), history_id(%d)\n", __FUNCTION__, token, prv->history[i].id, prv->history[i].id);
1567 if (prv->req_handlers[j].id == prv->history[i].id) {
1568 *id = prv->req_handlers[j].id;
1569 return prv->req_handlers[j].handler;
1570 }
1571 }
1572 }
1573 }
1574
1575 return NULL;
1576}
1577
codeworkxf1587a32012-08-03 23:32:29 +02001578static int blockingWrite(int fd, const void *buffer, size_t len) {
1579 size_t writeOffset = 0;
1580 const uint8_t *toWrite;
1581 ssize_t written = 0;
1582
1583 if (buffer == NULL)
1584 return -1;
1585
1586 toWrite = (const uint8_t *)buffer;
1587
1588 while (writeOffset < len) {
1589 do
1590 {
1591 written = write(fd, toWrite + writeOffset, len - writeOffset);
1592 } while (written < 0 && errno == EINTR);
1593
1594 if (written >= 0) {
1595 writeOffset += written;
1596 }
1597 else {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001598 RLOGE ("RIL Response: unexpected error on write errno:%d", errno);
codeworkxf1587a32012-08-03 23:32:29 +02001599 close(fd);
Basil Gello338942b2017-07-13 19:36:39 +03001600 return -errno;
codeworkxf1587a32012-08-03 23:32:29 +02001601 }
1602 }
1603
1604 return 0;
1605}
1606
1607} // namespace android
1608
1609// end of file
1610