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