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