blob: a0bf078446a4d5fc5c39dac31f6c6164e56268e8 [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"
codeworkxf1587a32012-08-03 23:32:29 +020039#define MULTI_CLIENT_SOCKET_NAME_2 "Multiclient2"
codeworkxf1587a32012-08-03 23:32:29 +020040
41#define MAX_COMMAND_BYTES (8 * 1024)
42#define REQ_POOL_SIZE 32
43#define TOKEN_POOL_SIZE 32
44
45// Constants for response types
46#define RESPONSE_SOLICITED 0
47#define RESPONSE_UNSOLICITED 1
48
49#define max(a, b) ((a) > (b) ? (a) : (b))
50
51#define REQ_OEM_HOOK_RAW RIL_REQUEST_OEM_HOOK_RAW
52#define REQ_SET_CALL_VOLUME 101
53#define REQ_SET_AUDIO_PATH 102
54#define REQ_SET_CALL_CLOCK_SYNC 103
55#define REQ_SET_CALL_RECORDING 104
56#define REQ_SET_CALL_MUTE 105
57#define REQ_GET_CALL_MUTE 106
58#define REQ_SET_CALL_VT_CTRL 107
59#define REQ_SET_TWO_MIC_CTRL 108
60#define REQ_SET_DHA_CTRL 109
61#define REQ_SET_LOOPBACK 110
62
63// OEM request function ID
64#define OEM_FUNC_SOUND 0x08
65
66// OEM request sub function ID
67#define OEM_SND_SET_VOLUME_CTRL 0x03
68#define OEM_SND_SET_AUDIO_PATH 0x05
69#define OEM_SND_GET_AUDIO_PATH 0x06
70#define OEM_SND_SET_VIDEO_CALL_CTRL 0x07
71#define OEM_SND_SET_LOOPBACK_CTRL 0x08
72#define OEM_SND_SET_VOICE_RECORDING_CTRL 0x09
73#define OEM_SND_SET_CLOCK_CTRL 0x0A
74#define OEM_SND_SET_MUTE 0x0B
75#define OEM_SND_GET_MUTE 0x0C
76#define OEM_SND_SET_TWO_MIC_CTL 0x0D
77#define OEM_SND_SET_DHA_CTL 0x0E
78
79#define OEM_SND_TYPE_VOICE 0x01 // Receiver(0x00) + Voice(0x01)
80#define OEM_SND_TYPE_SPEAKER 0x11 // SpeakerPhone(0x10) + Voice(0x01)
81#define OEM_SND_TYPE_HEADSET 0x31 // Headset(0x30) + Voice(0x01)
82#define OEM_SND_TYPE_BTVOICE 0x41 // BT(0x40) + Voice(0x01)
83
Christopher N. Hesse57eacca2016-03-08 15:50:23 +010084#ifdef SAMSUNG_NEXT_GEN_MODEM
Andreas Schneidere0058812017-02-14 17:24:02 +010085#define OEM_SND_AUDIO_PATH_EARPIECE 0x01
Andreas Schneider6b9cd5f2015-01-23 22:41:22 +010086#define OEM_SND_AUDIO_PATH_HEADSET 0x02
87#define OEM_SND_AUDIO_PATH_HFK 0x06
88#define OEM_SND_AUDIO_PATH_BLUETOOTH 0x04
89#define OEM_SND_AUDIO_PATH_STEREO_BLUETOOTH 0x05
90#define OEM_SND_AUDIO_PATH_SPEAKER 0x07
91#define OEM_SND_AUDIO_PATH_HEADPHONE 0x08
92#define OEM_SND_AUDIO_PATH_BT_NSEC_OFF 0x09
93#define OEM_SND_AUDIO_PATH_MIC1 0x0A
94#define OEM_SND_AUDIO_PATH_MIC2 0x0B
95#define OEM_SND_AUDIO_PATH_BT_WB 0x0C
96#define OEM_SND_AUDIO_PATH_BT_WB_NSEC_OFF 0x0D
97#else
Andreas Schneidere0058812017-02-14 17:24:02 +010098#define OEM_SND_AUDIO_PATH_EARPIECE 0x01
codeworkxf1587a32012-08-03 23:32:29 +020099#define OEM_SND_AUDIO_PATH_HEADSET 0x02
100#define OEM_SND_AUDIO_PATH_HFK 0x03
101#define OEM_SND_AUDIO_PATH_BLUETOOTH 0x04
102#define OEM_SND_AUDIO_PATH_STEREO_BLUETOOTH 0x05
103#define OEM_SND_AUDIO_PATH_SPEAKER 0x06
104#define OEM_SND_AUDIO_PATH_HEADPHONE 0x07
105#define OEM_SND_AUDIO_PATH_BT_NSEC_OFF 0x08
106#define OEM_SND_AUDIO_PATH_MIC1 0x09
107#define OEM_SND_AUDIO_PATH_MIC2 0x0A
108#define OEM_SND_AUDIO_PATH_BT_WB 0x0B
109#define OEM_SND_AUDIO_PATH_BT_WB_NSEC_OFF 0x0C
Andreas Schneider6b9cd5f2015-01-23 22:41:22 +0100110#endif
codeworkxf1587a32012-08-03 23:32:29 +0200111
112//---------------------------------------------------------------------------
113// Type definitions
114//---------------------------------------------------------------------------
115typedef struct _ReqHistory {
116 int token; // token used for request
117 uint32_t id; // request ID
118} ReqHistory;
119
120typedef struct _ReqRespHandler {
121 uint32_t id; // request ID
122 RilOnComplete handler; // handler function
123} ReqRespHandler;
124
125typedef struct _UnsolHandler {
126 uint32_t id; // unsolicited response ID
127 RilOnUnsolicited handler; // handler function
128} UnsolHandler;
129
130typedef struct _RilClientPrv {
131 HRilClient parent;
132 uint8_t b_connect; // connected to server?
133 int sock; // socket
134 int pipefd[2];
135 fd_set sock_rfds; // for read with select()
136 RecordStream *p_rs;
137 uint32_t token_pool; // each bit in token_pool used for token.
138 // so, pool size is 32.
139 pthread_t tid_reader; // socket reader thread id
140 ReqHistory history[TOKEN_POOL_SIZE]; // request history
141 ReqRespHandler req_handlers[REQ_POOL_SIZE]; // request response handler list
142 UnsolHandler unsol_handlers[REQ_POOL_SIZE]; // unsolicited response handler list
143 RilOnError err_cb; // error callback
144 void *err_cb_data; // error callback data
145 uint8_t b_del_handler;
146} RilClientPrv;
147
148
149//---------------------------------------------------------------------------
150// Local static function prototypes
151//---------------------------------------------------------------------------
152static void * RxReaderFunc(void *param);
153static int processRxBuffer(RilClientPrv *prv, void *buffer, size_t buflen);
154static uint32_t AllocateToken(uint32_t *token_pool);
155static void FreeToken(uint32_t *token_pool, uint32_t token);
156static uint8_t IsValidToken(uint32_t *token_pool, uint32_t token);
157static void DeallocateToken(uint32_t *token_pool, uint32_t token);
158static 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;
1089 int maxfd = -1;
1090
Basil Gello72aac792017-07-13 19:29:21 +03001091 unsigned int check_req_id = req_id;
1092
codeworkxf1587a32012-08-03 23:32:29 +02001093 client_prv = (RilClientPrv *)(client->prv);
1094
1095 // Allocate a token.
1096 token = AllocateToken(&(client_prv->token_pool));
1097 if (token == 0) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001098 RLOGE("%s: No token.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +02001099 return RIL_CLIENT_ERR_AGAIN;
1100 }
1101
1102 // Record token for the request sent.
1103 if (RecordReqHistory(client_prv, token, req_id) != RIL_CLIENT_ERR_SUCCESS) {
1104 goto error;
1105 }
1106
1107 // Make OEM request data.
1108 p.writeInt32(RIL_REQUEST_OEM_HOOK_RAW);
1109 p.writeInt32(token);
1110 p.writeInt32(len);
1111 p.write((void *)data, len);
1112
1113 // DO TX: header(size).
1114 header = htonl(p.dataSize());
1115
Andreas Schneider928ddca2017-02-08 16:52:54 +01001116 RLOGV("%s(): token = %d\n", __FUNCTION__, token);
codeworkxf1587a32012-08-03 23:32:29 +02001117
1118 ret = blockingWrite(client_prv->sock, (void *)&header, sizeof(header));
1119 if (ret < 0) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001120 RLOGE("%s: send request header failed. (%d)", __FUNCTION__, ret);
codeworkxf1587a32012-08-03 23:32:29 +02001121 goto error;
1122 }
1123
1124 // Do TX: response data.
1125 ret = blockingWrite(client_prv->sock, p.data(), p.dataSize());
1126 if (ret < 0) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001127 RLOGE("%s: send request data failed. (%d)", __FUNCTION__, ret);
codeworkxf1587a32012-08-03 23:32:29 +02001128 goto error;
1129 }
1130
Basil Gello72aac792017-07-13 19:29:21 +03001131 // check if the handler for specified event is NULL and deregister token
1132 // to prevent token pool overflow
1133 if(!FindReqHandler(client_prv, token, &check_req_id)) {
1134 FreeToken(&(client_prv->token_pool), token);
1135 ClearReqHistory(client_prv, token);
1136 }
1137
codeworkxf1587a32012-08-03 23:32:29 +02001138 return RIL_CLIENT_ERR_SUCCESS;
1139
1140error:
1141 FreeToken(&(client_prv->token_pool), token);
1142 ClearReqHistory(client_prv, token);
1143
1144 return RIL_CLIENT_ERR_UNKNOWN;
1145}
1146
1147
1148static bool isValidSoundType(SoundType type) {
1149 return (type >= SOUND_TYPE_VOICE && type <= SOUND_TYPE_BTVOICE);
1150}
1151
1152
1153static bool isValidAudioPath(AudioPath path) {
Andreas Schneidere0058812017-02-14 17:24:02 +01001154 return (path >= SOUND_AUDIO_PATH_EARPIECE && path <= OEM_SND_AUDIO_PATH_BT_WB_NSEC_OFF);
codeworkxf1587a32012-08-03 23:32:29 +02001155}
1156
1157
1158static bool isValidSoundClockCondition(SoundClockCondition condition) {
1159 return (condition >= SOUND_CLOCK_STOP && condition <= SOUND_CLOCK_START);
1160}
1161
1162static bool isValidCallRecCondition(CallRecCondition condition) {
1163 return (condition >= CALL_REC_STOP && condition <= CALL_REC_START);
1164}
1165
1166static bool isValidMuteCondition(MuteCondition condition) {
1167 return (condition >= TX_UNMUTE && condition <= RXTX_MUTE);
1168}
1169
1170static bool isValidTwoMicCtrl(TwoMicSolDevice device, TwoMicSolReport report) {
1171 return (device >= AUDIENCE && device <= FORTEMEDIA && report >= TWO_MIC_SOLUTION_OFF && report <= TWO_MIC_SOLUTION_ON );
1172}
1173
1174
1175static char ConvertSoundType(SoundType type) {
1176 switch (type) {
1177 case SOUND_TYPE_VOICE:
1178 return OEM_SND_TYPE_VOICE;
1179 case SOUND_TYPE_SPEAKER:
1180 return OEM_SND_TYPE_SPEAKER;
1181 case SOUND_TYPE_HEADSET:
1182 return OEM_SND_TYPE_HEADSET;
1183 case SOUND_TYPE_BTVOICE:
1184 return OEM_SND_TYPE_BTVOICE;
1185 default:
1186 return OEM_SND_TYPE_VOICE;
1187 }
1188}
1189
1190
1191static char ConvertAudioPath(AudioPath path) {
1192 switch (path) {
Andreas Schneidere0058812017-02-14 17:24:02 +01001193 case SOUND_AUDIO_PATH_EARPIECE:
1194 return OEM_SND_AUDIO_PATH_EARPIECE;
codeworkxf1587a32012-08-03 23:32:29 +02001195 case SOUND_AUDIO_PATH_HEADSET:
1196 return OEM_SND_AUDIO_PATH_HEADSET;
1197 case SOUND_AUDIO_PATH_SPEAKER:
1198 return OEM_SND_AUDIO_PATH_SPEAKER;
1199 case SOUND_AUDIO_PATH_BLUETOOTH:
1200 return OEM_SND_AUDIO_PATH_BLUETOOTH;
1201 case SOUND_AUDIO_PATH_STEREO_BT:
1202 return OEM_SND_AUDIO_PATH_STEREO_BLUETOOTH;
1203 case SOUND_AUDIO_PATH_HEADPHONE:
1204 return OEM_SND_AUDIO_PATH_HEADPHONE;
1205 case SOUND_AUDIO_PATH_BLUETOOTH_NO_NR:
1206 return OEM_SND_AUDIO_PATH_BT_NSEC_OFF;
1207 case SOUND_AUDIO_PATH_MIC1:
1208 return OEM_SND_AUDIO_PATH_MIC1;
1209 case SOUND_AUDIO_PATH_MIC2:
1210 return OEM_SND_AUDIO_PATH_MIC2;
1211 case SOUND_AUDIO_PATH_BLUETOOTH_WB:
1212 return OEM_SND_AUDIO_PATH_BT_WB;
1213 case SOUND_AUDIO_PATH_BLUETOOTH_WB_NO_NR:
1214 return OEM_SND_AUDIO_PATH_BT_WB_NSEC_OFF;
1215
1216 default:
Andreas Schneidere0058812017-02-14 17:24:02 +01001217 return OEM_SND_AUDIO_PATH_EARPIECE;
codeworkxf1587a32012-08-03 23:32:29 +02001218 }
1219}
1220
1221
1222static void * RxReaderFunc(void *param) {
1223 RilClientPrv *client_prv = (RilClientPrv *)param;
1224 int maxfd = 0;
1225 int token = 0;
1226 void *p_record = NULL;
1227 size_t recordlen = 0;
1228 int ret = 0;
1229 int n;
1230
1231 if (client_prv == NULL)
1232 return NULL;
1233
1234 maxfd = max(client_prv->sock, client_prv->pipefd[0]) + 1;
1235
1236 printf("[*] %s() b_connect=%d, maxfd=%d\n", __FUNCTION__, client_prv->b_connect, maxfd);
1237 while (client_prv->b_connect) {
1238 FD_ZERO(&(client_prv->sock_rfds));
1239
1240 FD_SET(client_prv->sock, &(client_prv->sock_rfds));
1241 FD_SET(client_prv->pipefd[0], &(client_prv->sock_rfds));
1242
Andreas Schneider928ddca2017-02-08 16:52:54 +01001243 RLOGV("[*] %s() b_connect=%d\n", __FUNCTION__, client_prv->b_connect);
codeworkxf1587a32012-08-03 23:32:29 +02001244 if (select(maxfd, &(client_prv->sock_rfds), NULL, NULL, NULL) > 0) {
1245 if (FD_ISSET(client_prv->sock, &(client_prv->sock_rfds))) {
1246 // Read incoming data
1247 for (;;) {
1248 // loop until EAGAIN/EINTR, end of stream, or other error
1249 ret = record_stream_get_next(client_prv->p_rs, &p_record, &recordlen);
1250 if (ret == 0 && p_record == NULL) { // end-of-stream
1251 break;
1252 }
1253 else if (ret < 0) {
1254 break;
1255 }
1256 else if (ret == 0) { // && p_record != NULL
1257 n = processRxBuffer(client_prv, p_record, recordlen);
1258 if (n != RIL_CLIENT_ERR_SUCCESS) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001259 RLOGE("%s: processRXBuffer returns %d", __FUNCTION__, n);
codeworkxf1587a32012-08-03 23:32:29 +02001260 }
1261 }
1262 else {
1263 printf("[*] %s()\n", __FUNCTION__);
1264 }
1265 }
1266
1267 if (ret == 0 || !(errno == EAGAIN || errno == EINTR)) {
1268 // fatal error or end-of-stream
1269 if (client_prv->sock > 0) {
1270 close(client_prv->sock);
1271 client_prv->sock = -1;
1272 client_prv->b_connect = 0;
1273 }
1274
1275 if (client_prv->p_rs)
1276 record_stream_free(client_prv->p_rs);
1277
1278 // EOS
1279 if (client_prv->err_cb) {
1280 client_prv->err_cb(client_prv->err_cb_data, RIL_CLIENT_ERR_CONNECT);
1281 return NULL;
1282 }
1283
1284 break;
1285 }
1286 }
1287 if (FD_ISSET(client_prv->pipefd[0], &(client_prv->sock_rfds))) {
1288 char end_cmd[10];
1289
Andreas Schneider928ddca2017-02-08 16:52:54 +01001290 RLOGV("%s(): close\n", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +02001291
1292 if (read(client_prv->pipefd[0], end_cmd, sizeof(end_cmd)) > 0) {
1293 close(client_prv->sock);
1294 close(client_prv->pipefd[0]);
1295 close(client_prv->pipefd[1]);
1296
1297 client_prv->sock = -1;
1298 client_prv->b_connect = 0;
1299 }
1300 }
1301 }
1302 }
1303
1304 return NULL;
1305}
1306
1307
1308static int processUnsolicited(RilClientPrv *prv, Parcel &p) {
1309 int32_t resp_id, len;
1310 status_t status;
1311 const void *data = NULL;
1312 RilOnUnsolicited unsol_func = NULL;
1313
1314 status = p.readInt32(&resp_id);
1315 if (status != NO_ERROR) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001316 RLOGE("%s: read resp_id failed.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +02001317 return RIL_CLIENT_ERR_IO;
1318 }
1319
1320 status = p.readInt32(&len);
1321 if (status != NO_ERROR) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001322 //RLOGE("%s: read length failed. assume zero length.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +02001323 len = 0;
1324 }
1325
Andreas Schneider560e37a2017-02-06 18:19:39 +01001326 RLOGD("%s(): resp_id (%d), len(%d)\n", __FUNCTION__, resp_id, len);
codeworkxf1587a32012-08-03 23:32:29 +02001327
1328 if (len)
1329 data = p.readInplace(len);
1330
1331 // Find unsolicited response handler.
1332 unsol_func = FindUnsolHandler(prv, (uint32_t)resp_id);
1333 if (unsol_func) {
1334 unsol_func(prv->parent, data, len);
1335 }
1336
1337 return RIL_CLIENT_ERR_SUCCESS;
1338}
1339
1340
1341static int processSolicited(RilClientPrv *prv, Parcel &p) {
1342 int32_t token, err, len;
1343 status_t status;
1344 const void *data = NULL;
1345 RilOnComplete req_func = NULL;
1346 int ret = RIL_CLIENT_ERR_SUCCESS;
1347 uint32_t req_id = 0;
1348
Andreas Schneider928ddca2017-02-08 16:52:54 +01001349 RLOGV("%s()", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +02001350
1351 status = p.readInt32(&token);
1352 if (status != NO_ERROR) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001353 RLOGE("%s: Read token fail. Status %d\n", __FUNCTION__, status);
codeworkxf1587a32012-08-03 23:32:29 +02001354 return RIL_CLIENT_ERR_IO;
1355 }
1356
1357 if (IsValidToken(&(prv->token_pool), token) == 0) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001358 RLOGE("%s: Invalid Token", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +02001359 return RIL_CLIENT_ERR_INVAL; // Invalid token.
1360 }
1361
1362 status = p.readInt32(&err);
1363 if (status != NO_ERROR) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001364 RLOGE("%s: Read err fail. Status %d\n", __FUNCTION__, status);
codeworkxf1587a32012-08-03 23:32:29 +02001365 ret = RIL_CLIENT_ERR_IO;
1366 goto error;
1367 }
1368
1369 // Don't go further for error response.
1370 if (err != RIL_CLIENT_ERR_SUCCESS) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001371 RLOGE("%s: Error %d\n", __FUNCTION__, err);
codeworkxf1587a32012-08-03 23:32:29 +02001372 if (prv->err_cb)
1373 prv->err_cb(prv->err_cb_data, err);
1374 ret = RIL_CLIENT_ERR_SUCCESS;
1375 goto error;
1376 }
1377
1378 status = p.readInt32(&len);
1379 if (status != NO_ERROR) {
1380 /* no length field */
1381 len = 0;
1382 }
1383
1384 if (len)
1385 data = p.readInplace(len);
1386
1387 // Find request handler for the token.
1388 // First, FindReqHandler() searches request history with the token
1389 // and finds out a request ID. Then, it search request handler table
1390 // with the request ID.
1391 req_func = FindReqHandler(prv, token, &req_id);
1392 if (req_func)
1393 {
Andreas Schneider928ddca2017-02-08 16:52:54 +01001394 RLOGV("[*] Call handler");
codeworkxf1587a32012-08-03 23:32:29 +02001395 req_func(prv->parent, data, len);
1396
1397 if(prv->b_del_handler) {
1398 prv->b_del_handler = 0;
1399 RegisterRequestCompleteHandler(prv->parent, req_id, NULL);
1400 }
1401 } else {
Andreas Schneider928ddca2017-02-08 16:52:54 +01001402 RLOGV("%s: No handler for token %d\n", __FUNCTION__, token);
codeworkxf1587a32012-08-03 23:32:29 +02001403 }
1404
1405error:
1406 FreeToken(&(prv->token_pool), token);
1407 ClearReqHistory(prv, token);
1408 return ret;
1409}
1410
1411
1412static int processRxBuffer(RilClientPrv *prv, void *buffer, size_t buflen) {
1413 Parcel p;
1414 int32_t response_type;
1415 status_t status;
1416 int ret = RIL_CLIENT_ERR_SUCCESS;
1417
1418 acquire_wake_lock(PARTIAL_WAKE_LOCK, RIL_CLIENT_WAKE_LOCK);
1419
1420 p.setData((uint8_t *)buffer, buflen);
1421
1422 status = p.readInt32(&response_type);
Andreas Schneider928ddca2017-02-08 16:52:54 +01001423 RLOGV("%s: status %d response_type %d", __FUNCTION__, status, response_type);
codeworkxf1587a32012-08-03 23:32:29 +02001424
1425 if (status != NO_ERROR) {
1426 ret = RIL_CLIENT_ERR_IO;
1427 goto EXIT;
1428 }
1429
1430 // FOr unsolicited response.
1431 if (response_type == RESPONSE_UNSOLICITED) {
1432 ret = processUnsolicited(prv, p);
1433 }
1434 // For solicited response.
1435 else if (response_type == RESPONSE_SOLICITED) {
1436 ret = processSolicited(prv, p);
1437 if (ret != RIL_CLIENT_ERR_SUCCESS && prv->err_cb) {
1438 prv->err_cb(prv->err_cb_data, ret);
1439 }
1440 }
1441 else {
1442 ret = RIL_CLIENT_ERR_INVAL;
1443 }
1444
1445EXIT:
1446 release_wake_lock(RIL_CLIENT_WAKE_LOCK);
1447 return ret;
1448}
1449
1450
1451static uint32_t AllocateToken(uint32_t *token_pool) {
1452 int i;
1453
1454 // Token pool is full.
1455 if (*token_pool == 0xFFFFFFFF)
1456 return 0;
1457
1458 for (i = 0; i < 32; i++) {
1459 uint32_t new_token = 0x00000001 << i;
1460
1461 if ((*token_pool & new_token) == 0) {
1462 *token_pool |= new_token;
1463 return new_token;
1464 }
1465 }
1466
1467 return 0;
1468}
1469
1470
1471static void FreeToken(uint32_t *token_pool, uint32_t token) {
1472 *token_pool &= ~token;
1473}
1474
1475
1476static uint8_t IsValidToken(uint32_t *token_pool, uint32_t token) {
1477 if (token == 0)
1478 return 0;
1479
1480 if ((*token_pool & token) == token)
1481 return 1;
1482 else
1483 return 0;
1484}
1485
1486
1487static int RecordReqHistory(RilClientPrv *prv, int token, uint32_t id) {
1488 int i = 0;
1489
Andreas Schneider928ddca2017-02-08 16:52:54 +01001490 RLOGV("[*] %s(): token(%d), ID(%d)\n", __FUNCTION__, token, id);
codeworkxf1587a32012-08-03 23:32:29 +02001491 for (i = 0; i < TOKEN_POOL_SIZE; i++) {
1492 if (prv->history[i].token == 0) {
1493 prv->history[i].token = token;
1494 prv->history[i].id = id;
1495
Andreas Schneider928ddca2017-02-08 16:52:54 +01001496 RLOGV("[*] %s(): token(%d), ID(%d)\n", __FUNCTION__, token, id);
codeworkxf1587a32012-08-03 23:32:29 +02001497
1498 return RIL_CLIENT_ERR_SUCCESS;
1499 }
1500 }
1501
Andreas Schneider560e37a2017-02-06 18:19:39 +01001502 RLOGE("%s: No free record for token %d", __FUNCTION__, token);
codeworkxf1587a32012-08-03 23:32:29 +02001503
1504 return RIL_CLIENT_ERR_RESOURCE;
1505}
1506
1507static void ClearReqHistory(RilClientPrv *prv, int token) {
1508 int i = 0;
1509
Andreas Schneider928ddca2017-02-08 16:52:54 +01001510 RLOGV("[*] %s(): token(%d)\n", __FUNCTION__, token);
codeworkxf1587a32012-08-03 23:32:29 +02001511 for (i = 0; i < TOKEN_POOL_SIZE; i++) {
1512 if (prv->history[i].token == token) {
1513 memset(&(prv->history[i]), 0, sizeof(ReqHistory));
1514 break;
1515 }
1516 }
1517}
1518
1519
1520static RilOnUnsolicited FindUnsolHandler(RilClientPrv *prv, uint32_t id) {
1521 int i;
1522
1523 // Search unsolicited handler table.
1524 for (i = 0; i < REQ_POOL_SIZE; i++) {
1525 if (prv->unsol_handlers[i].id == id)
1526 return prv->unsol_handlers[i].handler;
1527 }
1528
1529 return (RilOnUnsolicited)NULL;
1530}
1531
1532
1533static RilOnComplete FindReqHandler(RilClientPrv *prv, int token, uint32_t *id) {
1534 int i = 0;
1535 int j = 0;
1536
Andreas Schneider928ddca2017-02-08 16:52:54 +01001537 RLOGV("[*] %s(): token(%d)\n", __FUNCTION__, token);
codeworkxf1587a32012-08-03 23:32:29 +02001538
1539 // Search request history.
1540 for (i = 0; i < TOKEN_POOL_SIZE; i++) {
1541 printf("[*] %s(): history_token(%d)\n", __FUNCTION__, prv->history[i].token);
1542 if (prv->history[i].token == token) {
1543 // Search request handler with request ID found.
1544 for (j = 0; j < REQ_POOL_SIZE; j++) {
1545 printf("[*] %s(): token(%d), req_id(%d), history_id(%d)\n", __FUNCTION__, token, prv->history[i].id, prv->history[i].id);
1546 if (prv->req_handlers[j].id == prv->history[i].id) {
1547 *id = prv->req_handlers[j].id;
1548 return prv->req_handlers[j].handler;
1549 }
1550 }
1551 }
1552 }
1553
1554 return NULL;
1555}
1556
1557
1558static void DeallocateToken(uint32_t *token_pool, uint32_t token) {
1559 *token_pool &= !token;
1560}
1561
1562
1563static int blockingWrite(int fd, const void *buffer, size_t len) {
1564 size_t writeOffset = 0;
1565 const uint8_t *toWrite;
1566 ssize_t written = 0;
1567
1568 if (buffer == NULL)
1569 return -1;
1570
1571 toWrite = (const uint8_t *)buffer;
1572
1573 while (writeOffset < len) {
1574 do
1575 {
1576 written = write(fd, toWrite + writeOffset, len - writeOffset);
1577 } while (written < 0 && errno == EINTR);
1578
1579 if (written >= 0) {
1580 writeOffset += written;
1581 }
1582 else {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001583 RLOGE ("RIL Response: unexpected error on write errno:%d", errno);
codeworkxf1587a32012-08-03 23:32:29 +02001584 close(fd);
Basil Gello338942b2017-07-13 19:36:39 +03001585 return -errno;
codeworkxf1587a32012-08-03 23:32:29 +02001586 }
1587 }
1588
1589 return 0;
1590}
1591
1592} // namespace android
1593
1594// end of file
1595