blob: 3cd45479014b8e0f0bbf08a937aeba9273bbdb0c [file] [log] [blame]
codeworkxf1587a32012-08-03 23:32:29 +02001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "SapClient"
18
19#include <binder/Parcel.h>
20#include <telephony/ril.h>
21#include <cutils/record_stream.h>
22
23#include <unistd.h>
24#include <errno.h>
25#include <cutils/sockets.h>
26#include <netinet/in.h>
27#include <sys/types.h>
28#include <string.h>
29#include <fcntl.h>
30#include <utils/Log.h>
Sean hoyt7ef59ce2017-08-23 12:05:55 +000031#include <android/log.h>
codeworkxf1587a32012-08-03 23:32:29 +020032#include <pthread.h>
33#include "secril-client-sap.h"
34#include <hardware_legacy/power.h> // For wakelock
35
36#define RIL_CLIENT_WAKE_LOCK "client-sap-interface"
37
38namespace android {
39
40//---------------------------------------------------------------------------
41// Defines
42//---------------------------------------------------------------------------
43#define DBG 0
44
45#define MULTI_CLIENT_SOCKET_NAME "Multiclient"
46
47#define MAX_COMMAND_BYTES (8 * 1024)
48#define REQ_POOL_SIZE 32
49#define TOKEN_POOL_SIZE 32
50
51// Constants for response types
52#define RESPONSE_SOLICITED 0
53#define RESPONSE_UNSOLICITED 1
54
55#define max(a, b) ((a) > (b) ? (a) : (b))
56
57#define REQ_OEM_HOOK_RAW RIL_REQUEST_OEM_HOOK_RAW
58
59//---------------------------------------------------------------------------
60// Type definitions
61//---------------------------------------------------------------------------
62typedef struct _ReqHistory {
63 int token; // token used for request
64 uint32_t id; // request ID
65} ReqHistory;
66
67typedef struct _ReqRespHandler {
68 uint32_t id; // request ID
69 RilOnComplete handler; // handler function
70} ReqRespHandler;
71
72typedef struct _UnsolHandler {
73 uint32_t id; // unsolicited response ID
74 RilOnUnsolicited handler; // handler function
75} UnsolHandler;
76
77typedef struct _RilClientPrv {
78 HRilClient parent;
79 uint8_t b_connect; // connected to server?
80 int sock; // socket
81 int pipefd[2];
82 fd_set sock_rfds; // for read with select()
83 RecordStream *p_rs;
84 uint32_t token_pool; // each bit in token_pool used for token.
85 // so, pool size is 32.
86 pthread_t tid_reader; // socket reader thread id
87 ReqHistory history[TOKEN_POOL_SIZE]; // request history
88 ReqRespHandler req_handlers[REQ_POOL_SIZE]; // request response handler list
89 UnsolHandler unsol_handlers[REQ_POOL_SIZE]; // unsolicited response handler list
90 RilOnError err_cb; // error callback
91 void *err_cb_data; // error callback data
92 uint8_t b_del_handler;
93} RilClientPrv;
94
95
96//---------------------------------------------------------------------------
97// Local static function prototypes
98//---------------------------------------------------------------------------
99static void * RxReaderFunc(void *param);
100static int processRxBuffer(RilClientPrv *prv, void *buffer, size_t buflen);
101static uint32_t AllocateToken(uint32_t *token_pool);
102static void FreeToken(uint32_t *token_pool, uint32_t token);
103static uint8_t IsValidToken(uint32_t *token_pool, uint32_t token);
104static int blockingWrite(int fd, const void *buffer, size_t len);
105static int RecordReqHistory(RilClientPrv *prv, int token, uint32_t id);
106static void ClearReqHistory(RilClientPrv *prv, int token);
107static RilOnComplete FindReqHandler(RilClientPrv *prv, int token, uint32_t *id);
108static RilOnUnsolicited FindUnsolHandler(RilClientPrv *prv, uint32_t id);
109static int SendOemRequestHookRaw(HRilClient client, int req_id, char *data, size_t len);
110
111/**
112 * @fn int RegisterUnsolicitedHandler(HRilClient client, uint32_t id, RilOnUnsolicited handler)
113 *
114 * @params client: Client handle.
115 * id: Unsolicited response ID to which handler is registered.
116 * handler: Unsolicited handler. NULL for deregistration.
117 *
118 * @return 0 on success or error code.
119 */
120extern "C"
121int RegisterUnsolicitedHandler(HRilClient client, uint32_t id, RilOnUnsolicited handler) {
122 RilClientPrv *client_prv;
123 int match_slot = -1;
124 int first_empty_slot = -1;
125 int i;
126
127 if (client == NULL || client->prv == NULL)
128 return RIL_CLIENT_ERR_INVAL;
129
130 client_prv = (RilClientPrv *)(client->prv);
131
132 for (i = 0; i < REQ_POOL_SIZE; i++) {
133 // Check if there is matched handler.
134 if (id == client_prv->unsol_handlers[i].id) {
135 match_slot = i;
136 }
137 // Find first empty handler slot.
138 if (first_empty_slot == -1 && client_prv->unsol_handlers[i].id == 0) {
139 first_empty_slot = i;
140 }
141 }
142
143 if (handler == NULL) { // Unregister.
144 if (match_slot >= 0) {
145 memset(&(client_prv->unsol_handlers[match_slot]), 0, sizeof(UnsolHandler));
146 return RIL_CLIENT_ERR_SUCCESS;
147 }
148 else {
149 return RIL_CLIENT_ERR_SUCCESS;
150 }
151 }
152 else {// Register.
153 if (match_slot >= 0) {
154 client_prv->unsol_handlers[match_slot].handler = handler; // Just update.
155 }
156 else if (first_empty_slot >= 0) {
157 client_prv->unsol_handlers[first_empty_slot].id = id;
158 client_prv->unsol_handlers[first_empty_slot].handler = handler;
159 }
160 else {
161 return RIL_CLIENT_ERR_RESOURCE;
162 }
163 }
164
165 return RIL_CLIENT_ERR_SUCCESS;
166}
167
168
169/**
170 * @fn int RegisterRequestCompleteHandler(HRilClient client, uint32_t id, RilOnComplete handler)
171 *
172 * @params client: Client handle.
173 * id: Request ID to which handler is registered.
174 * handler: Request complete handler. NULL for deregistration.
175 *
176 * @return 0 on success or error code.
177 */
178extern "C"
179int RegisterRequestCompleteHandler(HRilClient client, uint32_t id, RilOnComplete handler) {
180 RilClientPrv *client_prv;
181 int match_slot = -1;
182 int first_empty_slot = -1;
183 int i;
184
185 if (client == NULL || client->prv == NULL)
186 return RIL_CLIENT_ERR_INVAL;
187
188 client_prv = (RilClientPrv *)(client->prv);
189
190 for (i = 0; i < REQ_POOL_SIZE; i++) {
191 // Check if there is matched handler.
192 if (id == client_prv->req_handlers[i].id) {
193 match_slot = i;
194 }
195 // Find first empty handler slot.
196 if (first_empty_slot == -1 && client_prv->req_handlers[i].id == 0) {
197 first_empty_slot = i;
198 }
199 }
200
201 if (handler == NULL) { // Unregister.
202 if (match_slot >= 0) {
203 memset(&(client_prv->req_handlers[match_slot]), 0, sizeof(ReqRespHandler));
204 return RIL_CLIENT_ERR_SUCCESS;
205 }
206 else {
207 return RIL_CLIENT_ERR_SUCCESS;
208 }
209 }
210 else { // Register.
211 if (match_slot >= 0) {
212 client_prv->req_handlers[match_slot].handler = handler; // Just update.
213 }
214 else if (first_empty_slot >= 0) {
215 client_prv->req_handlers[first_empty_slot].id = id;
216 client_prv->req_handlers[first_empty_slot].handler = handler;
217 }
218 else {
219 return RIL_CLIENT_ERR_RESOURCE;
220 }
221 }
222
223 return RIL_CLIENT_ERR_SUCCESS;
224}
225
226
227/**
228 * @fn int RegisterErrorCallback(HRilClient client, RilOnError cb, void *data)
229 *
230 * @params client: Client handle.
231 * cb: Error callback. NULL for unregistration.
232 * data: Callback data.
233 *
234 * @return 0 for success or error code.
235 */
236extern "C"
237int RegisterErrorCallback(HRilClient client, RilOnError cb, void *data) {
238 RilClientPrv *client_prv;
239
240 if (client == NULL || client->prv == NULL)
241 return RIL_CLIENT_ERR_INVAL;
242
243 client_prv = (RilClientPrv *)(client->prv);
244
245 client_prv->err_cb = cb;
246 client_prv->err_cb_data = data;
247
248 return RIL_CLIENT_ERR_SUCCESS;
249}
250
251
252/**
253 * @fn HRilClient OpenClient_RILD(void)
254 *
255 * @params None.
256 *
257 * @return Client handle, NULL on error.
258 */
259extern "C"
260HRilClient OpenClient_RILD(void) {
261 HRilClient client = (HRilClient)malloc(sizeof(struct RilClient));
262 if (client == NULL)
263 return NULL;
264
265 client->prv = (RilClientPrv *)malloc(sizeof(RilClientPrv));
266 if (client->prv == NULL) {
267 free(client);
268 return NULL;
269 }
270
271 memset(client->prv, 0, sizeof(RilClientPrv));
272
273 ((RilClientPrv *)(client->prv))->parent = client;
274 ((RilClientPrv *)(client->prv))->sock = -1;
275
276 return client;
277}
278
279
280/**
281 * @fn int Connect_RILD(void)
282 *
283 * @params client: Client handle.
284 *
285 * @return 0, or error code.
286 */
287extern "C"
288int Connect_RILD(HRilClient client) {
289 RilClientPrv *client_prv;
290
291 if (client == NULL || client->prv == NULL) {
292 ALOGE("%s: Invalid client %p", __FUNCTION__, client);
293 return RIL_CLIENT_ERR_INVAL;
294 }
295
296 client_prv = (RilClientPrv *)(client->prv);
297
298 // Open client socket and connect to server.
299 client_prv->sock = socket_local_client(MULTI_CLIENT_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM );
300
301 if (client_prv->sock < 0) {
302 ALOGE("%s: Connecting failed. %s(%d)", __FUNCTION__, strerror(errno), errno);
303 return RIL_CLIENT_ERR_CONNECT;
304 }
305
306 client_prv->b_connect = 1;
307
308 if (fcntl(client_prv->sock, F_SETFL, O_NONBLOCK) < 0) {
309 close(client_prv->sock);
310 return RIL_CLIENT_ERR_IO;
311 }
312
313 client_prv->p_rs = record_stream_new(client_prv->sock, MAX_COMMAND_BYTES);
314
315 if (pipe(client_prv->pipefd) < 0) {
316 close(client_prv->sock);
317 ALOGE("%s: Creating command pipe failed. %s(%d)", __FUNCTION__, strerror(errno), errno);
318 return RIL_CLIENT_ERR_IO;
319 }
320
321 if (fcntl(client_prv->pipefd[0], F_SETFL, O_NONBLOCK) < 0) {
322 close(client_prv->sock);
323 close(client_prv->pipefd[0]);
324 close(client_prv->pipefd[1]);
325 return RIL_CLIENT_ERR_IO;
326 }
327
328 // Start socket read thread.
329 if (pthread_create(&(client_prv->tid_reader), NULL, RxReaderFunc, (void *)client_prv) != 0) {
330 close(client_prv->sock);
331 close(client_prv->pipefd[0]);
332 close(client_prv->pipefd[1]);
333
334 memset(client_prv, 0, sizeof(RilClientPrv));
335 client_prv->sock = -1;
336 ALOGE("%s: Can't create Reader thread. %s(%d)", __FUNCTION__, strerror(errno), errno);
337 return RIL_CLIENT_ERR_CONNECT;
338 }
339
340 return RIL_CLIENT_ERR_SUCCESS;
341}
342
343/**
344 * @fn int Disconnect_RILD(HRilClient client)
345 *
346 * @params client: Client handle.
347 *
348 * @return 0 on success, or error code.
349 */
350extern "C"
351int Disconnect_RILD(HRilClient client) {
352 RilClientPrv *client_prv;
353 int ret = 0;
354
355 if (client == NULL || client->prv == NULL) {
356 ALOGE("%s: invalid client %p", __FUNCTION__, client);
357 return RIL_CLIENT_ERR_INVAL;
358 }
359
360 client_prv = (RilClientPrv *)(client->prv);
361
362 if (client_prv->sock == -1)
363 return RIL_CLIENT_ERR_SUCCESS;
364
365 ALOGD("[*] %s(): sock=%d\n", __FUNCTION__, client_prv->sock);
366
367 if (client_prv->sock > 0) {
368 do {
369 ret = write(client_prv->pipefd[1], "close", strlen("close"));
370 } while (ret < 0 && errno == EINTR);
371 }
372
373 client_prv->b_connect = 0;
374
375 pthread_join(client_prv->tid_reader, NULL);
376
377 return RIL_CLIENT_ERR_SUCCESS;
378}
379
380
381/**
382 * @fn int CloseClient_RILD(HRilClient client)
383 *
384 * @params client: Client handle.
385 *
386 * @return 0 on success, or error code.
387 */
388extern "C"
389int CloseClient_RILD(HRilClient client) {
390 if (client == NULL || client->prv == NULL) {
391 ALOGE("%s: invalid client %p", __FUNCTION__, client);
392 return RIL_CLIENT_ERR_INVAL;
393 }
394
395 Disconnect_RILD(client);
396
397 free(client->prv);
398 free(client);
399
400 return RIL_CLIENT_ERR_SUCCESS;
401}
402
403/**
404 * @fn int InvokeOemRequestHookRaw(HRilClient client, char *data, size_t len)
405 *
406 * @params client: Client handle.
407 * data: Request data.
408 * len: Request data length.
409 *
410 * @return 0 for success or error code. On receiving RIL_CLIENT_ERR_AGAIN,
411 * caller should retry.
412 */
413extern "C"
414int InvokeOemRequestHookRaw(HRilClient client, char *data, size_t len) {
415 RilClientPrv *client_prv;
416
417 if (client == NULL || client->prv == NULL) {
418 ALOGE("%s: Invalid client %p", __FUNCTION__, client);
419 return RIL_CLIENT_ERR_INVAL;
420 }
421
422 client_prv = (RilClientPrv *)(client->prv);
423
424 if (client_prv->sock < 0 ) {
425 ALOGE("%s: Not connected.", __FUNCTION__);
426 return RIL_CLIENT_ERR_CONNECT;
427 }
428
429 return SendOemRequestHookRaw(client, REQ_OEM_HOOK_RAW, data, len);
430}
431
432
433static int SendOemRequestHookRaw(HRilClient client, int req_id, char *data, size_t len) {
434 int token = 0;
435 int ret = 0;
436 uint32_t header = 0;
437 android::Parcel p;
438 RilClientPrv *client_prv;
codeworkxf1587a32012-08-03 23:32:29 +0200439
440 client_prv = (RilClientPrv *)(client->prv);
441
442 // Allocate a token.
443 token = AllocateToken(&(client_prv->token_pool));
444 if (token == 0) {
445 ALOGE("%s: No token.", __FUNCTION__);
446 return RIL_CLIENT_ERR_AGAIN;
447 }
448
449 // Record token for the request sent.
450 if (RecordReqHistory(client_prv, token, req_id) != RIL_CLIENT_ERR_SUCCESS) {
451 goto error;
452 }
453
454 // Make OEM request data.
455 p.writeInt32(RIL_REQUEST_OEM_HOOK_RAW);
456 p.writeInt32(token);
457 p.writeInt32(len);
458 p.write((void *)data, len);
459
460 // DO TX: header(size).
461 header = htonl(p.dataSize());
462
463 if (DBG) ALOGD("%s(): token = %d\n", __FUNCTION__, token);
464
465 ret = blockingWrite(client_prv->sock, (void *)&header, sizeof(header));
466 if (ret < 0) {
467 ALOGE("%s: send request header failed. (%d)", __FUNCTION__, ret);
468 goto error;
469 }
470
471 // Do TX: response data.
472 ret = blockingWrite(client_prv->sock, p.data(), p.dataSize());
473 if (ret < 0) {
474 ALOGE("%s: send request data failed. (%d)", __FUNCTION__, ret);
475 goto error;
476 }
477
478 return RIL_CLIENT_ERR_SUCCESS;
479
480error:
481 FreeToken(&(client_prv->token_pool), token);
482 ClearReqHistory(client_prv, token);
483
484 return RIL_CLIENT_ERR_UNKNOWN;
485}
486
487static void * RxReaderFunc(void *param) {
488 RilClientPrv *client_prv = (RilClientPrv *)param;
489 int maxfd = 0;
codeworkxf1587a32012-08-03 23:32:29 +0200490 void *p_record = NULL;
491 size_t recordlen = 0;
492 int ret = 0;
493 int n;
494
495 if (client_prv == NULL)
496 return NULL;
497
498 maxfd = max(client_prv->sock, client_prv->pipefd[0]) + 1;
499
500 ALOGD("[*] %s() b_connect=%d, maxfd=%d\n", __FUNCTION__, client_prv->b_connect, maxfd);
501 while (client_prv->b_connect) {
502 FD_ZERO(&(client_prv->sock_rfds));
503
504 FD_SET(client_prv->sock, &(client_prv->sock_rfds));
505 FD_SET(client_prv->pipefd[0], &(client_prv->sock_rfds));
506
507 if (DBG) ALOGD("[*] %s() b_connect=%d\n", __FUNCTION__, client_prv->b_connect);
508 if (select(maxfd, &(client_prv->sock_rfds), NULL, NULL, NULL) > 0) {
509 if (FD_ISSET(client_prv->sock, &(client_prv->sock_rfds))) {
510 // Read incoming data
511 for (;;) {
512 // loop until EAGAIN/EINTR, end of stream, or other error
513 ret = record_stream_get_next(client_prv->p_rs, &p_record, &recordlen);
514 if (ret == 0 && p_record == NULL) { // end-of-stream
515 break;
516 }
517 else if (ret < 0) {
518 break;
519 }
520 else if (ret == 0) { // && p_record != NULL
521 n = processRxBuffer(client_prv, p_record, recordlen);
522 if (n != RIL_CLIENT_ERR_SUCCESS) {
523 ALOGE("%s: processRXBuffer returns %d", __FUNCTION__, n);
524 }
525 }
526 else {
527 ALOGD("[*] %s()\n", __FUNCTION__);
528 }
529 }
530
531 if (ret == 0 || !(errno == EAGAIN || errno == EINTR)) {
532 // fatal error or end-of-stream
533 if (client_prv->sock > 0) {
534 close(client_prv->sock);
535 client_prv->sock = -1;
536 client_prv->b_connect = 0;
537 }
538
539 if (client_prv->p_rs)
540 record_stream_free(client_prv->p_rs);
541
542 // EOS
543 if (client_prv->err_cb) {
544 client_prv->err_cb(client_prv->err_cb_data, RIL_CLIENT_ERR_CONNECT);
545 return NULL;
546 }
547
548 break;
549 }
550 }
551 if (FD_ISSET(client_prv->pipefd[0], &(client_prv->sock_rfds))) {
552 char end_cmd[10];
553
554 if (DBG) ALOGD("%s(): close\n", __FUNCTION__);
555
556 if (read(client_prv->pipefd[0], end_cmd, sizeof(end_cmd)) > 0) {
557 close(client_prv->sock);
558 close(client_prv->pipefd[0]);
559 close(client_prv->pipefd[1]);
560
561 client_prv->sock = -1;
562 client_prv->b_connect = 0;
563 }
564 }
565 }
566 }
567
568 return NULL;
569}
570
571
572static int processUnsolicited(RilClientPrv *prv, Parcel &p) {
573 int32_t resp_id, len;
574 status_t status;
575 const void *data = NULL;
576 RilOnUnsolicited unsol_func = NULL;
577
578 status = p.readInt32(&resp_id);
579 if (status != NO_ERROR) {
580 ALOGE("%s: read resp_id failed.", __FUNCTION__);
581 return RIL_CLIENT_ERR_IO;
582 }
583
584 status = p.readInt32(&len);
585 if (status != NO_ERROR) {
586 //LOGE("%s: read length failed. assume zero length.", __FUNCTION__);
587 len = 0;
588 }
589
590 ALOGD("%s(): resp_id (%d), len(%d)\n", __FUNCTION__, resp_id, len);
591
592 if (len)
593 data = p.readInplace(len);
594
595 // Find unsolicited response handler.
596 unsol_func = FindUnsolHandler(prv, (uint32_t)resp_id);
597 if (unsol_func) {
598 unsol_func(prv->parent, data, len);
599 }
600
601 return RIL_CLIENT_ERR_SUCCESS;
602}
603
604
605static int processSolicited(RilClientPrv *prv, Parcel &p) {
606 int32_t token, err, len;
607 status_t status;
608 const void *data = NULL;
609 RilOnComplete req_func = NULL;
610 int ret = RIL_CLIENT_ERR_SUCCESS;
611 uint32_t req_id = 0;
612
613 if (DBG) ALOGD("%s()", __FUNCTION__);
614
615 status = p.readInt32(&token);
616 if (status != NO_ERROR) {
617 ALOGE("%s: Read token fail. Status %d\n", __FUNCTION__, status);
618 return RIL_CLIENT_ERR_IO;
619 }
620
621 if (IsValidToken(&(prv->token_pool), token) == 0) {
622 ALOGE("%s: Invalid Token", __FUNCTION__);
623 return RIL_CLIENT_ERR_INVAL; // Invalid token.
624 }
625
626 status = p.readInt32(&err);
627 if (status != NO_ERROR) {
628 ALOGE("%s: Read err fail. Status %d\n", __FUNCTION__, status);
629 ret = RIL_CLIENT_ERR_IO;
630 goto error;
631 }
632
633 // Don't go further for error response.
634 if (err != RIL_CLIENT_ERR_SUCCESS) {
635 ALOGE("%s: Error %d\n", __FUNCTION__, err);
636 if (prv->err_cb)
637 prv->err_cb(prv->err_cb_data, err);
638 ret = RIL_CLIENT_ERR_SUCCESS;
639 goto error;
640 }
641
642 status = p.readInt32(&len);
643 if (status != NO_ERROR) {
644 /* no length field */
645 len = 0;
646 }
647
648 if (len)
649 data = p.readInplace(len);
650
651 // Find request handler for the token.
652 // First, FindReqHandler() searches request history with the token
653 // and finds out a request ID. Then, it search request handler table
654 // with the request ID.
655 req_func = FindReqHandler(prv, token, &req_id);
656 if (req_func)
657 {
658 if (DBG) ALOGD("[*] Call handler");
659 req_func(prv->parent, data, len);
660
661 if(prv->b_del_handler) {
662 prv->b_del_handler = 0;
663 RegisterRequestCompleteHandler(prv->parent, req_id, NULL);
664 }
665 } else {
666 if (DBG) ALOGD("%s: No handler for token %d\n", __FUNCTION__, token);
667 }
668
669error:
670 FreeToken(&(prv->token_pool), token);
671 ClearReqHistory(prv, token);
672 return ret;
673}
674
675
676static int processRxBuffer(RilClientPrv *prv, void *buffer, size_t buflen) {
677 Parcel p;
678 int32_t response_type;
679 status_t status;
680 int ret = RIL_CLIENT_ERR_SUCCESS;
681
682 acquire_wake_lock(PARTIAL_WAKE_LOCK, RIL_CLIENT_WAKE_LOCK);
683
684 p.setData((uint8_t *)buffer, buflen);
685
686 status = p.readInt32(&response_type);
687 if (DBG) ALOGD("%s: status %d response_type %d", __FUNCTION__, status, response_type);
688
689 if (status != NO_ERROR) {
690 ret = RIL_CLIENT_ERR_IO;
691 goto EXIT;
692 }
693
694 // FOr unsolicited response.
695 if (response_type == RESPONSE_UNSOLICITED) {
696 ret = processUnsolicited(prv, p);
697 }
698 // For solicited response.
699 else if (response_type == RESPONSE_SOLICITED) {
700 ret = processSolicited(prv, p);
701 if (ret != RIL_CLIENT_ERR_SUCCESS && prv->err_cb) {
702 prv->err_cb(prv->err_cb_data, ret);
703 }
704 }
705 else {
706 ret = RIL_CLIENT_ERR_INVAL;
707 }
708
709EXIT:
710 release_wake_lock(RIL_CLIENT_WAKE_LOCK);
711 return ret;
712}
713
714
715static uint32_t AllocateToken(uint32_t *token_pool) {
716 int i;
717
718 // Token pool is full.
719 if (*token_pool == 0xFFFFFFFF)
720 return 0;
721
722 for (i = 0; i < 32; i++) {
723 uint32_t new_token = 0x00000001 << i;
724
725 if ((*token_pool & new_token) == 0) {
726 *token_pool |= new_token;
727 return new_token;
728 }
729 }
730
731 return 0;
732}
733
734
735static void FreeToken(uint32_t *token_pool, uint32_t token) {
736 *token_pool &= ~token;
737}
738
739
740static uint8_t IsValidToken(uint32_t *token_pool, uint32_t token) {
741 if (token == 0)
742 return 0;
743
744 if ((*token_pool & token) == token)
745 return 1;
746 else
747 return 0;
748}
749
750
751static int RecordReqHistory(RilClientPrv *prv, int token, uint32_t id) {
752 int i = 0;
753
754 if (DBG) ALOGD("[*] %s(): token(%d), ID(%d)\n", __FUNCTION__, token, id);
755 for (i = 0; i < TOKEN_POOL_SIZE; i++) {
756 if (prv->history[i].token == 0) {
757 prv->history[i].token = token;
758 prv->history[i].id = id;
759
760 if (DBG) ALOGD("[*] %s(): token(%d), ID(%d)\n", __FUNCTION__, token, id);
761
762 return RIL_CLIENT_ERR_SUCCESS;
763 }
764 }
765
766 ALOGE("%s: No free record for token %d", __FUNCTION__, token);
767
768 return RIL_CLIENT_ERR_RESOURCE;
769}
770
771static void ClearReqHistory(RilClientPrv *prv, int token) {
772 int i = 0;
773
774 if (DBG) ALOGD("[*] %s(): token(%d)\n", __FUNCTION__, token);
775 for (i = 0; i < TOKEN_POOL_SIZE; i++) {
776 if (prv->history[i].token == token) {
777 memset(&(prv->history[i]), 0, sizeof(ReqHistory));
778 break;
779 }
780 }
781}
782
783
784static RilOnUnsolicited FindUnsolHandler(RilClientPrv *prv, uint32_t id) {
785 int i;
786
787 // Search unsolicited handler table.
788 for (i = 0; i < REQ_POOL_SIZE; i++) {
789 if (prv->unsol_handlers[i].id == id)
790 return prv->unsol_handlers[i].handler;
791 }
792
793 return (RilOnUnsolicited)NULL;
794}
795
796
797static RilOnComplete FindReqHandler(RilClientPrv *prv, int token, uint32_t *id) {
798 int i = 0;
799 int j = 0;
800
801 if (DBG) ALOGD("[*] %s(): token(%d)\n", __FUNCTION__, token);
802
803 // Search request history.
804 for (i = 0; i < TOKEN_POOL_SIZE; i++) {
805 ALOGD("[*] %s(): history_token(%d)\n", __FUNCTION__, prv->history[i].token);
806 if (prv->history[i].token == token) {
807 // Search request handler with request ID found.
808 for (j = 0; j < REQ_POOL_SIZE; j++) {
809 ALOGD("[*] %s(): token(%d), req_id(%d), history_id(%d)\n", __FUNCTION__, token, prv->history[i].id, prv->history[i].id);
810 if (prv->req_handlers[j].id == prv->history[i].id) {
811 *id = prv->req_handlers[j].id;
812 return prv->req_handlers[j].handler;
813 }
814 }
815 }
816 }
817
818 return NULL;
819}
820
821
822static int blockingWrite(int fd, const void *buffer, size_t len) {
823 size_t writeOffset = 0;
824 const uint8_t *toWrite;
825 ssize_t written = 0;
826
827 if (buffer == NULL)
828 return -1;
829
830 toWrite = (const uint8_t *)buffer;
831
832 while (writeOffset < len) {
833 do
834 {
835 written = write(fd, toWrite + writeOffset, len - writeOffset);
836 } while (written < 0 && errno == EINTR);
837
838 if (written >= 0) {
839 writeOffset += written;
840 }
841 else {
842 ALOGE ("RIL Response: unexpected error on write errno:%d", errno);
843 close(fd);
844 return -1;
845 }
846 }
847
848 return 0;
849}
850
851} // namespace android
852
853// end of file
854