blob: 4701884ac3a21a2bf84782fa7f345fac75dff01f [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);
158static void DeallocateToken(uint32_t *token_pool, uint32_t token);
159static int blockingWrite(int fd, const void *buffer, size_t len);
160static int RecordReqHistory(RilClientPrv *prv, int token, uint32_t id);
161static void ClearReqHistory(RilClientPrv *prv, int token);
162static RilOnComplete FindReqHandler(RilClientPrv *prv, int token, uint32_t *id);
163static RilOnUnsolicited FindUnsolHandler(RilClientPrv *prv, uint32_t id);
164static int SendOemRequestHookRaw(HRilClient client, int req_id, char *data, size_t len);
165static bool isValidSoundType(SoundType type);
166static bool isValidAudioPath(AudioPath path);
167static bool isValidSoundClockCondition(SoundClockCondition condition);
168static bool isValidCallRecCondition(CallRecCondition condition);
169static bool isValidMuteCondition(MuteCondition condition);
170static bool isValidTwoMicCtrl(TwoMicSolDevice device, TwoMicSolReport report);
171static char ConvertSoundType(SoundType type);
172static char ConvertAudioPath(AudioPath path);
173
174
175/**
176 * @fn int RegisterUnsolicitedHandler(HRilClient client, uint32_t id, RilOnUnsolicited handler)
177 *
178 * @params client: Client handle.
179 * id: Unsolicited response ID to which handler is registered.
180 * handler: Unsolicited handler. NULL for deregistration.
181 *
182 * @return 0 on success or error code.
183 */
184extern "C"
185int RegisterUnsolicitedHandler(HRilClient client, uint32_t id, RilOnUnsolicited handler) {
186 RilClientPrv *client_prv;
187 int match_slot = -1;
188 int first_empty_slot = -1;
189 int i;
190
191 if (client == NULL || client->prv == NULL)
192 return RIL_CLIENT_ERR_INVAL;
193
194 client_prv = (RilClientPrv *)(client->prv);
195
196 for (i = 0; i < REQ_POOL_SIZE; i++) {
197 // Check if there is matched handler.
198 if (id == client_prv->unsol_handlers[i].id) {
199 match_slot = i;
200 }
201 // Find first empty handler slot.
202 if (first_empty_slot == -1 && client_prv->unsol_handlers[i].id == 0) {
203 first_empty_slot = i;
204 }
205 }
206
207 if (handler == NULL) { // Unregister.
208 if (match_slot >= 0) {
209 memset(&(client_prv->unsol_handlers[match_slot]), 0, sizeof(UnsolHandler));
210 return RIL_CLIENT_ERR_SUCCESS;
211 }
212 else {
213 return RIL_CLIENT_ERR_SUCCESS;
214 }
215 }
216 else {// Register.
217 if (match_slot >= 0) {
218 client_prv->unsol_handlers[match_slot].handler = handler; // Just update.
219 }
220 else if (first_empty_slot >= 0) {
221 client_prv->unsol_handlers[first_empty_slot].id = id;
222 client_prv->unsol_handlers[first_empty_slot].handler = handler;
223 }
224 else {
225 return RIL_CLIENT_ERR_RESOURCE;
226 }
227 }
228
229 return RIL_CLIENT_ERR_SUCCESS;
230}
231
232
233/**
234 * @fn int RegisterRequestCompleteHandler(HRilClient client, uint32_t id, RilOnComplete handler)
235 *
236 * @params client: Client handle.
237 * id: Request ID to which handler is registered.
238 * handler: Request complete handler. NULL for deregistration.
239 *
240 * @return 0 on success or error code.
241 */
242extern "C"
243int RegisterRequestCompleteHandler(HRilClient client, uint32_t id, RilOnComplete handler) {
244 RilClientPrv *client_prv;
245 int match_slot = -1;
246 int first_empty_slot = -1;
247 int i;
248
249 if (client == NULL || client->prv == NULL)
250 return RIL_CLIENT_ERR_INVAL;
251
252 client_prv = (RilClientPrv *)(client->prv);
253
254 for (i = 0; i < REQ_POOL_SIZE; i++) {
255 // Check if there is matched handler.
256 if (id == client_prv->req_handlers[i].id) {
257 match_slot = i;
258 }
259 // Find first empty handler slot.
260 if (first_empty_slot == -1 && client_prv->req_handlers[i].id == 0) {
261 first_empty_slot = i;
262 }
263 }
264
265 if (handler == NULL) { // Unregister.
266 if (match_slot >= 0) {
267 memset(&(client_prv->req_handlers[match_slot]), 0, sizeof(ReqRespHandler));
268 return RIL_CLIENT_ERR_SUCCESS;
269 }
270 else {
271 return RIL_CLIENT_ERR_SUCCESS;
272 }
273 }
274 else { // Register.
275 if (match_slot >= 0) {
276 client_prv->req_handlers[match_slot].handler = handler; // Just update.
277 }
278 else if (first_empty_slot >= 0) {
279 client_prv->req_handlers[first_empty_slot].id = id;
280 client_prv->req_handlers[first_empty_slot].handler = handler;
281 }
282 else {
283 return RIL_CLIENT_ERR_RESOURCE;
284 }
285 }
286
287 return RIL_CLIENT_ERR_SUCCESS;
288}
289
290
291/**
292 * @fn int RegisterErrorCallback(HRilClient client, RilOnError cb, void *data)
293 *
294 * @params client: Client handle.
295 * cb: Error callback. NULL for unregistration.
296 * data: Callback data.
297 *
298 * @return 0 for success or error code.
299 */
300extern "C"
301int RegisterErrorCallback(HRilClient client, RilOnError cb, void *data) {
302 RilClientPrv *client_prv;
303
304 if (client == NULL || client->prv == NULL)
305 return RIL_CLIENT_ERR_INVAL;
306
307 client_prv = (RilClientPrv *)(client->prv);
308
309 client_prv->err_cb = cb;
310 client_prv->err_cb_data = data;
311
312 return RIL_CLIENT_ERR_SUCCESS;
313}
314
315
316/**
317 * @fn HRilClient OpenClient_RILD(void)
318 *
319 * @params None.
320 *
321 * @return Client handle, NULL on error.
322 */
323extern "C"
324HRilClient OpenClient_RILD(void) {
325 HRilClient client = (HRilClient)malloc(sizeof(struct RilClient));
326 if (client == NULL)
327 return NULL;
328
329 client->prv = (RilClientPrv *)malloc(sizeof(RilClientPrv));
330 if (client->prv == NULL) {
331 free(client);
332 return NULL;
333 }
334
335 memset(client->prv, 0, sizeof(RilClientPrv));
336
337 ((RilClientPrv *)(client->prv))->parent = client;
338 ((RilClientPrv *)(client->prv))->sock = -1;
339
340 return client;
341}
342
343
344/**
345 * @fn int Connect_RILD(void)
346 *
347 * @params client: Client handle.
348 *
349 * @return 0, or error code.
350 */
351extern "C"
352int Connect_RILD(HRilClient client) {
353 RilClientPrv *client_prv;
354
355 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100356 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200357 return RIL_CLIENT_ERR_INVAL;
358 }
359
360 client_prv = (RilClientPrv *)(client->prv);
361
362 // Open client socket and connect to server.
363 //client_prv->sock = socket_loopback_client(RILD_PORT, SOCK_STREAM);
364 client_prv->sock = socket_local_client(MULTI_CLIENT_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM );
365
366 if (client_prv->sock < 0) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100367 RLOGE("%s: Connecting failed. %s(%d)", __FUNCTION__, strerror(errno), errno);
codeworkxf1587a32012-08-03 23:32:29 +0200368 return RIL_CLIENT_ERR_CONNECT;
369 }
370
371 client_prv->b_connect = 1;
372
373 if (fcntl(client_prv->sock, F_SETFL, O_NONBLOCK) < 0) {
374 close(client_prv->sock);
375 return RIL_CLIENT_ERR_IO;
376 }
377
378 client_prv->p_rs = record_stream_new(client_prv->sock, MAX_COMMAND_BYTES);
379
380 if (pipe(client_prv->pipefd) < 0) {
381 close(client_prv->sock);
Andreas Schneider560e37a2017-02-06 18:19:39 +0100382 RLOGE("%s: Creating command pipe failed. %s(%d)", __FUNCTION__, strerror(errno), errno);
codeworkxf1587a32012-08-03 23:32:29 +0200383 return RIL_CLIENT_ERR_IO;
384 }
385
386 if (fcntl(client_prv->pipefd[0], F_SETFL, O_NONBLOCK) < 0) {
387 close(client_prv->sock);
388 close(client_prv->pipefd[0]);
389 close(client_prv->pipefd[1]);
390 return RIL_CLIENT_ERR_IO;
391 }
392
393 // Start socket read thread.
394 if (pthread_create(&(client_prv->tid_reader), NULL, RxReaderFunc, (void *)client_prv) != 0) {
395 close(client_prv->sock);
396 close(client_prv->pipefd[0]);
397 close(client_prv->pipefd[1]);
398
399 memset(client_prv, 0, sizeof(RilClientPrv));
400 client_prv->sock = -1;
Andreas Schneider560e37a2017-02-06 18:19:39 +0100401 RLOGE("%s: Can't create Reader thread. %s(%d)", __FUNCTION__, strerror(errno), errno);
codeworkxf1587a32012-08-03 23:32:29 +0200402 return RIL_CLIENT_ERR_CONNECT;
403 }
404
405 return RIL_CLIENT_ERR_SUCCESS;
406}
407
408/**
409 * @fn int Connect_QRILD(void)
410 *
411 * @params client: Client handle.
412 *
413 * @return 0, or error code.
414 */
415extern "C"
416int Connect_QRILD(HRilClient client) {
417 RilClientPrv *client_prv;
418
419 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100420 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200421 return RIL_CLIENT_ERR_INVAL;
422 }
423
424 client_prv = (RilClientPrv *)(client->prv);
425
426 // Open client socket and connect to server.
427 //client_prv->sock = socket_loopback_client(RILD_PORT, SOCK_STREAM);
428 client_prv->sock = socket_local_client(MULTI_CLIENT_Q_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM );
429
430 if (client_prv->sock < 0) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100431 RLOGE("%s: Connecting failed. %s(%d)", __FUNCTION__, strerror(errno), errno);
codeworkxf1587a32012-08-03 23:32:29 +0200432 return RIL_CLIENT_ERR_CONNECT;
433 }
434
435 client_prv->b_connect = 1;
436
437 if (fcntl(client_prv->sock, F_SETFL, O_NONBLOCK) < 0) {
438 close(client_prv->sock);
439 return RIL_CLIENT_ERR_IO;
440 }
441
442 client_prv->p_rs = record_stream_new(client_prv->sock, MAX_COMMAND_BYTES);
443
444 if (pipe(client_prv->pipefd) < 0) {
445 close(client_prv->sock);
Andreas Schneider560e37a2017-02-06 18:19:39 +0100446 RLOGE("%s: Creating command pipe failed. %s(%d)", __FUNCTION__, strerror(errno), errno);
codeworkxf1587a32012-08-03 23:32:29 +0200447 return RIL_CLIENT_ERR_IO;
448 }
449
450 if (fcntl(client_prv->pipefd[0], F_SETFL, O_NONBLOCK) < 0) {
451 close(client_prv->sock);
452 close(client_prv->pipefd[0]);
453 close(client_prv->pipefd[1]);
454 return RIL_CLIENT_ERR_IO;
455 }
456
457 // Start socket read thread.
458 if (pthread_create(&(client_prv->tid_reader), NULL, RxReaderFunc, (void *)client_prv) != 0) {
459 close(client_prv->sock);
460 close(client_prv->pipefd[0]);
461 close(client_prv->pipefd[1]);
462
463 memset(client_prv, 0, sizeof(RilClientPrv));
464 client_prv->sock = -1;
Andreas Schneider560e37a2017-02-06 18:19:39 +0100465 RLOGE("%s: Can't create Reader thread. %s(%d)", __FUNCTION__, strerror(errno), errno);
codeworkxf1587a32012-08-03 23:32:29 +0200466 return RIL_CLIENT_ERR_CONNECT;
467 }
468
469 return RIL_CLIENT_ERR_SUCCESS;
470}
471
codeworkxf1587a32012-08-03 23:32:29 +0200472/**
473 * @fn int Connect_RILD_Second(void)
474 *
475 * @params client: Client handle.
476 *
477 * @return 0, or error code.
478 */
479extern "C"
480int Connect_RILD_Second(HRilClient client) {
481 RilClientPrv *client_prv;
482
483 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100484 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200485 return RIL_CLIENT_ERR_INVAL;
486 }
487
488 client_prv = (RilClientPrv *)(client->prv);
489
490 // Open client socket and connect to server.
491 //client_prv->sock = socket_loopback_client(RILD_PORT, SOCK_STREAM);
492 client_prv->sock = socket_local_client(MULTI_CLIENT_SOCKET_NAME_2, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM );
493
494 if (client_prv->sock < 0) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100495 RLOGE("%s: Connecting failed. %s(%d)", __FUNCTION__, strerror(errno), errno);
codeworkxf1587a32012-08-03 23:32:29 +0200496 return RIL_CLIENT_ERR_CONNECT;
497 }
498
499 client_prv->b_connect = 1;
500
501 if (fcntl(client_prv->sock, F_SETFL, O_NONBLOCK) < 0) {
502 close(client_prv->sock);
503 return RIL_CLIENT_ERR_IO;
504 }
505
506 client_prv->p_rs = record_stream_new(client_prv->sock, MAX_COMMAND_BYTES);
507
508 if (pipe(client_prv->pipefd) < 0) {
509 close(client_prv->sock);
Andreas Schneider560e37a2017-02-06 18:19:39 +0100510 RLOGE("%s: Creating command pipe failed. %s(%d)", __FUNCTION__, strerror(errno), errno);
codeworkxf1587a32012-08-03 23:32:29 +0200511 return RIL_CLIENT_ERR_IO;
512 }
513
514 if (fcntl(client_prv->pipefd[0], F_SETFL, O_NONBLOCK) < 0) {
515 close(client_prv->sock);
516 close(client_prv->pipefd[0]);
517 close(client_prv->pipefd[1]);
518 return RIL_CLIENT_ERR_IO;
519 }
520
521 // Start socket read thread.
522 if (pthread_create(&(client_prv->tid_reader), NULL, RxReaderFunc, (void *)client_prv) != 0) {
523 close(client_prv->sock);
524 close(client_prv->pipefd[0]);
525 close(client_prv->pipefd[1]);
526
527 memset(client_prv, 0, sizeof(RilClientPrv));
528 client_prv->sock = -1;
Andreas Schneider560e37a2017-02-06 18:19:39 +0100529 RLOGE("%s: Can't create Reader thread. %s(%d)", __FUNCTION__, strerror(errno), errno);
codeworkxf1587a32012-08-03 23:32:29 +0200530 return RIL_CLIENT_ERR_CONNECT;
531 }
532
533 return RIL_CLIENT_ERR_SUCCESS;
534}
codeworkxf1587a32012-08-03 23:32:29 +0200535
536/**
537 * @fn int isConnected_RILD(HRilClient client)
538 *
539 * @params client: Client handle.
540 *
541 * @return 0, or 1.
542 */
543extern "C"
544int isConnected_RILD(HRilClient client) {
545 RilClientPrv *client_prv;
546
547 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100548 RLOGE("%s: invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200549 return RIL_CLIENT_ERR_INVAL;
550 }
551
552 client_prv = (RilClientPrv *)(client->prv);
553
554 return client_prv->b_connect == 1;
555}
556
557/**
558 * @fn int Disconnect_RILD(HRilClient client)
559 *
560 * @params client: Client handle.
561 *
562 * @return 0 on success, or error code.
563 */
564extern "C"
565int Disconnect_RILD(HRilClient client) {
566 RilClientPrv *client_prv;
567 int ret = 0;
568
569 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100570 RLOGE("%s: invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200571 return RIL_CLIENT_ERR_INVAL;
572 }
573
574 client_prv = (RilClientPrv *)(client->prv);
575
576 if (client_prv->sock == -1)
577 return RIL_CLIENT_ERR_SUCCESS;
578
579 printf("[*] %s(): sock=%d\n", __FUNCTION__, client_prv->sock);
580
581 if (client_prv->sock > 0) {
582 do {
583 ret = write(client_prv->pipefd[1], "close", strlen("close"));
584 } while (ret < 0 && errno == EINTR);
585 }
586
587 client_prv->b_connect = 0;
588
589 pthread_join(client_prv->tid_reader, NULL);
590
591 return RIL_CLIENT_ERR_SUCCESS;
592}
593
594
595/**
596 * @fn int CloseClient_RILD(HRilClient client)
597 *
598 * @params client: Client handle.
599 *
600 * @return 0 on success, or error code.
601 */
602extern "C"
603int CloseClient_RILD(HRilClient client) {
604 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100605 RLOGE("%s: invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200606 return RIL_CLIENT_ERR_INVAL;
607 }
608
609 Disconnect_RILD(client);
610
611 free(client->prv);
612 free(client);
613
614 return RIL_CLIENT_ERR_SUCCESS;
615}
616
617
618/**
619 * Set in-call volume.
620 */
621extern "C"
622int SetCallVolume(HRilClient client, SoundType type, int vol_level) {
623 RilClientPrv *client_prv;
624 int ret;
625 char data[6] = {0,};
626
627 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100628 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200629 return RIL_CLIENT_ERR_INVAL;
630 }
631
632 client_prv = (RilClientPrv *)(client->prv);
633
634 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100635 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200636 return RIL_CLIENT_ERR_CONNECT;
637 }
638
639 if (isValidSoundType(type) == false) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100640 RLOGE("%s: Invalid sound type", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200641 return RIL_CLIENT_ERR_INVAL;
642 }
643
644 // Make raw data
645 data[0] = OEM_FUNC_SOUND;
646 data[1] = OEM_SND_SET_VOLUME_CTRL;
647 data[2] = 0x00; // data length
648 data[3] = 0x06; // data length
649 data[4] = ConvertSoundType(type); // volume type
650 data[5] = vol_level; // volume level
651
652 RegisterRequestCompleteHandler(client, REQ_SET_CALL_VOLUME, NULL);
653
654 ret = SendOemRequestHookRaw(client, REQ_SET_CALL_VOLUME, data, sizeof(data));
655 if (ret != RIL_CLIENT_ERR_SUCCESS) {
656 RegisterRequestCompleteHandler(client, REQ_SET_CALL_VOLUME, NULL);
657 }
658
659 return ret;
660}
661
662
663/**
664 * Set external sound device path for noise reduction.
665 */
666extern "C"
Android-Andi40afadb2016-01-07 11:51:38 +0100667#ifdef RIL_CALL_AUDIO_PATH_EXTRAVOLUME
Andreas Schneider94275102015-08-24 19:55:42 +0200668int SetCallAudioPath(HRilClient client, AudioPath path, ExtraVolume mode)
669#else
670int SetCallAudioPath(HRilClient client, AudioPath path)
671#endif
672{
codeworkxf1587a32012-08-03 23:32:29 +0200673 RilClientPrv *client_prv;
674 int ret;
675 char data[6] = {0,};
676
677 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100678 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200679 return RIL_CLIENT_ERR_INVAL;
680 }
681
682 client_prv = (RilClientPrv *)(client->prv);
683
684 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100685 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200686 return RIL_CLIENT_ERR_CONNECT;
687 }
688
689 if (isValidAudioPath(path) == false) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100690 RLOGE("%s: Invalid audio path", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200691 return RIL_CLIENT_ERR_INVAL;
692 }
693
694 // Make raw data
695 data[0] = OEM_FUNC_SOUND;
696 data[1] = OEM_SND_SET_AUDIO_PATH;
697 data[2] = 0x00; // data length
698 data[3] = 0x06; // data length
699 data[4] = ConvertAudioPath(path); // audio path
Android-Andi40afadb2016-01-07 11:51:38 +0100700#ifdef RIL_CALL_AUDIO_PATH_EXTRAVOLUME
codeworkxf1587a32012-08-03 23:32:29 +0200701 data[5] = mode; // ExtraVolume
Andreas Schneider94275102015-08-24 19:55:42 +0200702#endif
codeworkxf1587a32012-08-03 23:32:29 +0200703
704 RegisterRequestCompleteHandler(client, REQ_SET_AUDIO_PATH, NULL);
705
706 ret = SendOemRequestHookRaw(client, REQ_SET_AUDIO_PATH, data, sizeof(data));
707 if (ret != RIL_CLIENT_ERR_SUCCESS) {
708 RegisterRequestCompleteHandler(client, REQ_SET_AUDIO_PATH, NULL);
709 }
710
711 return ret;
712}
713
714
715/**
716 * Set modem clock to master or slave.
717 */
718extern "C"
719int SetCallClockSync(HRilClient client, SoundClockCondition condition) {
720 RilClientPrv *client_prv;
721 int ret;
722 char data[5] = {0,};
723
724 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100725 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200726 return RIL_CLIENT_ERR_INVAL;
727 }
728
729 client_prv = (RilClientPrv *)(client->prv);
730
731 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100732 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200733 return RIL_CLIENT_ERR_CONNECT;
734 }
735
736 if (isValidSoundClockCondition(condition) == false) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100737 RLOGE("%s: Invalid sound clock condition", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200738 return RIL_CLIENT_ERR_INVAL;
739 }
740
741 // Make raw data
742 data[0] = OEM_FUNC_SOUND;
743 data[1] = OEM_SND_SET_CLOCK_CTRL;
744 data[2] = 0x00; // data length
745 data[3] = 0x05; // data length
746 data[4] = condition;
747
748 RegisterRequestCompleteHandler(client, REQ_SET_CALL_CLOCK_SYNC, NULL);
749
750 ret = SendOemRequestHookRaw(client, REQ_SET_CALL_CLOCK_SYNC, data, sizeof(data));
751 if (ret != RIL_CLIENT_ERR_SUCCESS) {
752 RegisterRequestCompleteHandler(client, REQ_SET_CALL_CLOCK_SYNC, NULL);
753 }
754
755 return ret;
756}
757
758/**
759 * Set modem VTCall clock to master or slave.
760 */
761extern "C"
762int SetVideoCallClockSync(HRilClient client, SoundClockCondition condition) {
763 RilClientPrv *client_prv;
764 int ret;
765 char data[5] = {0,};
766
767 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100768 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200769 return RIL_CLIENT_ERR_INVAL;
770 }
771
772 client_prv = (RilClientPrv *)(client->prv);
773
774 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100775 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200776 return RIL_CLIENT_ERR_CONNECT;
777 }
778
779 if (isValidSoundClockCondition(condition) == false) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100780 RLOGE("%s: Invalid sound clock condition", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200781 return RIL_CLIENT_ERR_INVAL;
782 }
783
784 // Make raw data
785 data[0] = OEM_FUNC_SOUND;
786 data[1] = OEM_SND_SET_VIDEO_CALL_CTRL;
787 data[2] = 0x00; // data length
788 data[3] = 0x05; // data length
789 data[4] = condition;
790
791 RegisterRequestCompleteHandler(client, REQ_SET_CALL_VT_CTRL, NULL);
792
793 ret = SendOemRequestHookRaw(client, REQ_SET_CALL_VT_CTRL, data, sizeof(data));
794 if (ret != RIL_CLIENT_ERR_SUCCESS) {
795 RegisterRequestCompleteHandler(client, REQ_SET_CALL_VT_CTRL, NULL);
796 }
797
798 return ret;
799}
800
801/**
802 * Set voice recording.
803 */
804extern "C"
805int SetCallRecord(HRilClient client, CallRecCondition condition) {
806 RilClientPrv *client_prv;
807 int ret;
808 char data[5] = {0,};
809
810 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100811 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200812 return RIL_CLIENT_ERR_INVAL;
813 }
814
815 client_prv = (RilClientPrv *)(client->prv);
816
817 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100818 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200819 return RIL_CLIENT_ERR_CONNECT;
820 }
821
822 if (isValidCallRecCondition(condition) == false) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100823 RLOGE("%s: Invalid sound clock condition", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200824 return RIL_CLIENT_ERR_INVAL;
825 }
826
827 // Make raw data
828 data[0] = OEM_FUNC_SOUND;
829 data[1] = OEM_SND_SET_VOICE_RECORDING_CTRL;
830 data[2] = 0x00; // data length
831 data[3] = 0x05; // data length
832 data[4] = condition;
833
834 RegisterRequestCompleteHandler(client, REQ_SET_CALL_RECORDING, NULL);
835
836 ret = SendOemRequestHookRaw(client, REQ_SET_CALL_RECORDING, data, sizeof(data));
837 if (ret != RIL_CLIENT_ERR_SUCCESS) {
838 RegisterRequestCompleteHandler(client, REQ_SET_CALL_RECORDING, NULL);
839 }
840
841 return ret;
842}
843
844/**
845 * Set mute or unmute.
846 */
847extern "C"
848int SetMute(HRilClient client, MuteCondition condition) {
849 RilClientPrv *client_prv;
850 int ret;
851 char data[5] = {0,};
852
853 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100854 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200855 return RIL_CLIENT_ERR_INVAL;
856 }
857
858 client_prv = (RilClientPrv *)(client->prv);
859
860 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100861 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200862 return RIL_CLIENT_ERR_CONNECT;
863 }
864
865 if (isValidMuteCondition(condition) == false) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100866 RLOGE("%s: Invalid sound clock condition", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200867 return RIL_CLIENT_ERR_INVAL;
868 }
869
870 // Make raw data
871 data[0] = OEM_FUNC_SOUND;
872 data[1] = OEM_SND_SET_MUTE;
873 data[2] = 0x00; // data length
874 data[3] = 0x05; // data length
875 data[4] = condition;
876
877 RegisterRequestCompleteHandler(client, REQ_SET_CALL_MUTE, NULL);
878
879 ret = SendOemRequestHookRaw(client, REQ_SET_CALL_MUTE, data, sizeof(data));
880 if (ret != RIL_CLIENT_ERR_SUCCESS) {
881 RegisterRequestCompleteHandler(client, REQ_SET_CALL_MUTE, NULL);
882 }
883
884 return ret;
885}
886
887/**
888 * Get mute state.
889 */
890extern "C"
891int GetMute(HRilClient client, RilOnComplete handler) {
892 RilClientPrv *client_prv;
893 int ret;
894 char data[4] = {0,};
895
896 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100897 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200898 return RIL_CLIENT_ERR_INVAL;
899 }
900
901 client_prv = (RilClientPrv *)(client->prv);
902
903 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100904 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200905 return RIL_CLIENT_ERR_CONNECT;
906 }
907
908 client_prv->b_del_handler = 1;
909
910 // Make raw data
911 data[0] = OEM_FUNC_SOUND;
912 data[1] = OEM_SND_GET_MUTE;
913 data[2] = 0x00; // data length
914 data[3] = 0x04; // data length
915
916 RegisterRequestCompleteHandler(client, REQ_GET_CALL_MUTE, handler);
917
918 ret = SendOemRequestHookRaw(client, REQ_GET_CALL_MUTE, data, sizeof(data));
919 if (ret != RIL_CLIENT_ERR_SUCCESS) {
920 RegisterRequestCompleteHandler(client, REQ_GET_CALL_MUTE, NULL);
921 }
922
923 return ret;
924}
925
926extern "C"
927int SetTwoMicControl(HRilClient client, TwoMicSolDevice device, TwoMicSolReport report) {
928 RilClientPrv *client_prv;
929 int ret;
930 char data[6] = {0,};
931
Andreas Schneider928ddca2017-02-08 16:52:54 +0100932 RLOGV(" + %s", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200933
934 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100935 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200936 return RIL_CLIENT_ERR_INVAL;
937 }
938
939 client_prv = (RilClientPrv *)(client->prv);
940
941 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100942 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200943 return RIL_CLIENT_ERR_CONNECT;
944 }
945
946 if (isValidTwoMicCtrl(device, report) == false) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100947 RLOGE("%s: Invalid sound set two params", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200948 return RIL_CLIENT_ERR_INVAL;
949 }
950
951 // Make raw data
952 data[0] = OEM_FUNC_SOUND;
953 data[1] = OEM_SND_SET_TWO_MIC_CTL;
954 data[2] = 0x00; // data length
955 data[3] = 0x06; // data length
956 data[4] = device;
957 data[5] = report;
958
959 RegisterRequestCompleteHandler(client, REQ_SET_TWO_MIC_CTRL, NULL);
960
961 ret = SendOemRequestHookRaw(client, REQ_SET_TWO_MIC_CTRL, data, sizeof(data));
962 if (ret != RIL_CLIENT_ERR_SUCCESS) {
963 RegisterRequestCompleteHandler(client, REQ_SET_TWO_MIC_CTRL, NULL);
964 }
965
Andreas Schneider928ddca2017-02-08 16:52:54 +0100966 RLOGV(" - %s", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200967
968 return ret;
969}
970
971extern "C"
972int SetDhaSolution(HRilClient client, DhaSolMode mode, DhaSolSelect select, char *parameter) {
973 RilClientPrv *client_prv;
974 int ret;
975 char data[30] = {0,};
976 char tempPara[24]={0,};
977
978 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100979 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +0200980 return RIL_CLIENT_ERR_INVAL;
981 }
982
983 client_prv = (RilClientPrv *)(client->prv);
984
985 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +0100986 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +0200987 return RIL_CLIENT_ERR_CONNECT;
988 }
989
Andreas Schneider560e37a2017-02-06 18:19:39 +0100990 RLOGE("%s: DHA mode=%d, select=%d", __FUNCTION__,mode, select);
codeworkxf1587a32012-08-03 23:32:29 +0200991
992 // Make raw data
993 data[0] = OEM_FUNC_SOUND;
994 data[1] = OEM_SND_SET_DHA_CTL;
995 data[2] = 0x00; // data length
996 data[3] = 0x1E; // data length
997 data[4] = mode;
998 data[5] = select;
999
1000 memcpy(tempPara, parameter, 24);
1001 for(int i=0; i<24; i++)
1002 data[6+i]= tempPara[i];
1003
1004 RegisterRequestCompleteHandler(client, REQ_SET_DHA_CTRL, NULL);
1005
1006 ret = SendOemRequestHookRaw(client, REQ_SET_DHA_CTRL, data, sizeof(data));
1007 if (ret != RIL_CLIENT_ERR_SUCCESS) {
1008 RegisterRequestCompleteHandler(client, REQ_SET_DHA_CTRL, NULL);
1009 }
1010
1011 return ret;
1012}
1013
1014/**
1015 * Set LoopbackTest mode, path.
1016 */
1017extern "C"
1018int SetLoopbackTest(HRilClient client, LoopbackMode mode, AudioPath path) {
1019 RilClientPrv *client_prv;
1020 int ret;
1021 char data[6] = {0,};
1022
1023 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001024 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +02001025 return RIL_CLIENT_ERR_INVAL;
1026 }
1027
1028 client_prv = (RilClientPrv *)(client->prv);
1029
1030 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001031 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +02001032 return RIL_CLIENT_ERR_CONNECT;
1033 }
1034
1035 // Make raw data
1036 data[0] = OEM_FUNC_SOUND;
1037 data[1] = OEM_SND_SET_LOOPBACK_CTRL;
1038 data[2] = 0x00; // data length
1039 data[3] = 0x06; // data length
1040 data[4] = mode; // Loopback Mode
1041 data[5] = ConvertAudioPath(path); // Loopback path
1042
1043 RegisterRequestCompleteHandler(client, REQ_SET_LOOPBACK, NULL);
1044
1045 ret = SendOemRequestHookRaw(client, REQ_SET_LOOPBACK, data, sizeof(data));
1046 if (ret != RIL_CLIENT_ERR_SUCCESS) {
1047 RegisterRequestCompleteHandler(client, REQ_SET_LOOPBACK, NULL);
1048 }
1049
1050 return ret;
1051}
1052
1053
1054/**
1055 * @fn int InvokeOemRequestHookRaw(HRilClient client, char *data, size_t len)
1056 *
1057 * @params client: Client handle.
1058 * data: Request data.
1059 * len: Request data length.
1060 *
1061 * @return 0 for success or error code. On receiving RIL_CLIENT_ERR_AGAIN,
1062 * caller should retry.
1063 */
1064extern "C"
1065int InvokeOemRequestHookRaw(HRilClient client, char *data, size_t len) {
1066 RilClientPrv *client_prv;
1067
1068 if (client == NULL || client->prv == NULL) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001069 RLOGE("%s: Invalid client %p", __FUNCTION__, client);
codeworkxf1587a32012-08-03 23:32:29 +02001070 return RIL_CLIENT_ERR_INVAL;
1071 }
1072
1073 client_prv = (RilClientPrv *)(client->prv);
1074
1075 if (client_prv->sock < 0 ) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001076 RLOGE("%s: Not connected.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +02001077 return RIL_CLIENT_ERR_CONNECT;
1078 }
1079
1080 return SendOemRequestHookRaw(client, REQ_OEM_HOOK_RAW, data, len);
1081}
1082
1083
1084static int SendOemRequestHookRaw(HRilClient client, int req_id, char *data, size_t len) {
1085 int token = 0;
1086 int ret = 0;
1087 uint32_t header = 0;
1088 android::Parcel p;
1089 RilClientPrv *client_prv;
1090 int maxfd = -1;
1091
Basil Gello72aac792017-07-13 19:29:21 +03001092 unsigned int check_req_id = req_id;
1093
codeworkxf1587a32012-08-03 23:32:29 +02001094 client_prv = (RilClientPrv *)(client->prv);
1095
1096 // Allocate a token.
1097 token = AllocateToken(&(client_prv->token_pool));
1098 if (token == 0) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001099 RLOGE("%s: No token.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +02001100 return RIL_CLIENT_ERR_AGAIN;
1101 }
1102
1103 // Record token for the request sent.
1104 if (RecordReqHistory(client_prv, token, req_id) != RIL_CLIENT_ERR_SUCCESS) {
1105 goto error;
1106 }
1107
1108 // Make OEM request data.
1109 p.writeInt32(RIL_REQUEST_OEM_HOOK_RAW);
1110 p.writeInt32(token);
1111 p.writeInt32(len);
1112 p.write((void *)data, len);
1113
1114 // DO TX: header(size).
1115 header = htonl(p.dataSize());
1116
Andreas Schneider928ddca2017-02-08 16:52:54 +01001117 RLOGV("%s(): token = %d\n", __FUNCTION__, token);
codeworkxf1587a32012-08-03 23:32:29 +02001118
1119 ret = blockingWrite(client_prv->sock, (void *)&header, sizeof(header));
1120 if (ret < 0) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001121 RLOGE("%s: send request header failed. (%d)", __FUNCTION__, ret);
codeworkxf1587a32012-08-03 23:32:29 +02001122 goto error;
1123 }
1124
1125 // Do TX: response data.
1126 ret = blockingWrite(client_prv->sock, p.data(), p.dataSize());
1127 if (ret < 0) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001128 RLOGE("%s: send request data failed. (%d)", __FUNCTION__, ret);
codeworkxf1587a32012-08-03 23:32:29 +02001129 goto error;
1130 }
1131
Basil Gello72aac792017-07-13 19:29:21 +03001132 // check if the handler for specified event is NULL and deregister token
1133 // to prevent token pool overflow
1134 if(!FindReqHandler(client_prv, token, &check_req_id)) {
1135 FreeToken(&(client_prv->token_pool), token);
1136 ClearReqHistory(client_prv, token);
1137 }
1138
codeworkxf1587a32012-08-03 23:32:29 +02001139 return RIL_CLIENT_ERR_SUCCESS;
1140
1141error:
1142 FreeToken(&(client_prv->token_pool), token);
1143 ClearReqHistory(client_prv, token);
1144
Basil Gello2a400242017-07-18 22:00:01 +03001145 if (ret == -EPIPE || ret == -EBADFD) {
1146 close(client_prv->sock);
1147 client_prv->sock = -1;
1148 client_prv->b_connect = 0;
1149 }
1150
codeworkxf1587a32012-08-03 23:32:29 +02001151 return RIL_CLIENT_ERR_UNKNOWN;
1152}
1153
1154
1155static bool isValidSoundType(SoundType type) {
1156 return (type >= SOUND_TYPE_VOICE && type <= SOUND_TYPE_BTVOICE);
1157}
1158
1159
1160static bool isValidAudioPath(AudioPath path) {
Andreas Schneidere0058812017-02-14 17:24:02 +01001161 return (path >= SOUND_AUDIO_PATH_EARPIECE && path <= OEM_SND_AUDIO_PATH_BT_WB_NSEC_OFF);
codeworkxf1587a32012-08-03 23:32:29 +02001162}
1163
1164
1165static bool isValidSoundClockCondition(SoundClockCondition condition) {
1166 return (condition >= SOUND_CLOCK_STOP && condition <= SOUND_CLOCK_START);
1167}
1168
1169static bool isValidCallRecCondition(CallRecCondition condition) {
1170 return (condition >= CALL_REC_STOP && condition <= CALL_REC_START);
1171}
1172
1173static bool isValidMuteCondition(MuteCondition condition) {
1174 return (condition >= TX_UNMUTE && condition <= RXTX_MUTE);
1175}
1176
1177static bool isValidTwoMicCtrl(TwoMicSolDevice device, TwoMicSolReport report) {
1178 return (device >= AUDIENCE && device <= FORTEMEDIA && report >= TWO_MIC_SOLUTION_OFF && report <= TWO_MIC_SOLUTION_ON );
1179}
1180
1181
1182static char ConvertSoundType(SoundType type) {
1183 switch (type) {
1184 case SOUND_TYPE_VOICE:
1185 return OEM_SND_TYPE_VOICE;
1186 case SOUND_TYPE_SPEAKER:
1187 return OEM_SND_TYPE_SPEAKER;
1188 case SOUND_TYPE_HEADSET:
1189 return OEM_SND_TYPE_HEADSET;
1190 case SOUND_TYPE_BTVOICE:
1191 return OEM_SND_TYPE_BTVOICE;
1192 default:
1193 return OEM_SND_TYPE_VOICE;
1194 }
1195}
1196
1197
1198static char ConvertAudioPath(AudioPath path) {
1199 switch (path) {
Andreas Schneidere0058812017-02-14 17:24:02 +01001200 case SOUND_AUDIO_PATH_EARPIECE:
1201 return OEM_SND_AUDIO_PATH_EARPIECE;
codeworkxf1587a32012-08-03 23:32:29 +02001202 case SOUND_AUDIO_PATH_HEADSET:
1203 return OEM_SND_AUDIO_PATH_HEADSET;
1204 case SOUND_AUDIO_PATH_SPEAKER:
1205 return OEM_SND_AUDIO_PATH_SPEAKER;
1206 case SOUND_AUDIO_PATH_BLUETOOTH:
1207 return OEM_SND_AUDIO_PATH_BLUETOOTH;
1208 case SOUND_AUDIO_PATH_STEREO_BT:
1209 return OEM_SND_AUDIO_PATH_STEREO_BLUETOOTH;
1210 case SOUND_AUDIO_PATH_HEADPHONE:
1211 return OEM_SND_AUDIO_PATH_HEADPHONE;
1212 case SOUND_AUDIO_PATH_BLUETOOTH_NO_NR:
1213 return OEM_SND_AUDIO_PATH_BT_NSEC_OFF;
1214 case SOUND_AUDIO_PATH_MIC1:
1215 return OEM_SND_AUDIO_PATH_MIC1;
1216 case SOUND_AUDIO_PATH_MIC2:
1217 return OEM_SND_AUDIO_PATH_MIC2;
1218 case SOUND_AUDIO_PATH_BLUETOOTH_WB:
1219 return OEM_SND_AUDIO_PATH_BT_WB;
1220 case SOUND_AUDIO_PATH_BLUETOOTH_WB_NO_NR:
1221 return OEM_SND_AUDIO_PATH_BT_WB_NSEC_OFF;
1222
1223 default:
Andreas Schneidere0058812017-02-14 17:24:02 +01001224 return OEM_SND_AUDIO_PATH_EARPIECE;
codeworkxf1587a32012-08-03 23:32:29 +02001225 }
1226}
1227
1228
1229static void * RxReaderFunc(void *param) {
1230 RilClientPrv *client_prv = (RilClientPrv *)param;
1231 int maxfd = 0;
1232 int token = 0;
1233 void *p_record = NULL;
1234 size_t recordlen = 0;
1235 int ret = 0;
1236 int n;
1237
1238 if (client_prv == NULL)
1239 return NULL;
1240
1241 maxfd = max(client_prv->sock, client_prv->pipefd[0]) + 1;
1242
1243 printf("[*] %s() b_connect=%d, maxfd=%d\n", __FUNCTION__, client_prv->b_connect, maxfd);
1244 while (client_prv->b_connect) {
1245 FD_ZERO(&(client_prv->sock_rfds));
1246
1247 FD_SET(client_prv->sock, &(client_prv->sock_rfds));
1248 FD_SET(client_prv->pipefd[0], &(client_prv->sock_rfds));
1249
Andreas Schneider928ddca2017-02-08 16:52:54 +01001250 RLOGV("[*] %s() b_connect=%d\n", __FUNCTION__, client_prv->b_connect);
codeworkxf1587a32012-08-03 23:32:29 +02001251 if (select(maxfd, &(client_prv->sock_rfds), NULL, NULL, NULL) > 0) {
1252 if (FD_ISSET(client_prv->sock, &(client_prv->sock_rfds))) {
1253 // Read incoming data
1254 for (;;) {
1255 // loop until EAGAIN/EINTR, end of stream, or other error
1256 ret = record_stream_get_next(client_prv->p_rs, &p_record, &recordlen);
1257 if (ret == 0 && p_record == NULL) { // end-of-stream
1258 break;
1259 }
1260 else if (ret < 0) {
1261 break;
1262 }
1263 else if (ret == 0) { // && p_record != NULL
1264 n = processRxBuffer(client_prv, p_record, recordlen);
1265 if (n != RIL_CLIENT_ERR_SUCCESS) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001266 RLOGE("%s: processRXBuffer returns %d", __FUNCTION__, n);
codeworkxf1587a32012-08-03 23:32:29 +02001267 }
1268 }
1269 else {
1270 printf("[*] %s()\n", __FUNCTION__);
1271 }
1272 }
1273
1274 if (ret == 0 || !(errno == EAGAIN || errno == EINTR)) {
1275 // fatal error or end-of-stream
1276 if (client_prv->sock > 0) {
1277 close(client_prv->sock);
1278 client_prv->sock = -1;
1279 client_prv->b_connect = 0;
1280 }
1281
1282 if (client_prv->p_rs)
1283 record_stream_free(client_prv->p_rs);
1284
1285 // EOS
1286 if (client_prv->err_cb) {
1287 client_prv->err_cb(client_prv->err_cb_data, RIL_CLIENT_ERR_CONNECT);
1288 return NULL;
1289 }
1290
1291 break;
1292 }
1293 }
1294 if (FD_ISSET(client_prv->pipefd[0], &(client_prv->sock_rfds))) {
1295 char end_cmd[10];
1296
Andreas Schneider928ddca2017-02-08 16:52:54 +01001297 RLOGV("%s(): close\n", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +02001298
1299 if (read(client_prv->pipefd[0], end_cmd, sizeof(end_cmd)) > 0) {
1300 close(client_prv->sock);
1301 close(client_prv->pipefd[0]);
1302 close(client_prv->pipefd[1]);
1303
1304 client_prv->sock = -1;
1305 client_prv->b_connect = 0;
1306 }
1307 }
Basil Gello2a400242017-07-18 22:00:01 +03001308 } else {
1309 RLOGE("%s: select() returned %d\n", __FUNCTION__, -errno);
1310
1311 if (client_prv->sock > 0) {
1312 close(client_prv->sock);
1313 client_prv->sock = -1;
1314 client_prv->b_connect = 0;
1315 }
1316
1317 if (client_prv->p_rs)
1318 record_stream_free(client_prv->p_rs);
1319
1320 // EOS
1321 if (client_prv->err_cb) {
1322 client_prv->err_cb(client_prv->err_cb_data, RIL_CLIENT_ERR_CONNECT);
1323 return NULL;
1324 }
codeworkxf1587a32012-08-03 23:32:29 +02001325 }
1326 }
1327
1328 return NULL;
1329}
1330
1331
1332static int processUnsolicited(RilClientPrv *prv, Parcel &p) {
1333 int32_t resp_id, len;
1334 status_t status;
1335 const void *data = NULL;
1336 RilOnUnsolicited unsol_func = NULL;
1337
1338 status = p.readInt32(&resp_id);
1339 if (status != NO_ERROR) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001340 RLOGE("%s: read resp_id failed.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +02001341 return RIL_CLIENT_ERR_IO;
1342 }
1343
1344 status = p.readInt32(&len);
1345 if (status != NO_ERROR) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001346 //RLOGE("%s: read length failed. assume zero length.", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +02001347 len = 0;
1348 }
1349
Andreas Schneider560e37a2017-02-06 18:19:39 +01001350 RLOGD("%s(): resp_id (%d), len(%d)\n", __FUNCTION__, resp_id, len);
codeworkxf1587a32012-08-03 23:32:29 +02001351
1352 if (len)
1353 data = p.readInplace(len);
1354
1355 // Find unsolicited response handler.
1356 unsol_func = FindUnsolHandler(prv, (uint32_t)resp_id);
1357 if (unsol_func) {
1358 unsol_func(prv->parent, data, len);
1359 }
1360
1361 return RIL_CLIENT_ERR_SUCCESS;
1362}
1363
1364
1365static int processSolicited(RilClientPrv *prv, Parcel &p) {
1366 int32_t token, err, len;
1367 status_t status;
1368 const void *data = NULL;
1369 RilOnComplete req_func = NULL;
1370 int ret = RIL_CLIENT_ERR_SUCCESS;
1371 uint32_t req_id = 0;
1372
Andreas Schneider928ddca2017-02-08 16:52:54 +01001373 RLOGV("%s()", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +02001374
1375 status = p.readInt32(&token);
1376 if (status != NO_ERROR) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001377 RLOGE("%s: Read token fail. Status %d\n", __FUNCTION__, status);
codeworkxf1587a32012-08-03 23:32:29 +02001378 return RIL_CLIENT_ERR_IO;
1379 }
1380
1381 if (IsValidToken(&(prv->token_pool), token) == 0) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001382 RLOGE("%s: Invalid Token", __FUNCTION__);
codeworkxf1587a32012-08-03 23:32:29 +02001383 return RIL_CLIENT_ERR_INVAL; // Invalid token.
1384 }
1385
1386 status = p.readInt32(&err);
1387 if (status != NO_ERROR) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001388 RLOGE("%s: Read err fail. Status %d\n", __FUNCTION__, status);
codeworkxf1587a32012-08-03 23:32:29 +02001389 ret = RIL_CLIENT_ERR_IO;
1390 goto error;
1391 }
1392
1393 // Don't go further for error response.
1394 if (err != RIL_CLIENT_ERR_SUCCESS) {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001395 RLOGE("%s: Error %d\n", __FUNCTION__, err);
codeworkxf1587a32012-08-03 23:32:29 +02001396 if (prv->err_cb)
1397 prv->err_cb(prv->err_cb_data, err);
1398 ret = RIL_CLIENT_ERR_SUCCESS;
1399 goto error;
1400 }
1401
1402 status = p.readInt32(&len);
1403 if (status != NO_ERROR) {
1404 /* no length field */
1405 len = 0;
1406 }
1407
1408 if (len)
1409 data = p.readInplace(len);
1410
1411 // Find request handler for the token.
1412 // First, FindReqHandler() searches request history with the token
1413 // and finds out a request ID. Then, it search request handler table
1414 // with the request ID.
1415 req_func = FindReqHandler(prv, token, &req_id);
1416 if (req_func)
1417 {
Andreas Schneider928ddca2017-02-08 16:52:54 +01001418 RLOGV("[*] Call handler");
codeworkxf1587a32012-08-03 23:32:29 +02001419 req_func(prv->parent, data, len);
1420
1421 if(prv->b_del_handler) {
1422 prv->b_del_handler = 0;
1423 RegisterRequestCompleteHandler(prv->parent, req_id, NULL);
1424 }
1425 } else {
Andreas Schneider928ddca2017-02-08 16:52:54 +01001426 RLOGV("%s: No handler for token %d\n", __FUNCTION__, token);
codeworkxf1587a32012-08-03 23:32:29 +02001427 }
1428
1429error:
1430 FreeToken(&(prv->token_pool), token);
1431 ClearReqHistory(prv, token);
1432 return ret;
1433}
1434
1435
1436static int processRxBuffer(RilClientPrv *prv, void *buffer, size_t buflen) {
1437 Parcel p;
1438 int32_t response_type;
1439 status_t status;
1440 int ret = RIL_CLIENT_ERR_SUCCESS;
1441
1442 acquire_wake_lock(PARTIAL_WAKE_LOCK, RIL_CLIENT_WAKE_LOCK);
1443
1444 p.setData((uint8_t *)buffer, buflen);
1445
1446 status = p.readInt32(&response_type);
Andreas Schneider928ddca2017-02-08 16:52:54 +01001447 RLOGV("%s: status %d response_type %d", __FUNCTION__, status, response_type);
codeworkxf1587a32012-08-03 23:32:29 +02001448
1449 if (status != NO_ERROR) {
1450 ret = RIL_CLIENT_ERR_IO;
1451 goto EXIT;
1452 }
1453
1454 // FOr unsolicited response.
1455 if (response_type == RESPONSE_UNSOLICITED) {
1456 ret = processUnsolicited(prv, p);
1457 }
1458 // For solicited response.
1459 else if (response_type == RESPONSE_SOLICITED) {
1460 ret = processSolicited(prv, p);
1461 if (ret != RIL_CLIENT_ERR_SUCCESS && prv->err_cb) {
1462 prv->err_cb(prv->err_cb_data, ret);
1463 }
1464 }
1465 else {
1466 ret = RIL_CLIENT_ERR_INVAL;
1467 }
1468
1469EXIT:
1470 release_wake_lock(RIL_CLIENT_WAKE_LOCK);
1471 return ret;
1472}
1473
1474
1475static uint32_t AllocateToken(uint32_t *token_pool) {
1476 int i;
1477
1478 // Token pool is full.
1479 if (*token_pool == 0xFFFFFFFF)
1480 return 0;
1481
1482 for (i = 0; i < 32; i++) {
1483 uint32_t new_token = 0x00000001 << i;
1484
1485 if ((*token_pool & new_token) == 0) {
1486 *token_pool |= new_token;
1487 return new_token;
1488 }
1489 }
1490
1491 return 0;
1492}
1493
1494
1495static void FreeToken(uint32_t *token_pool, uint32_t token) {
1496 *token_pool &= ~token;
1497}
1498
1499
1500static uint8_t IsValidToken(uint32_t *token_pool, uint32_t token) {
1501 if (token == 0)
1502 return 0;
1503
1504 if ((*token_pool & token) == token)
1505 return 1;
1506 else
1507 return 0;
1508}
1509
1510
1511static int RecordReqHistory(RilClientPrv *prv, int token, uint32_t id) {
1512 int i = 0;
1513
Andreas Schneider928ddca2017-02-08 16:52:54 +01001514 RLOGV("[*] %s(): token(%d), ID(%d)\n", __FUNCTION__, token, id);
codeworkxf1587a32012-08-03 23:32:29 +02001515 for (i = 0; i < TOKEN_POOL_SIZE; i++) {
1516 if (prv->history[i].token == 0) {
1517 prv->history[i].token = token;
1518 prv->history[i].id = id;
1519
Andreas Schneider928ddca2017-02-08 16:52:54 +01001520 RLOGV("[*] %s(): token(%d), ID(%d)\n", __FUNCTION__, token, id);
codeworkxf1587a32012-08-03 23:32:29 +02001521
1522 return RIL_CLIENT_ERR_SUCCESS;
1523 }
1524 }
1525
Andreas Schneider560e37a2017-02-06 18:19:39 +01001526 RLOGE("%s: No free record for token %d", __FUNCTION__, token);
codeworkxf1587a32012-08-03 23:32:29 +02001527
1528 return RIL_CLIENT_ERR_RESOURCE;
1529}
1530
1531static void ClearReqHistory(RilClientPrv *prv, int token) {
1532 int i = 0;
1533
Andreas Schneider928ddca2017-02-08 16:52:54 +01001534 RLOGV("[*] %s(): token(%d)\n", __FUNCTION__, token);
codeworkxf1587a32012-08-03 23:32:29 +02001535 for (i = 0; i < TOKEN_POOL_SIZE; i++) {
1536 if (prv->history[i].token == token) {
1537 memset(&(prv->history[i]), 0, sizeof(ReqHistory));
1538 break;
1539 }
1540 }
1541}
1542
1543
1544static RilOnUnsolicited FindUnsolHandler(RilClientPrv *prv, uint32_t id) {
1545 int i;
1546
1547 // Search unsolicited handler table.
1548 for (i = 0; i < REQ_POOL_SIZE; i++) {
1549 if (prv->unsol_handlers[i].id == id)
1550 return prv->unsol_handlers[i].handler;
1551 }
1552
1553 return (RilOnUnsolicited)NULL;
1554}
1555
1556
1557static RilOnComplete FindReqHandler(RilClientPrv *prv, int token, uint32_t *id) {
1558 int i = 0;
1559 int j = 0;
1560
Andreas Schneider928ddca2017-02-08 16:52:54 +01001561 RLOGV("[*] %s(): token(%d)\n", __FUNCTION__, token);
codeworkxf1587a32012-08-03 23:32:29 +02001562
1563 // Search request history.
1564 for (i = 0; i < TOKEN_POOL_SIZE; i++) {
1565 printf("[*] %s(): history_token(%d)\n", __FUNCTION__, prv->history[i].token);
1566 if (prv->history[i].token == token) {
1567 // Search request handler with request ID found.
1568 for (j = 0; j < REQ_POOL_SIZE; j++) {
1569 printf("[*] %s(): token(%d), req_id(%d), history_id(%d)\n", __FUNCTION__, token, prv->history[i].id, prv->history[i].id);
1570 if (prv->req_handlers[j].id == prv->history[i].id) {
1571 *id = prv->req_handlers[j].id;
1572 return prv->req_handlers[j].handler;
1573 }
1574 }
1575 }
1576 }
1577
1578 return NULL;
1579}
1580
1581
1582static void DeallocateToken(uint32_t *token_pool, uint32_t token) {
1583 *token_pool &= !token;
1584}
1585
1586
1587static int blockingWrite(int fd, const void *buffer, size_t len) {
1588 size_t writeOffset = 0;
1589 const uint8_t *toWrite;
1590 ssize_t written = 0;
1591
1592 if (buffer == NULL)
1593 return -1;
1594
1595 toWrite = (const uint8_t *)buffer;
1596
1597 while (writeOffset < len) {
1598 do
1599 {
1600 written = write(fd, toWrite + writeOffset, len - writeOffset);
1601 } while (written < 0 && errno == EINTR);
1602
1603 if (written >= 0) {
1604 writeOffset += written;
1605 }
1606 else {
Andreas Schneider560e37a2017-02-06 18:19:39 +01001607 RLOGE ("RIL Response: unexpected error on write errno:%d", errno);
codeworkxf1587a32012-08-03 23:32:29 +02001608 close(fd);
Basil Gello338942b2017-07-13 19:36:39 +03001609 return -errno;
codeworkxf1587a32012-08-03 23:32:29 +02001610 }
1611 }
1612
1613 return 0;
1614}
1615
1616} // namespace android
1617
1618// end of file
1619