2 * Copyright (C) 2014 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #define __STDC_LIMIT_MACROS
20 #include "telephony/ril.h"
21 #include "RilSapSocket.h"
22 #include "pb_decode.h"
23 #include "pb_encode.h"
25 #define LOG_TAG "RIL_UIM_SOCKET"
26 #include <utils/Log.h>
27 #include <arpa/inet.h>
30 static RilSapSocket::RilSapSocketList *head = NULL;
32 void ril_sap_on_request_complete (
33 RIL_Token t, RIL_Errno e,
34 void *response, size_t responselen
37 void ril_sap_on_unsolicited_response (
38 int unsolResponse, const void *data,
42 RIL_requestTimedCallback (RIL_TimedCallback callback, void *param,
43 const struct timeval *relativeTime);
45 struct RIL_Env RilSapSocket::uimRilEnv = {
46 .OnRequestComplete = RilSapSocket::sOnRequestComplete,
47 .OnUnsolicitedResponse = RilSapSocket::sOnUnsolicitedResponse,
48 .RequestTimedCallback = RIL_requestTimedCallback
51 void RilSapSocket::sOnRequestComplete (RIL_Token t,
55 RilSapSocket *sap_socket;
56 SapSocketRequest *request = (SapSocketRequest*) t;
58 RLOGD("Socket id:%d", request->socketId);
60 sap_socket = getSocketById(request->socketId);
63 sap_socket->onRequestComplete(t,e,response,responselen);
65 RLOGE("Invalid socket id");
66 if (request->curr->payload) {
67 free(request->curr->payload);
74 #if defined(ANDROID_MULTI_SIM)
75 void RilSapSocket::sOnUnsolicitedResponse(int unsolResponse,
78 RIL_SOCKET_ID socketId) {
79 RilSapSocket *sap_socket = getSocketById(socketId);
81 sap_socket->onUnsolicitedResponse(unsolResponse, (void *)data, datalen);
85 void RilSapSocket::sOnUnsolicitedResponse(int unsolResponse,
88 RilSapSocket *sap_socket = getSocketById(RIL_SOCKET_1);
89 sap_socket->onUnsolicitedResponse(unsolResponse, (void *)data, datalen);
93 void RilSapSocket::printList() {
94 RilSapSocketList *current = head;
95 RLOGD("Printing socket list");
96 while(NULL != current) {
97 RLOGD("SocketName:%s",current->socket->name);
98 RLOGD("Socket id:%d",current->socket->id);
99 current = current->next;
103 RilSapSocket *RilSapSocket::getSocketById(RIL_SOCKET_ID socketId) {
104 RilSapSocket *sap_socket;
105 RilSapSocketList *current = head;
107 RLOGD("Entered getSocketById");
110 while(NULL != current) {
111 if(socketId == current->socket->id) {
112 sap_socket = current->socket;
115 current = current->next;
120 void RilSapSocket::initSapSocket(const char *socketName,
121 RIL_RadioFunctions *uimFuncs) {
123 if (strcmp(socketName, "sap_uim_socket1") == 0) {
124 if(!SocketExists(socketName)) {
125 addSocketToList(socketName, RIL_SOCKET_1, uimFuncs);
130 if (strcmp(socketName, "sap_uim_socket2") == 0) {
131 if(!SocketExists(socketName)) {
132 addSocketToList(socketName, RIL_SOCKET_2, uimFuncs);
138 if (strcmp(socketName, "sap_uim_socket3") == 0) {
139 if(!SocketExists(socketName)) {
140 addSocketToList(socketName, RIL_SOCKET_3, uimFuncs);
146 if (strcmp(socketName, "sap_uim_socket4") == 0) {
147 if(!SocketExists(socketName)) {
148 addSocketToList(socketName, RIL_SOCKET_4, uimFuncs);
154 void RilSapSocket::addSocketToList(const char *socketName, RIL_SOCKET_ID socketid,
155 RIL_RadioFunctions *uimFuncs) {
156 RilSapSocket* socket = NULL;
157 RilSapSocketList *current;
159 if(!SocketExists(socketName)) {
160 socket = new RilSapSocket(socketName, socketid, uimFuncs);
161 RilSapSocketList* listItem = (RilSapSocketList*)malloc(sizeof(RilSapSocketList));
163 RLOGE("addSocketToList: OOM");
166 listItem->socket = socket;
167 listItem->next = NULL;
169 RLOGD("Adding socket with id: %d", socket->id);
177 while(NULL != current->next) {
178 current = current->next;
180 current->next = listItem;
182 socket->socketInit();
186 bool RilSapSocket::SocketExists(const char *socketName) {
187 RilSapSocketList* current = head;
189 while(NULL != current) {
190 if(strcmp(current->socket->name, socketName) == 0) {
193 current = current->next;
198 void* RilSapSocket::processRequestsLoop(void) {
199 RLOGI("UIM_SOCKET:Request loop started");
202 SapSocketRequest *req = dispatchQueue.dequeue();
204 RLOGI("New request from the dispatch Queue");
207 dispatchRequest(req->curr);
210 RLOGE("Fetched null buffer from queue!");
216 RilSapSocket::RilSapSocket(const char *socketName,
217 RIL_SOCKET_ID socketId,
218 RIL_RadioFunctions *inputUimFuncs):
219 RilSocket(socketName, socketId) {
221 uimFuncs = inputUimFuncs;
225 #define BYTES_PER_LINE 16
227 #define NIBBLE_TO_HEX(n) ({ \
228 uint8_t __n = (uint8_t) n & 0x0f; \
229 __nibble >= 10 ? 'A' + __n - 10: '0' + __n; \
232 #define HEX_HIGH(b) ({ \
233 uint8_t __b = (uint8_t) b; \
234 uint8_t __nibble = (__b >> 4) & 0x0f; \
235 NIBBLE_TO_HEX(__nibble); \
238 #define HEX_LOW(b) ({ \
239 uint8_t __b = (uint8_t) b; \
240 uint8_t __nibble = __b & 0x0f; \
241 NIBBLE_TO_HEX(__nibble); \
244 void log_hex(const char *who, const uint8_t *buffer, int length) {
248 int dest_len = sizeof(out);
252 dest += sprintf(out, "%8.8s [%8.8x] ", who, source);
253 for(; source < length && dest_len - dest > 3 && per_line < BYTES_PER_LINE; source++,
255 out[dest++] = HEX_HIGH(buffer[source]);
256 out[dest++] = HEX_LOW(buffer[source]);
259 if (dest < dest_len && (per_line == BYTES_PER_LINE || source >= length)) {
265 } while(source < length && dest < dest_len);
268 void RilSapSocket::dispatchRequest(MsgHeader *req) {
269 // SapSocketRequest will be deallocated in onRequestComplete()
270 SapSocketRequest* currRequest=(SapSocketRequest*)malloc(sizeof(SapSocketRequest));
272 RLOGE("dispatchRequest: OOM");
273 // Free MsgHeader allocated in pushRecord()
277 currRequest->token = req->token;
278 currRequest->curr = req;
279 currRequest->p_next = NULL;
280 currRequest->socketId = id;
282 pendingResponseQueue.enqueue(currRequest);
285 RLOGI("[%d] > SAP REQUEST type: %d. id: %d. error: %d",
291 #if defined(ANDROID_MULTI_SIM)
292 uimFuncs->onRequest(req->id, req->payload->bytes, req->payload->size, currRequest, id);
294 uimFuncs->onRequest(req->id, req->payload->bytes, req->payload->size, currRequest);
299 void RilSapSocket::onRequestComplete(RIL_Token t, RIL_Errno e, void *response,
300 size_t response_len) {
301 SapSocketRequest* request= (SapSocketRequest*)t;
302 MsgHeader *hdr = request->curr;
305 rsp.token = request->curr->token;
306 rsp.type = MsgType_RESPONSE;
307 rsp.id = request->curr->id;
308 rsp.error = (Error)e;
309 rsp.payload = (pb_bytes_array_t *)calloc(1, sizeof(pb_bytes_array_t) + response_len);
311 RLOGE("onRequestComplete: OOM");
313 if (response && response_len > 0) {
314 memcpy(rsp.payload->bytes, response, response_len);
315 rsp.payload->size = response_len;
317 rsp.payload->size = 0;
320 RLOGE("Token:%d, MessageId:%d", hdr->token, hdr->id);
326 // Deallocate SapSocketRequest
327 if(!pendingResponseQueue.checkAndDequeue(hdr->id, hdr->token)) {
328 RLOGE("Token:%d, MessageId:%d", hdr->token, hdr->id);
329 RLOGE ("RilSapSocket::onRequestComplete: invalid Token or Message Id");
332 // Deallocate MsgHeader
336 void RilSapSocket::sendResponse(MsgHeader* hdr) {
337 size_t encoded_size = 0;
338 uint32_t written_size;
339 size_t buffer_size = 0;
340 pb_ostream_t ostream;
341 bool success = false;
343 pthread_mutex_lock(&write_lock);
345 if ((success = pb_get_encoded_size(&encoded_size, MsgHeader_fields,
346 hdr)) && encoded_size <= INT32_MAX && commandFd != -1) {
347 buffer_size = encoded_size + sizeof(uint32_t);
348 uint8_t* buffer = (uint8_t*)malloc(buffer_size);
350 RLOGE("sendResponse: OOM");
351 pthread_mutex_unlock(&write_lock);
354 written_size = htonl((uint32_t) encoded_size);
355 ostream = pb_ostream_from_buffer(buffer, buffer_size);
356 pb_write(&ostream, (uint8_t *)&written_size, sizeof(written_size));
357 success = pb_encode(&ostream, MsgHeader_fields, hdr);
360 RLOGD("Size: %zu (0x%zx) Size as written: 0x%x", encoded_size,
361 encoded_size, written_size);
362 log_hex("onRequestComplete", &buffer[sizeof(written_size)], encoded_size);
363 RLOGI("[%d] < SAP RESPONSE type: %d. id: %d. error: %d",
364 hdr->token, hdr->type, hdr->id,hdr->error );
366 if ( 0 != blockingWrite_helper(commandFd, buffer, buffer_size)) {
367 RLOGE("Error %d while writing to fd", errno);
369 RLOGD("Write successful");
372 RLOGE("Error while encoding response of type %d id %d buffer_size: %zu: %s.",
373 hdr->type, hdr->id, buffer_size, PB_GET_ERROR(&ostream));
377 RLOGE("Not sending response type %d: encoded_size: %zu. commandFd: %d. encoded size result:\
378 %d", hdr->type, encoded_size, commandFd, success);
381 pthread_mutex_unlock(&write_lock);
384 void RilSapSocket::onUnsolicitedResponse(int unsolResponse, void *data, size_t datalen) {
385 if (data && datalen > 0) {
386 pb_bytes_array_t *payload = (pb_bytes_array_t *)calloc(1,
387 sizeof(pb_bytes_array_t) + datalen);
389 RLOGE("onUnsolicitedResponse: OOM");
392 memcpy(payload->bytes, data, datalen);
393 payload->size = datalen;
395 rsp.payload = payload;
396 rsp.type = MsgType_UNSOL_RESPONSE;
397 rsp.id = (MsgId)unsolResponse;
398 rsp.error = Error_RIL_E_SUCCESS;
404 void RilSapSocket::pushRecord(void *p_record, size_t recordlen) {
405 pb_istream_t stream = pb_istream_from_buffer((uint8_t *)p_record, recordlen);
406 // MsgHeader will be deallocated in onRequestComplete()
407 MsgHeader *reqHeader = (MsgHeader *)malloc(sizeof (MsgHeader));
409 RLOGE("pushRecord: OOM");
412 memset(reqHeader, 0, sizeof(MsgHeader));
414 log_hex("BtSapTest-Payload", (const uint8_t*)p_record, recordlen);
416 if (!pb_decode(&stream, MsgHeader_fields, reqHeader) ) {
417 RLOGE("Error decoding protobuf buffer : %s", PB_GET_ERROR(&stream));
420 // SapSocketRequest will be deallocated in processRequestsLoop()
421 SapSocketRequest *recv = (SapSocketRequest*)malloc(sizeof(SapSocketRequest));
423 RLOGE("pushRecord: OOM");
427 recv->token = reqHeader->token;
428 recv->curr = reqHeader;
431 dispatchQueue.enqueue(recv);
435 void RilSapSocket::sendDisconnect() {
436 size_t encoded_size = 0;
437 uint32_t written_size;
438 size_t buffer_size = 0;
439 pb_ostream_t ostream;
440 bool success = false;
442 RIL_SIM_SAP_DISCONNECT_REQ disconnectReq;
444 if ((success = pb_get_encoded_size(&encoded_size, RIL_SIM_SAP_DISCONNECT_REQ_fields,
445 &disconnectReq)) && encoded_size <= INT32_MAX) {
446 buffer_size = encoded_size + sizeof(uint32_t);
447 uint8_t* buffer = (uint8_t*)malloc(buffer_size);
449 RLOGE("sendDisconnect: OOM");
452 written_size = htonl((uint32_t) encoded_size);
453 ostream = pb_ostream_from_buffer(buffer, buffer_size);
454 pb_write(&ostream, (uint8_t *)&written_size, sizeof(written_size));
455 success = pb_encode(&ostream, RIL_SIM_SAP_DISCONNECT_REQ_fields, buffer);
458 // Buffer will be deallocated in sOnRequestComplete()
459 pb_bytes_array_t *payload = (pb_bytes_array_t *)calloc(1,
460 sizeof(pb_bytes_array_t) + written_size);
462 RLOGE("sendDisconnect: OOM");
465 memcpy(payload->bytes, buffer, written_size);
466 payload->size = written_size;
467 // MsgHeader will be deallocated in sOnRequestComplete()
468 MsgHeader *hdr = (MsgHeader *)malloc(sizeof(MsgHeader));
470 RLOGE("sendDisconnect: OOM");
474 hdr->payload = payload;
475 hdr->type = MsgType_REQUEST;
476 hdr->id = MsgId_RIL_SIM_SAP_DISCONNECT;
477 hdr->error = Error_RIL_E_SUCCESS;
478 dispatchDisconnect(hdr);
481 RLOGE("Encode failed in send disconnect!");
487 void RilSapSocket::dispatchDisconnect(MsgHeader *req) {
488 // SapSocketRequest will be deallocated in sOnRequestComplete()
489 SapSocketRequest* currRequest=(SapSocketRequest*)malloc(sizeof(SapSocketRequest));
491 RLOGE("dispatchDisconnect: OOM");
492 // Free memory allocated in sendDisconnect
497 currRequest->token = -1;
498 currRequest->curr = req;
499 currRequest->p_next = NULL;
500 currRequest->socketId = (RIL_SOCKET_ID)99;
502 RLOGD("Sending disconnect on command close!");
504 #if defined(ANDROID_MULTI_SIM)
505 uimFuncs->onRequest(req->id, req->payload->bytes, req->payload->size, currRequest, id);
507 uimFuncs->onRequest(req->id, req->payload->bytes, req->payload->size, currRequest);
511 void RilSapSocket::onCommandsSocketClosed() {
513 RLOGE("Socket command closed");