blob: 61f046d176084f44bca80ff869dfb611ea8a722b [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
Andreas Schneider6b9cd5f2015-01-23 22:41:22 +010087#ifdef MODEM_TYPE_XMM7260
88#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"
671int SetCallAudioPath(HRilClient client, AudioPath path, ExtraVolume mode) {
672 RilClientPrv *client_prv;
673 int ret;
674 char data[6] = {0,};
675
676 if (client == NULL || client->prv == NULL) {
677 ALOGE("%s: Invalid client %p", __FUNCTION__, client);
678 return RIL_CLIENT_ERR_INVAL;
679 }
680
681 client_prv = (RilClientPrv *)(client->prv);
682
683 if (client_prv->sock < 0 ) {
684 ALOGE("%s: Not connected.", __FUNCTION__);
685 return RIL_CLIENT_ERR_CONNECT;
686 }
687
688 if (isValidAudioPath(path) == false) {
689 ALOGE("%s: Invalid audio path", __FUNCTION__);
690 return RIL_CLIENT_ERR_INVAL;
691 }
692
693 // Make raw data
694 data[0] = OEM_FUNC_SOUND;
695 data[1] = OEM_SND_SET_AUDIO_PATH;
696 data[2] = 0x00; // data length
697 data[3] = 0x06; // data length
698 data[4] = ConvertAudioPath(path); // audio path
699 data[5] = mode; // ExtraVolume
700
701 RegisterRequestCompleteHandler(client, REQ_SET_AUDIO_PATH, NULL);
702
703 ret = SendOemRequestHookRaw(client, REQ_SET_AUDIO_PATH, data, sizeof(data));
704 if (ret != RIL_CLIENT_ERR_SUCCESS) {
705 RegisterRequestCompleteHandler(client, REQ_SET_AUDIO_PATH, NULL);
706 }
707
708 return ret;
709}
710
711
712/**
713 * Set modem clock to master or slave.
714 */
715extern "C"
716int SetCallClockSync(HRilClient client, SoundClockCondition condition) {
717 RilClientPrv *client_prv;
718 int ret;
719 char data[5] = {0,};
720
721 if (client == NULL || client->prv == NULL) {
722 ALOGE("%s: Invalid client %p", __FUNCTION__, client);
723 return RIL_CLIENT_ERR_INVAL;
724 }
725
726 client_prv = (RilClientPrv *)(client->prv);
727
728 if (client_prv->sock < 0 ) {
729 ALOGE("%s: Not connected.", __FUNCTION__);
730 return RIL_CLIENT_ERR_CONNECT;
731 }
732
733 if (isValidSoundClockCondition(condition) == false) {
734 ALOGE("%s: Invalid sound clock condition", __FUNCTION__);
735 return RIL_CLIENT_ERR_INVAL;
736 }
737
738 // Make raw data
739 data[0] = OEM_FUNC_SOUND;
740 data[1] = OEM_SND_SET_CLOCK_CTRL;
741 data[2] = 0x00; // data length
742 data[3] = 0x05; // data length
743 data[4] = condition;
744
745 RegisterRequestCompleteHandler(client, REQ_SET_CALL_CLOCK_SYNC, NULL);
746
747 ret = SendOemRequestHookRaw(client, REQ_SET_CALL_CLOCK_SYNC, data, sizeof(data));
748 if (ret != RIL_CLIENT_ERR_SUCCESS) {
749 RegisterRequestCompleteHandler(client, REQ_SET_CALL_CLOCK_SYNC, NULL);
750 }
751
752 return ret;
753}
754
755/**
756 * Set modem VTCall clock to master or slave.
757 */
758extern "C"
759int SetVideoCallClockSync(HRilClient client, SoundClockCondition condition) {
760 RilClientPrv *client_prv;
761 int ret;
762 char data[5] = {0,};
763
764 if (client == NULL || client->prv == NULL) {
765 ALOGE("%s: Invalid client %p", __FUNCTION__, client);
766 return RIL_CLIENT_ERR_INVAL;
767 }
768
769 client_prv = (RilClientPrv *)(client->prv);
770
771 if (client_prv->sock < 0 ) {
772 ALOGE("%s: Not connected.", __FUNCTION__);
773 return RIL_CLIENT_ERR_CONNECT;
774 }
775
776 if (isValidSoundClockCondition(condition) == false) {
777 ALOGE("%s: Invalid sound clock condition", __FUNCTION__);
778 return RIL_CLIENT_ERR_INVAL;
779 }
780
781 // Make raw data
782 data[0] = OEM_FUNC_SOUND;
783 data[1] = OEM_SND_SET_VIDEO_CALL_CTRL;
784 data[2] = 0x00; // data length
785 data[3] = 0x05; // data length
786 data[4] = condition;
787
788 RegisterRequestCompleteHandler(client, REQ_SET_CALL_VT_CTRL, NULL);
789
790 ret = SendOemRequestHookRaw(client, REQ_SET_CALL_VT_CTRL, data, sizeof(data));
791 if (ret != RIL_CLIENT_ERR_SUCCESS) {
792 RegisterRequestCompleteHandler(client, REQ_SET_CALL_VT_CTRL, NULL);
793 }
794
795 return ret;
796}
797
798/**
799 * Set voice recording.
800 */
801extern "C"
802int SetCallRecord(HRilClient client, CallRecCondition condition) {
803 RilClientPrv *client_prv;
804 int ret;
805 char data[5] = {0,};
806
807 if (client == NULL || client->prv == NULL) {
808 ALOGE("%s: Invalid client %p", __FUNCTION__, client);
809 return RIL_CLIENT_ERR_INVAL;
810 }
811
812 client_prv = (RilClientPrv *)(client->prv);
813
814 if (client_prv->sock < 0 ) {
815 ALOGE("%s: Not connected.", __FUNCTION__);
816 return RIL_CLIENT_ERR_CONNECT;
817 }
818
819 if (isValidCallRecCondition(condition) == false) {
820 ALOGE("%s: Invalid sound clock condition", __FUNCTION__);
821 return RIL_CLIENT_ERR_INVAL;
822 }
823
824 // Make raw data
825 data[0] = OEM_FUNC_SOUND;
826 data[1] = OEM_SND_SET_VOICE_RECORDING_CTRL;
827 data[2] = 0x00; // data length
828 data[3] = 0x05; // data length
829 data[4] = condition;
830
831 RegisterRequestCompleteHandler(client, REQ_SET_CALL_RECORDING, NULL);
832
833 ret = SendOemRequestHookRaw(client, REQ_SET_CALL_RECORDING, data, sizeof(data));
834 if (ret != RIL_CLIENT_ERR_SUCCESS) {
835 RegisterRequestCompleteHandler(client, REQ_SET_CALL_RECORDING, NULL);
836 }
837
838 return ret;
839}
840
841/**
842 * Set mute or unmute.
843 */
844extern "C"
845int SetMute(HRilClient client, MuteCondition condition) {
846 RilClientPrv *client_prv;
847 int ret;
848 char data[5] = {0,};
849
850 if (client == NULL || client->prv == NULL) {
851 ALOGE("%s: Invalid client %p", __FUNCTION__, client);
852 return RIL_CLIENT_ERR_INVAL;
853 }
854
855 client_prv = (RilClientPrv *)(client->prv);
856
857 if (client_prv->sock < 0 ) {
858 ALOGE("%s: Not connected.", __FUNCTION__);
859 return RIL_CLIENT_ERR_CONNECT;
860 }
861
862 if (isValidMuteCondition(condition) == false) {
863 ALOGE("%s: Invalid sound clock condition", __FUNCTION__);
864 return RIL_CLIENT_ERR_INVAL;
865 }
866
867 // Make raw data
868 data[0] = OEM_FUNC_SOUND;
869 data[1] = OEM_SND_SET_MUTE;
870 data[2] = 0x00; // data length
871 data[3] = 0x05; // data length
872 data[4] = condition;
873
874 RegisterRequestCompleteHandler(client, REQ_SET_CALL_MUTE, NULL);
875
876 ret = SendOemRequestHookRaw(client, REQ_SET_CALL_MUTE, data, sizeof(data));
877 if (ret != RIL_CLIENT_ERR_SUCCESS) {
878 RegisterRequestCompleteHandler(client, REQ_SET_CALL_MUTE, NULL);
879 }
880
881 return ret;
882}
883
884/**
885 * Get mute state.
886 */
887extern "C"
888int GetMute(HRilClient client, RilOnComplete handler) {
889 RilClientPrv *client_prv;
890 int ret;
891 char data[4] = {0,};
892
893 if (client == NULL || client->prv == NULL) {
894 ALOGE("%s: Invalid client %p", __FUNCTION__, client);
895 return RIL_CLIENT_ERR_INVAL;
896 }
897
898 client_prv = (RilClientPrv *)(client->prv);
899
900 if (client_prv->sock < 0 ) {
901 ALOGE("%s: Not connected.", __FUNCTION__);
902 return RIL_CLIENT_ERR_CONNECT;
903 }
904
905 client_prv->b_del_handler = 1;
906
907 // Make raw data
908 data[0] = OEM_FUNC_SOUND;
909 data[1] = OEM_SND_GET_MUTE;
910 data[2] = 0x00; // data length
911 data[3] = 0x04; // data length
912
913 RegisterRequestCompleteHandler(client, REQ_GET_CALL_MUTE, handler);
914
915 ret = SendOemRequestHookRaw(client, REQ_GET_CALL_MUTE, data, sizeof(data));
916 if (ret != RIL_CLIENT_ERR_SUCCESS) {
917 RegisterRequestCompleteHandler(client, REQ_GET_CALL_MUTE, NULL);
918 }
919
920 return ret;
921}
922
923extern "C"
924int SetTwoMicControl(HRilClient client, TwoMicSolDevice device, TwoMicSolReport report) {
925 RilClientPrv *client_prv;
926 int ret;
927 char data[6] = {0,};
928
929 ALOGE(" + %s", __FUNCTION__);
930
931 if (client == NULL || client->prv == NULL) {
932 ALOGE("%s: Invalid client %p", __FUNCTION__, client);
933 return RIL_CLIENT_ERR_INVAL;
934 }
935
936 client_prv = (RilClientPrv *)(client->prv);
937
938 if (client_prv->sock < 0 ) {
939 ALOGE("%s: Not connected.", __FUNCTION__);
940 return RIL_CLIENT_ERR_CONNECT;
941 }
942
943 if (isValidTwoMicCtrl(device, report) == false) {
944 ALOGE("%s: Invalid sound set two params", __FUNCTION__);
945 return RIL_CLIENT_ERR_INVAL;
946 }
947
948 // Make raw data
949 data[0] = OEM_FUNC_SOUND;
950 data[1] = OEM_SND_SET_TWO_MIC_CTL;
951 data[2] = 0x00; // data length
952 data[3] = 0x06; // data length
953 data[4] = device;
954 data[5] = report;
955
956 RegisterRequestCompleteHandler(client, REQ_SET_TWO_MIC_CTRL, NULL);
957
958 ret = SendOemRequestHookRaw(client, REQ_SET_TWO_MIC_CTRL, data, sizeof(data));
959 if (ret != RIL_CLIENT_ERR_SUCCESS) {
960 RegisterRequestCompleteHandler(client, REQ_SET_TWO_MIC_CTRL, NULL);
961 }
962
963 ALOGE(" - %s", __FUNCTION__);
964
965 return ret;
966}
967
968extern "C"
969int SetDhaSolution(HRilClient client, DhaSolMode mode, DhaSolSelect select, char *parameter) {
970 RilClientPrv *client_prv;
971 int ret;
972 char data[30] = {0,};
973 char tempPara[24]={0,};
974
975 if (client == NULL || client->prv == NULL) {
976 ALOGE("%s: Invalid client %p", __FUNCTION__, client);
977 return RIL_CLIENT_ERR_INVAL;
978 }
979
980 client_prv = (RilClientPrv *)(client->prv);
981
982 if (client_prv->sock < 0 ) {
983 ALOGE("%s: Not connected.", __FUNCTION__);
984 return RIL_CLIENT_ERR_CONNECT;
985 }
986
987 ALOGE("%s: DHA mode=%d, select=%d", __FUNCTION__,mode, select);
988
989 // Make raw data
990 data[0] = OEM_FUNC_SOUND;
991 data[1] = OEM_SND_SET_DHA_CTL;
992 data[2] = 0x00; // data length
993 data[3] = 0x1E; // data length
994 data[4] = mode;
995 data[5] = select;
996
997 memcpy(tempPara, parameter, 24);
998 for(int i=0; i<24; i++)
999 data[6+i]= tempPara[i];
1000
1001 RegisterRequestCompleteHandler(client, REQ_SET_DHA_CTRL, NULL);
1002
1003 ret = SendOemRequestHookRaw(client, REQ_SET_DHA_CTRL, data, sizeof(data));
1004 if (ret != RIL_CLIENT_ERR_SUCCESS) {
1005 RegisterRequestCompleteHandler(client, REQ_SET_DHA_CTRL, NULL);
1006 }
1007
1008 return ret;
1009}
1010
1011/**
1012 * Set LoopbackTest mode, path.
1013 */
1014extern "C"
1015int SetLoopbackTest(HRilClient client, LoopbackMode mode, AudioPath path) {
1016 RilClientPrv *client_prv;
1017 int ret;
1018 char data[6] = {0,};
1019
1020 if (client == NULL || client->prv == NULL) {
1021 ALOGE("%s: Invalid client %p", __FUNCTION__, client);
1022 return RIL_CLIENT_ERR_INVAL;
1023 }
1024
1025 client_prv = (RilClientPrv *)(client->prv);
1026
1027 if (client_prv->sock < 0 ) {
1028 ALOGE("%s: Not connected.", __FUNCTION__);
1029 return RIL_CLIENT_ERR_CONNECT;
1030 }
1031
1032 // Make raw data
1033 data[0] = OEM_FUNC_SOUND;
1034 data[1] = OEM_SND_SET_LOOPBACK_CTRL;
1035 data[2] = 0x00; // data length
1036 data[3] = 0x06; // data length
1037 data[4] = mode; // Loopback Mode
1038 data[5] = ConvertAudioPath(path); // Loopback path
1039
1040 RegisterRequestCompleteHandler(client, REQ_SET_LOOPBACK, NULL);
1041
1042 ret = SendOemRequestHookRaw(client, REQ_SET_LOOPBACK, data, sizeof(data));
1043 if (ret != RIL_CLIENT_ERR_SUCCESS) {
1044 RegisterRequestCompleteHandler(client, REQ_SET_LOOPBACK, NULL);
1045 }
1046
1047 return ret;
1048}
1049
1050
1051/**
1052 * @fn int InvokeOemRequestHookRaw(HRilClient client, char *data, size_t len)
1053 *
1054 * @params client: Client handle.
1055 * data: Request data.
1056 * len: Request data length.
1057 *
1058 * @return 0 for success or error code. On receiving RIL_CLIENT_ERR_AGAIN,
1059 * caller should retry.
1060 */
1061extern "C"
1062int InvokeOemRequestHookRaw(HRilClient client, char *data, size_t len) {
1063 RilClientPrv *client_prv;
1064
1065 if (client == NULL || client->prv == NULL) {
1066 ALOGE("%s: Invalid client %p", __FUNCTION__, client);
1067 return RIL_CLIENT_ERR_INVAL;
1068 }
1069
1070 client_prv = (RilClientPrv *)(client->prv);
1071
1072 if (client_prv->sock < 0 ) {
1073 ALOGE("%s: Not connected.", __FUNCTION__);
1074 return RIL_CLIENT_ERR_CONNECT;
1075 }
1076
1077 return SendOemRequestHookRaw(client, REQ_OEM_HOOK_RAW, data, len);
1078}
1079
1080
1081static int SendOemRequestHookRaw(HRilClient client, int req_id, char *data, size_t len) {
1082 int token = 0;
1083 int ret = 0;
1084 uint32_t header = 0;
1085 android::Parcel p;
1086 RilClientPrv *client_prv;
1087 int maxfd = -1;
1088
1089 client_prv = (RilClientPrv *)(client->prv);
1090
1091 // Allocate a token.
1092 token = AllocateToken(&(client_prv->token_pool));
1093 if (token == 0) {
1094 ALOGE("%s: No token.", __FUNCTION__);
1095 return RIL_CLIENT_ERR_AGAIN;
1096 }
1097
1098 // Record token for the request sent.
1099 if (RecordReqHistory(client_prv, token, req_id) != RIL_CLIENT_ERR_SUCCESS) {
1100 goto error;
1101 }
1102
1103 // Make OEM request data.
1104 p.writeInt32(RIL_REQUEST_OEM_HOOK_RAW);
1105 p.writeInt32(token);
1106 p.writeInt32(len);
1107 p.write((void *)data, len);
1108
1109 // DO TX: header(size).
1110 header = htonl(p.dataSize());
1111
1112 if (DBG) ALOGD("%s(): token = %d\n", __FUNCTION__, token);
1113
1114 ret = blockingWrite(client_prv->sock, (void *)&header, sizeof(header));
1115 if (ret < 0) {
1116 ALOGE("%s: send request header failed. (%d)", __FUNCTION__, ret);
1117 goto error;
1118 }
1119
1120 // Do TX: response data.
1121 ret = blockingWrite(client_prv->sock, p.data(), p.dataSize());
1122 if (ret < 0) {
1123 ALOGE("%s: send request data failed. (%d)", __FUNCTION__, ret);
1124 goto error;
1125 }
1126
1127 return RIL_CLIENT_ERR_SUCCESS;
1128
1129error:
1130 FreeToken(&(client_prv->token_pool), token);
1131 ClearReqHistory(client_prv, token);
1132
1133 return RIL_CLIENT_ERR_UNKNOWN;
1134}
1135
1136
1137static bool isValidSoundType(SoundType type) {
1138 return (type >= SOUND_TYPE_VOICE && type <= SOUND_TYPE_BTVOICE);
1139}
1140
1141
1142static bool isValidAudioPath(AudioPath path) {
1143 return (path >= SOUND_AUDIO_PATH_HANDSET && path <= OEM_SND_AUDIO_PATH_BT_WB_NSEC_OFF);
1144}
1145
1146
1147static bool isValidSoundClockCondition(SoundClockCondition condition) {
1148 return (condition >= SOUND_CLOCK_STOP && condition <= SOUND_CLOCK_START);
1149}
1150
1151static bool isValidCallRecCondition(CallRecCondition condition) {
1152 return (condition >= CALL_REC_STOP && condition <= CALL_REC_START);
1153}
1154
1155static bool isValidMuteCondition(MuteCondition condition) {
1156 return (condition >= TX_UNMUTE && condition <= RXTX_MUTE);
1157}
1158
1159static bool isValidTwoMicCtrl(TwoMicSolDevice device, TwoMicSolReport report) {
1160 return (device >= AUDIENCE && device <= FORTEMEDIA && report >= TWO_MIC_SOLUTION_OFF && report <= TWO_MIC_SOLUTION_ON );
1161}
1162
1163
1164static char ConvertSoundType(SoundType type) {
1165 switch (type) {
1166 case SOUND_TYPE_VOICE:
1167 return OEM_SND_TYPE_VOICE;
1168 case SOUND_TYPE_SPEAKER:
1169 return OEM_SND_TYPE_SPEAKER;
1170 case SOUND_TYPE_HEADSET:
1171 return OEM_SND_TYPE_HEADSET;
1172 case SOUND_TYPE_BTVOICE:
1173 return OEM_SND_TYPE_BTVOICE;
1174 default:
1175 return OEM_SND_TYPE_VOICE;
1176 }
1177}
1178
1179
1180static char ConvertAudioPath(AudioPath path) {
1181 switch (path) {
1182 case SOUND_AUDIO_PATH_HANDSET:
1183 return OEM_SND_AUDIO_PATH_HANDSET;
1184 case SOUND_AUDIO_PATH_HEADSET:
1185 return OEM_SND_AUDIO_PATH_HEADSET;
1186 case SOUND_AUDIO_PATH_SPEAKER:
1187 return OEM_SND_AUDIO_PATH_SPEAKER;
1188 case SOUND_AUDIO_PATH_BLUETOOTH:
1189 return OEM_SND_AUDIO_PATH_BLUETOOTH;
1190 case SOUND_AUDIO_PATH_STEREO_BT:
1191 return OEM_SND_AUDIO_PATH_STEREO_BLUETOOTH;
1192 case SOUND_AUDIO_PATH_HEADPHONE:
1193 return OEM_SND_AUDIO_PATH_HEADPHONE;
1194 case SOUND_AUDIO_PATH_BLUETOOTH_NO_NR:
1195 return OEM_SND_AUDIO_PATH_BT_NSEC_OFF;
1196 case SOUND_AUDIO_PATH_MIC1:
1197 return OEM_SND_AUDIO_PATH_MIC1;
1198 case SOUND_AUDIO_PATH_MIC2:
1199 return OEM_SND_AUDIO_PATH_MIC2;
1200 case SOUND_AUDIO_PATH_BLUETOOTH_WB:
1201 return OEM_SND_AUDIO_PATH_BT_WB;
1202 case SOUND_AUDIO_PATH_BLUETOOTH_WB_NO_NR:
1203 return OEM_SND_AUDIO_PATH_BT_WB_NSEC_OFF;
1204
1205 default:
1206 return OEM_SND_AUDIO_PATH_HANDSET;
1207 }
1208}
1209
1210
1211static void * RxReaderFunc(void *param) {
1212 RilClientPrv *client_prv = (RilClientPrv *)param;
1213 int maxfd = 0;
1214 int token = 0;
1215 void *p_record = NULL;
1216 size_t recordlen = 0;
1217 int ret = 0;
1218 int n;
1219
1220 if (client_prv == NULL)
1221 return NULL;
1222
1223 maxfd = max(client_prv->sock, client_prv->pipefd[0]) + 1;
1224
1225 printf("[*] %s() b_connect=%d, maxfd=%d\n", __FUNCTION__, client_prv->b_connect, maxfd);
1226 while (client_prv->b_connect) {
1227 FD_ZERO(&(client_prv->sock_rfds));
1228
1229 FD_SET(client_prv->sock, &(client_prv->sock_rfds));
1230 FD_SET(client_prv->pipefd[0], &(client_prv->sock_rfds));
1231
1232 if (DBG) ALOGD("[*] %s() b_connect=%d\n", __FUNCTION__, client_prv->b_connect);
1233 if (select(maxfd, &(client_prv->sock_rfds), NULL, NULL, NULL) > 0) {
1234 if (FD_ISSET(client_prv->sock, &(client_prv->sock_rfds))) {
1235 // Read incoming data
1236 for (;;) {
1237 // loop until EAGAIN/EINTR, end of stream, or other error
1238 ret = record_stream_get_next(client_prv->p_rs, &p_record, &recordlen);
1239 if (ret == 0 && p_record == NULL) { // end-of-stream
1240 break;
1241 }
1242 else if (ret < 0) {
1243 break;
1244 }
1245 else if (ret == 0) { // && p_record != NULL
1246 n = processRxBuffer(client_prv, p_record, recordlen);
1247 if (n != RIL_CLIENT_ERR_SUCCESS) {
1248 ALOGE("%s: processRXBuffer returns %d", __FUNCTION__, n);
1249 }
1250 }
1251 else {
1252 printf("[*] %s()\n", __FUNCTION__);
1253 }
1254 }
1255
1256 if (ret == 0 || !(errno == EAGAIN || errno == EINTR)) {
1257 // fatal error or end-of-stream
1258 if (client_prv->sock > 0) {
1259 close(client_prv->sock);
1260 client_prv->sock = -1;
1261 client_prv->b_connect = 0;
1262 }
1263
1264 if (client_prv->p_rs)
1265 record_stream_free(client_prv->p_rs);
1266
1267 // EOS
1268 if (client_prv->err_cb) {
1269 client_prv->err_cb(client_prv->err_cb_data, RIL_CLIENT_ERR_CONNECT);
1270 return NULL;
1271 }
1272
1273 break;
1274 }
1275 }
1276 if (FD_ISSET(client_prv->pipefd[0], &(client_prv->sock_rfds))) {
1277 char end_cmd[10];
1278
1279 if (DBG) ALOGD("%s(): close\n", __FUNCTION__);
1280
1281 if (read(client_prv->pipefd[0], end_cmd, sizeof(end_cmd)) > 0) {
1282 close(client_prv->sock);
1283 close(client_prv->pipefd[0]);
1284 close(client_prv->pipefd[1]);
1285
1286 client_prv->sock = -1;
1287 client_prv->b_connect = 0;
1288 }
1289 }
1290 }
1291 }
1292
1293 return NULL;
1294}
1295
1296
1297static int processUnsolicited(RilClientPrv *prv, Parcel &p) {
1298 int32_t resp_id, len;
1299 status_t status;
1300 const void *data = NULL;
1301 RilOnUnsolicited unsol_func = NULL;
1302
1303 status = p.readInt32(&resp_id);
1304 if (status != NO_ERROR) {
1305 ALOGE("%s: read resp_id failed.", __FUNCTION__);
1306 return RIL_CLIENT_ERR_IO;
1307 }
1308
1309 status = p.readInt32(&len);
1310 if (status != NO_ERROR) {
1311 //ALOGE("%s: read length failed. assume zero length.", __FUNCTION__);
1312 len = 0;
1313 }
1314
1315 ALOGD("%s(): resp_id (%d), len(%d)\n", __FUNCTION__, resp_id, len);
1316
1317 if (len)
1318 data = p.readInplace(len);
1319
1320 // Find unsolicited response handler.
1321 unsol_func = FindUnsolHandler(prv, (uint32_t)resp_id);
1322 if (unsol_func) {
1323 unsol_func(prv->parent, data, len);
1324 }
1325
1326 return RIL_CLIENT_ERR_SUCCESS;
1327}
1328
1329
1330static int processSolicited(RilClientPrv *prv, Parcel &p) {
1331 int32_t token, err, len;
1332 status_t status;
1333 const void *data = NULL;
1334 RilOnComplete req_func = NULL;
1335 int ret = RIL_CLIENT_ERR_SUCCESS;
1336 uint32_t req_id = 0;
1337
1338 if (DBG) ALOGD("%s()", __FUNCTION__);
1339
1340 status = p.readInt32(&token);
1341 if (status != NO_ERROR) {
1342 ALOGE("%s: Read token fail. Status %d\n", __FUNCTION__, status);
1343 return RIL_CLIENT_ERR_IO;
1344 }
1345
1346 if (IsValidToken(&(prv->token_pool), token) == 0) {
1347 ALOGE("%s: Invalid Token", __FUNCTION__);
1348 return RIL_CLIENT_ERR_INVAL; // Invalid token.
1349 }
1350
1351 status = p.readInt32(&err);
1352 if (status != NO_ERROR) {
1353 ALOGE("%s: Read err fail. Status %d\n", __FUNCTION__, status);
1354 ret = RIL_CLIENT_ERR_IO;
1355 goto error;
1356 }
1357
1358 // Don't go further for error response.
1359 if (err != RIL_CLIENT_ERR_SUCCESS) {
1360 ALOGE("%s: Error %d\n", __FUNCTION__, err);
1361 if (prv->err_cb)
1362 prv->err_cb(prv->err_cb_data, err);
1363 ret = RIL_CLIENT_ERR_SUCCESS;
1364 goto error;
1365 }
1366
1367 status = p.readInt32(&len);
1368 if (status != NO_ERROR) {
1369 /* no length field */
1370 len = 0;
1371 }
1372
1373 if (len)
1374 data = p.readInplace(len);
1375
1376 // Find request handler for the token.
1377 // First, FindReqHandler() searches request history with the token
1378 // and finds out a request ID. Then, it search request handler table
1379 // with the request ID.
1380 req_func = FindReqHandler(prv, token, &req_id);
1381 if (req_func)
1382 {
1383 if (DBG) ALOGD("[*] Call handler");
1384 req_func(prv->parent, data, len);
1385
1386 if(prv->b_del_handler) {
1387 prv->b_del_handler = 0;
1388 RegisterRequestCompleteHandler(prv->parent, req_id, NULL);
1389 }
1390 } else {
1391 if (DBG) ALOGD("%s: No handler for token %d\n", __FUNCTION__, token);
1392 }
1393
1394error:
1395 FreeToken(&(prv->token_pool), token);
1396 ClearReqHistory(prv, token);
1397 return ret;
1398}
1399
1400
1401static int processRxBuffer(RilClientPrv *prv, void *buffer, size_t buflen) {
1402 Parcel p;
1403 int32_t response_type;
1404 status_t status;
1405 int ret = RIL_CLIENT_ERR_SUCCESS;
1406
1407 acquire_wake_lock(PARTIAL_WAKE_LOCK, RIL_CLIENT_WAKE_LOCK);
1408
1409 p.setData((uint8_t *)buffer, buflen);
1410
1411 status = p.readInt32(&response_type);
1412 if (DBG) ALOGD("%s: status %d response_type %d", __FUNCTION__, status, response_type);
1413
1414 if (status != NO_ERROR) {
1415 ret = RIL_CLIENT_ERR_IO;
1416 goto EXIT;
1417 }
1418
1419 // FOr unsolicited response.
1420 if (response_type == RESPONSE_UNSOLICITED) {
1421 ret = processUnsolicited(prv, p);
1422 }
1423 // For solicited response.
1424 else if (response_type == RESPONSE_SOLICITED) {
1425 ret = processSolicited(prv, p);
1426 if (ret != RIL_CLIENT_ERR_SUCCESS && prv->err_cb) {
1427 prv->err_cb(prv->err_cb_data, ret);
1428 }
1429 }
1430 else {
1431 ret = RIL_CLIENT_ERR_INVAL;
1432 }
1433
1434EXIT:
1435 release_wake_lock(RIL_CLIENT_WAKE_LOCK);
1436 return ret;
1437}
1438
1439
1440static uint32_t AllocateToken(uint32_t *token_pool) {
1441 int i;
1442
1443 // Token pool is full.
1444 if (*token_pool == 0xFFFFFFFF)
1445 return 0;
1446
1447 for (i = 0; i < 32; i++) {
1448 uint32_t new_token = 0x00000001 << i;
1449
1450 if ((*token_pool & new_token) == 0) {
1451 *token_pool |= new_token;
1452 return new_token;
1453 }
1454 }
1455
1456 return 0;
1457}
1458
1459
1460static void FreeToken(uint32_t *token_pool, uint32_t token) {
1461 *token_pool &= ~token;
1462}
1463
1464
1465static uint8_t IsValidToken(uint32_t *token_pool, uint32_t token) {
1466 if (token == 0)
1467 return 0;
1468
1469 if ((*token_pool & token) == token)
1470 return 1;
1471 else
1472 return 0;
1473}
1474
1475
1476static int RecordReqHistory(RilClientPrv *prv, int token, uint32_t id) {
1477 int i = 0;
1478
1479 if (DBG) ALOGD("[*] %s(): token(%d), ID(%d)\n", __FUNCTION__, token, id);
1480 for (i = 0; i < TOKEN_POOL_SIZE; i++) {
1481 if (prv->history[i].token == 0) {
1482 prv->history[i].token = token;
1483 prv->history[i].id = id;
1484
1485 if (DBG) ALOGD("[*] %s(): token(%d), ID(%d)\n", __FUNCTION__, token, id);
1486
1487 return RIL_CLIENT_ERR_SUCCESS;
1488 }
1489 }
1490
1491 ALOGE("%s: No free record for token %d", __FUNCTION__, token);
1492
1493 return RIL_CLIENT_ERR_RESOURCE;
1494}
1495
1496static void ClearReqHistory(RilClientPrv *prv, int token) {
1497 int i = 0;
1498
1499 if (DBG) ALOGD("[*] %s(): token(%d)\n", __FUNCTION__, token);
1500 for (i = 0; i < TOKEN_POOL_SIZE; i++) {
1501 if (prv->history[i].token == token) {
1502 memset(&(prv->history[i]), 0, sizeof(ReqHistory));
1503 break;
1504 }
1505 }
1506}
1507
1508
1509static RilOnUnsolicited FindUnsolHandler(RilClientPrv *prv, uint32_t id) {
1510 int i;
1511
1512 // Search unsolicited handler table.
1513 for (i = 0; i < REQ_POOL_SIZE; i++) {
1514 if (prv->unsol_handlers[i].id == id)
1515 return prv->unsol_handlers[i].handler;
1516 }
1517
1518 return (RilOnUnsolicited)NULL;
1519}
1520
1521
1522static RilOnComplete FindReqHandler(RilClientPrv *prv, int token, uint32_t *id) {
1523 int i = 0;
1524 int j = 0;
1525
1526 if (DBG) ALOGD("[*] %s(): token(%d)\n", __FUNCTION__, token);
1527
1528 // Search request history.
1529 for (i = 0; i < TOKEN_POOL_SIZE; i++) {
1530 printf("[*] %s(): history_token(%d)\n", __FUNCTION__, prv->history[i].token);
1531 if (prv->history[i].token == token) {
1532 // Search request handler with request ID found.
1533 for (j = 0; j < REQ_POOL_SIZE; j++) {
1534 printf("[*] %s(): token(%d), req_id(%d), history_id(%d)\n", __FUNCTION__, token, prv->history[i].id, prv->history[i].id);
1535 if (prv->req_handlers[j].id == prv->history[i].id) {
1536 *id = prv->req_handlers[j].id;
1537 return prv->req_handlers[j].handler;
1538 }
1539 }
1540 }
1541 }
1542
1543 return NULL;
1544}
1545
1546
1547static void DeallocateToken(uint32_t *token_pool, uint32_t token) {
1548 *token_pool &= !token;
1549}
1550
1551
1552static int blockingWrite(int fd, const void *buffer, size_t len) {
1553 size_t writeOffset = 0;
1554 const uint8_t *toWrite;
1555 ssize_t written = 0;
1556
1557 if (buffer == NULL)
1558 return -1;
1559
1560 toWrite = (const uint8_t *)buffer;
1561
1562 while (writeOffset < len) {
1563 do
1564 {
1565 written = write(fd, toWrite + writeOffset, len - writeOffset);
1566 } while (written < 0 && errno == EINTR);
1567
1568 if (written >= 0) {
1569 writeOffset += written;
1570 }
1571 else {
1572 ALOGE ("RIL Response: unexpected error on write errno:%d", errno);
1573 printf("RIL Response: unexpected error on write errno:%d\n", errno);
1574 close(fd);
1575 return -1;
1576 }
1577 }
1578
1579 return 0;
1580}
1581
1582} // namespace android
1583
1584// end of file
1585