blob: 1182b907a97def131ebf1c428eff6bb6ad331ce4 [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;
439 int maxfd = -1;
440
441 client_prv = (RilClientPrv *)(client->prv);
442
443 // Allocate a token.
444 token = AllocateToken(&(client_prv->token_pool));
445 if (token == 0) {
446 ALOGE("%s: No token.", __FUNCTION__);
447 return RIL_CLIENT_ERR_AGAIN;
448 }
449
450 // Record token for the request sent.
451 if (RecordReqHistory(client_prv, token, req_id) != RIL_CLIENT_ERR_SUCCESS) {
452 goto error;
453 }
454
455 // Make OEM request data.
456 p.writeInt32(RIL_REQUEST_OEM_HOOK_RAW);
457 p.writeInt32(token);
458 p.writeInt32(len);
459 p.write((void *)data, len);
460
461 // DO TX: header(size).
462 header = htonl(p.dataSize());
463
464 if (DBG) ALOGD("%s(): token = %d\n", __FUNCTION__, token);
465
466 ret = blockingWrite(client_prv->sock, (void *)&header, sizeof(header));
467 if (ret < 0) {
468 ALOGE("%s: send request header failed. (%d)", __FUNCTION__, ret);
469 goto error;
470 }
471
472 // Do TX: response data.
473 ret = blockingWrite(client_prv->sock, p.data(), p.dataSize());
474 if (ret < 0) {
475 ALOGE("%s: send request data failed. (%d)", __FUNCTION__, ret);
476 goto error;
477 }
478
479 return RIL_CLIENT_ERR_SUCCESS;
480
481error:
482 FreeToken(&(client_prv->token_pool), token);
483 ClearReqHistory(client_prv, token);
484
485 return RIL_CLIENT_ERR_UNKNOWN;
486}
487
488static void * RxReaderFunc(void *param) {
489 RilClientPrv *client_prv = (RilClientPrv *)param;
490 int maxfd = 0;
491 int token = 0;
492 void *p_record = NULL;
493 size_t recordlen = 0;
494 int ret = 0;
495 int n;
496
497 if (client_prv == NULL)
498 return NULL;
499
500 maxfd = max(client_prv->sock, client_prv->pipefd[0]) + 1;
501
502 ALOGD("[*] %s() b_connect=%d, maxfd=%d\n", __FUNCTION__, client_prv->b_connect, maxfd);
503 while (client_prv->b_connect) {
504 FD_ZERO(&(client_prv->sock_rfds));
505
506 FD_SET(client_prv->sock, &(client_prv->sock_rfds));
507 FD_SET(client_prv->pipefd[0], &(client_prv->sock_rfds));
508
509 if (DBG) ALOGD("[*] %s() b_connect=%d\n", __FUNCTION__, client_prv->b_connect);
510 if (select(maxfd, &(client_prv->sock_rfds), NULL, NULL, NULL) > 0) {
511 if (FD_ISSET(client_prv->sock, &(client_prv->sock_rfds))) {
512 // Read incoming data
513 for (;;) {
514 // loop until EAGAIN/EINTR, end of stream, or other error
515 ret = record_stream_get_next(client_prv->p_rs, &p_record, &recordlen);
516 if (ret == 0 && p_record == NULL) { // end-of-stream
517 break;
518 }
519 else if (ret < 0) {
520 break;
521 }
522 else if (ret == 0) { // && p_record != NULL
523 n = processRxBuffer(client_prv, p_record, recordlen);
524 if (n != RIL_CLIENT_ERR_SUCCESS) {
525 ALOGE("%s: processRXBuffer returns %d", __FUNCTION__, n);
526 }
527 }
528 else {
529 ALOGD("[*] %s()\n", __FUNCTION__);
530 }
531 }
532
533 if (ret == 0 || !(errno == EAGAIN || errno == EINTR)) {
534 // fatal error or end-of-stream
535 if (client_prv->sock > 0) {
536 close(client_prv->sock);
537 client_prv->sock = -1;
538 client_prv->b_connect = 0;
539 }
540
541 if (client_prv->p_rs)
542 record_stream_free(client_prv->p_rs);
543
544 // EOS
545 if (client_prv->err_cb) {
546 client_prv->err_cb(client_prv->err_cb_data, RIL_CLIENT_ERR_CONNECT);
547 return NULL;
548 }
549
550 break;
551 }
552 }
553 if (FD_ISSET(client_prv->pipefd[0], &(client_prv->sock_rfds))) {
554 char end_cmd[10];
555
556 if (DBG) ALOGD("%s(): close\n", __FUNCTION__);
557
558 if (read(client_prv->pipefd[0], end_cmd, sizeof(end_cmd)) > 0) {
559 close(client_prv->sock);
560 close(client_prv->pipefd[0]);
561 close(client_prv->pipefd[1]);
562
563 client_prv->sock = -1;
564 client_prv->b_connect = 0;
565 }
566 }
567 }
568 }
569
570 return NULL;
571}
572
573
574static int processUnsolicited(RilClientPrv *prv, Parcel &p) {
575 int32_t resp_id, len;
576 status_t status;
577 const void *data = NULL;
578 RilOnUnsolicited unsol_func = NULL;
579
580 status = p.readInt32(&resp_id);
581 if (status != NO_ERROR) {
582 ALOGE("%s: read resp_id failed.", __FUNCTION__);
583 return RIL_CLIENT_ERR_IO;
584 }
585
586 status = p.readInt32(&len);
587 if (status != NO_ERROR) {
588 //LOGE("%s: read length failed. assume zero length.", __FUNCTION__);
589 len = 0;
590 }
591
592 ALOGD("%s(): resp_id (%d), len(%d)\n", __FUNCTION__, resp_id, len);
593
594 if (len)
595 data = p.readInplace(len);
596
597 // Find unsolicited response handler.
598 unsol_func = FindUnsolHandler(prv, (uint32_t)resp_id);
599 if (unsol_func) {
600 unsol_func(prv->parent, data, len);
601 }
602
603 return RIL_CLIENT_ERR_SUCCESS;
604}
605
606
607static int processSolicited(RilClientPrv *prv, Parcel &p) {
608 int32_t token, err, len;
609 status_t status;
610 const void *data = NULL;
611 RilOnComplete req_func = NULL;
612 int ret = RIL_CLIENT_ERR_SUCCESS;
613 uint32_t req_id = 0;
614
615 if (DBG) ALOGD("%s()", __FUNCTION__);
616
617 status = p.readInt32(&token);
618 if (status != NO_ERROR) {
619 ALOGE("%s: Read token fail. Status %d\n", __FUNCTION__, status);
620 return RIL_CLIENT_ERR_IO;
621 }
622
623 if (IsValidToken(&(prv->token_pool), token) == 0) {
624 ALOGE("%s: Invalid Token", __FUNCTION__);
625 return RIL_CLIENT_ERR_INVAL; // Invalid token.
626 }
627
628 status = p.readInt32(&err);
629 if (status != NO_ERROR) {
630 ALOGE("%s: Read err fail. Status %d\n", __FUNCTION__, status);
631 ret = RIL_CLIENT_ERR_IO;
632 goto error;
633 }
634
635 // Don't go further for error response.
636 if (err != RIL_CLIENT_ERR_SUCCESS) {
637 ALOGE("%s: Error %d\n", __FUNCTION__, err);
638 if (prv->err_cb)
639 prv->err_cb(prv->err_cb_data, err);
640 ret = RIL_CLIENT_ERR_SUCCESS;
641 goto error;
642 }
643
644 status = p.readInt32(&len);
645 if (status != NO_ERROR) {
646 /* no length field */
647 len = 0;
648 }
649
650 if (len)
651 data = p.readInplace(len);
652
653 // Find request handler for the token.
654 // First, FindReqHandler() searches request history with the token
655 // and finds out a request ID. Then, it search request handler table
656 // with the request ID.
657 req_func = FindReqHandler(prv, token, &req_id);
658 if (req_func)
659 {
660 if (DBG) ALOGD("[*] Call handler");
661 req_func(prv->parent, data, len);
662
663 if(prv->b_del_handler) {
664 prv->b_del_handler = 0;
665 RegisterRequestCompleteHandler(prv->parent, req_id, NULL);
666 }
667 } else {
668 if (DBG) ALOGD("%s: No handler for token %d\n", __FUNCTION__, token);
669 }
670
671error:
672 FreeToken(&(prv->token_pool), token);
673 ClearReqHistory(prv, token);
674 return ret;
675}
676
677
678static int processRxBuffer(RilClientPrv *prv, void *buffer, size_t buflen) {
679 Parcel p;
680 int32_t response_type;
681 status_t status;
682 int ret = RIL_CLIENT_ERR_SUCCESS;
683
684 acquire_wake_lock(PARTIAL_WAKE_LOCK, RIL_CLIENT_WAKE_LOCK);
685
686 p.setData((uint8_t *)buffer, buflen);
687
688 status = p.readInt32(&response_type);
689 if (DBG) ALOGD("%s: status %d response_type %d", __FUNCTION__, status, response_type);
690
691 if (status != NO_ERROR) {
692 ret = RIL_CLIENT_ERR_IO;
693 goto EXIT;
694 }
695
696 // FOr unsolicited response.
697 if (response_type == RESPONSE_UNSOLICITED) {
698 ret = processUnsolicited(prv, p);
699 }
700 // For solicited response.
701 else if (response_type == RESPONSE_SOLICITED) {
702 ret = processSolicited(prv, p);
703 if (ret != RIL_CLIENT_ERR_SUCCESS && prv->err_cb) {
704 prv->err_cb(prv->err_cb_data, ret);
705 }
706 }
707 else {
708 ret = RIL_CLIENT_ERR_INVAL;
709 }
710
711EXIT:
712 release_wake_lock(RIL_CLIENT_WAKE_LOCK);
713 return ret;
714}
715
716
717static uint32_t AllocateToken(uint32_t *token_pool) {
718 int i;
719
720 // Token pool is full.
721 if (*token_pool == 0xFFFFFFFF)
722 return 0;
723
724 for (i = 0; i < 32; i++) {
725 uint32_t new_token = 0x00000001 << i;
726
727 if ((*token_pool & new_token) == 0) {
728 *token_pool |= new_token;
729 return new_token;
730 }
731 }
732
733 return 0;
734}
735
736
737static void FreeToken(uint32_t *token_pool, uint32_t token) {
738 *token_pool &= ~token;
739}
740
741
742static uint8_t IsValidToken(uint32_t *token_pool, uint32_t token) {
743 if (token == 0)
744 return 0;
745
746 if ((*token_pool & token) == token)
747 return 1;
748 else
749 return 0;
750}
751
752
753static int RecordReqHistory(RilClientPrv *prv, int token, uint32_t id) {
754 int i = 0;
755
756 if (DBG) ALOGD("[*] %s(): token(%d), ID(%d)\n", __FUNCTION__, token, id);
757 for (i = 0; i < TOKEN_POOL_SIZE; i++) {
758 if (prv->history[i].token == 0) {
759 prv->history[i].token = token;
760 prv->history[i].id = id;
761
762 if (DBG) ALOGD("[*] %s(): token(%d), ID(%d)\n", __FUNCTION__, token, id);
763
764 return RIL_CLIENT_ERR_SUCCESS;
765 }
766 }
767
768 ALOGE("%s: No free record for token %d", __FUNCTION__, token);
769
770 return RIL_CLIENT_ERR_RESOURCE;
771}
772
773static void ClearReqHistory(RilClientPrv *prv, int token) {
774 int i = 0;
775
776 if (DBG) ALOGD("[*] %s(): token(%d)\n", __FUNCTION__, token);
777 for (i = 0; i < TOKEN_POOL_SIZE; i++) {
778 if (prv->history[i].token == token) {
779 memset(&(prv->history[i]), 0, sizeof(ReqHistory));
780 break;
781 }
782 }
783}
784
785
786static RilOnUnsolicited FindUnsolHandler(RilClientPrv *prv, uint32_t id) {
787 int i;
788
789 // Search unsolicited handler table.
790 for (i = 0; i < REQ_POOL_SIZE; i++) {
791 if (prv->unsol_handlers[i].id == id)
792 return prv->unsol_handlers[i].handler;
793 }
794
795 return (RilOnUnsolicited)NULL;
796}
797
798
799static RilOnComplete FindReqHandler(RilClientPrv *prv, int token, uint32_t *id) {
800 int i = 0;
801 int j = 0;
802
803 if (DBG) ALOGD("[*] %s(): token(%d)\n", __FUNCTION__, token);
804
805 // Search request history.
806 for (i = 0; i < TOKEN_POOL_SIZE; i++) {
807 ALOGD("[*] %s(): history_token(%d)\n", __FUNCTION__, prv->history[i].token);
808 if (prv->history[i].token == token) {
809 // Search request handler with request ID found.
810 for (j = 0; j < REQ_POOL_SIZE; j++) {
811 ALOGD("[*] %s(): token(%d), req_id(%d), history_id(%d)\n", __FUNCTION__, token, prv->history[i].id, prv->history[i].id);
812 if (prv->req_handlers[j].id == prv->history[i].id) {
813 *id = prv->req_handlers[j].id;
814 return prv->req_handlers[j].handler;
815 }
816 }
817 }
818 }
819
820 return NULL;
821}
822
823
824static int blockingWrite(int fd, const void *buffer, size_t len) {
825 size_t writeOffset = 0;
826 const uint8_t *toWrite;
827 ssize_t written = 0;
828
829 if (buffer == NULL)
830 return -1;
831
832 toWrite = (const uint8_t *)buffer;
833
834 while (writeOffset < len) {
835 do
836 {
837 written = write(fd, toWrite + writeOffset, len - writeOffset);
838 } while (written < 0 && errno == EINTR);
839
840 if (written >= 0) {
841 writeOffset += written;
842 }
843 else {
844 ALOGE ("RIL Response: unexpected error on write errno:%d", errno);
845 close(fd);
846 return -1;
847 }
848 }
849
850 return 0;
851}
852
853} // namespace android
854
855// end of file
856