blob: 7e4e9c14c58e72fe14c1a00172738c74b07ec187 [file] [log] [blame]
Dheeraj Shetty27976c42014-07-02 21:27:57 +02001/*
2* Copyright (C) 2014 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 __STDC_LIMIT_MACROS
18#include <stdint.h>
19#define RIL_SHLIB
20#include "telephony/ril.h"
21#include "RilSapSocket.h"
22#include "pb_decode.h"
23#include "pb_encode.h"
24#define LOG_TAG "RIL_UIM_SOCKET"
25#include <utils/Log.h>
26#include <arpa/inet.h>
Vinit Deshpande1b1ec2d2015-04-15 13:31:05 -070027#include <errno.h>
Dheeraj Shetty27976c42014-07-02 21:27:57 +020028
Pavel Zhamaitsiakd33397b2015-08-18 11:40:01 -070029static RilSapSocket::RilSapSocketList *head = NULL;
Dheeraj Shetty27976c42014-07-02 21:27:57 +020030
31void ril_sap_on_request_complete (
32 RIL_Token t, RIL_Errno e,
33 void *response, size_t responselen
34);
35
36void ril_sap_on_unsolicited_response (
37 int unsolResponse, const void *data,
38 size_t datalen
39);
40extern "C" void
41RIL_requestTimedCallback (RIL_TimedCallback callback, void *param,
42 const struct timeval *relativeTime);
43
44struct RIL_Env RilSapSocket::uimRilEnv = {
45 .OnRequestComplete = RilSapSocket::sOnRequestComplete,
46 .OnUnsolicitedResponse = RilSapSocket::sOnUnsolicitedResponse,
47 .RequestTimedCallback = RIL_requestTimedCallback
48};
49
50void RilSapSocket::sOnRequestComplete (RIL_Token t,
51 RIL_Errno e,
52 void *response,
53 size_t responselen) {
54 RilSapSocket *sap_socket;
55 SapSocketRequest *request = (SapSocketRequest*) t;
56
57 RLOGD("Socket id:%d", request->socketId);
58
59 sap_socket = getSocketById(request->socketId);
60
61 if (sap_socket) {
62 sap_socket->onRequestComplete(t,e,response,responselen);
63 } else {
64 RLOGE("Invalid socket id");
Pavel Zhamaitsiakd33397b2015-08-18 11:40:01 -070065 if (request->curr->payload) {
66 free(request->curr->payload);
67 }
Dheeraj Shetty27976c42014-07-02 21:27:57 +020068 free(request->curr);
69 free(request);
70 }
71}
72
73#if defined(ANDROID_MULTI_SIM)
74void RilSapSocket::sOnUnsolicitedResponse(int unsolResponse,
75 const void *data,
76 size_t datalen,
77 RIL_SOCKET_ID socketId) {
78 RilSapSocket *sap_socket = getSocketById(socketId);
79 if (sap_socket) {
80 sap_socket->onUnsolicitedResponse(unsolResponse, (void *)data, datalen);
81 }
82}
83#else
84void RilSapSocket::sOnUnsolicitedResponse(int unsolResponse,
85 const void *data,
86 size_t datalen) {
87 RilSapSocket *sap_socket = getSocketById(RIL_SOCKET_1);
88 sap_socket->onUnsolicitedResponse(unsolResponse, (void *)data, datalen);
89}
90#endif
91
92void RilSapSocket::printList() {
93 RilSapSocketList *current = head;
94 RLOGD("Printing socket list");
95 while(NULL != current) {
96 RLOGD("SocketName:%s",current->socket->name);
97 RLOGD("Socket id:%d",current->socket->id);
98 current = current->next;
99 }
100}
101
102RilSapSocket *RilSapSocket::getSocketById(RIL_SOCKET_ID socketId) {
103 RilSapSocket *sap_socket;
104 RilSapSocketList *current = head;
105
106 RLOGD("Entered getSocketById");
107 printList();
108
109 while(NULL != current) {
110 if(socketId == current->socket->id) {
111 sap_socket = current->socket;
112 return sap_socket;
113 }
114 current = current->next;
115 }
116 return NULL;
117}
118
119void RilSapSocket::initSapSocket(const char *socketName,
120 RIL_RadioFunctions *uimFuncs) {
121
122 if (strcmp(socketName, "sap_uim_socket1") == 0) {
123 if(!SocketExists(socketName)) {
124 addSocketToList(socketName, RIL_SOCKET_1, uimFuncs);
125 }
126 }
127
128#if (SIM_COUNT >= 2)
129 if (strcmp(socketName, "sap_uim_socket2") == 0) {
130 if(!SocketExists(socketName)) {
131 addSocketToList(socketName, RIL_SOCKET_2, uimFuncs);
132 }
133 }
134#endif
135
136#if (SIM_COUNT >= 3)
137 if (strcmp(socketName, "sap_uim_socket3") == 0) {
138 if(!SocketExists(socketName)) {
139 addSocketToList(socketName, RIL_SOCKET_3, uimFuncs);
140 }
141 }
142#endif
143
144#if (SIM_COUNT >= 4)
145 if (strcmp(socketName, "sap_uim_socket4") == 0) {
146 if(!SocketExists(socketName)) {
147 addSocketToList(socketName, RIL_SOCKET_4, uimFuncs);
148 }
149 }
150#endif
151}
152
153void RilSapSocket::addSocketToList(const char *socketName, RIL_SOCKET_ID socketid,
154 RIL_RadioFunctions *uimFuncs) {
155 RilSapSocket* socket = NULL;
Dheeraj Shetty27976c42014-07-02 21:27:57 +0200156 RilSapSocketList *current;
157
158 if(!SocketExists(socketName)) {
159 socket = new RilSapSocket(socketName, socketid, uimFuncs);
Pavel Zhamaitsiakd33397b2015-08-18 11:40:01 -0700160 RilSapSocketList* listItem = (RilSapSocketList*)malloc(sizeof(RilSapSocketList));
161 if (!listItem) {
162 RLOGE("addSocketToList: OOM");
Yunlian Jiang0c049562016-11-08 18:19:11 -0800163 delete socket;
Pavel Zhamaitsiakd33397b2015-08-18 11:40:01 -0700164 return;
165 }
Dheeraj Shetty27976c42014-07-02 21:27:57 +0200166 listItem->socket = socket;
167 listItem->next = NULL;
168
169 RLOGD("Adding socket with id: %d", socket->id);
170
171 if(NULL == head) {
172 head = listItem;
173 head->next = NULL;
174 }
175 else {
176 current = head;
177 while(NULL != current->next) {
178 current = current->next;
179 }
180 current->next = listItem;
181 }
182 socket->socketInit();
183 }
184}
185
186bool RilSapSocket::SocketExists(const char *socketName) {
187 RilSapSocketList* current = head;
188
189 while(NULL != current) {
190 if(strcmp(current->socket->name, socketName) == 0) {
191 return true;
192 }
193 current = current->next;
194 }
195 return false;
196}
197
198void* RilSapSocket::processRequestsLoop(void) {
Dheeraj Shetty27976c42014-07-02 21:27:57 +0200199 RLOGI("UIM_SOCKET:Request loop started");
200
201 while(true) {
Pavel Zhamaitsiakd33397b2015-08-18 11:40:01 -0700202 SapSocketRequest *req = dispatchQueue.dequeue();
Dheeraj Shetty27976c42014-07-02 21:27:57 +0200203
204 RLOGI("New request from the dispatch Queue");
205
206 if (req != NULL) {
Pavel Zhamaitsiakd33397b2015-08-18 11:40:01 -0700207 dispatchRequest(req->curr);
Dheeraj Shetty27976c42014-07-02 21:27:57 +0200208 free(req);
209 } else {
210 RLOGE("Fetched null buffer from queue!");
211 }
212 }
213 return NULL;
214}
215
216RilSapSocket::RilSapSocket(const char *socketName,
217 RIL_SOCKET_ID socketId,
218 RIL_RadioFunctions *inputUimFuncs):
219 RilSocket(socketName, socketId) {
220 if (inputUimFuncs) {
221 uimFuncs = inputUimFuncs;
222 }
223}
224
Dheeraj Shetty27976c42014-07-02 21:27:57 +0200225#define BYTES_PER_LINE 16
226
227#define NIBBLE_TO_HEX(n) ({ \
Chih-Hung Hsieh434554c2016-05-12 10:01:16 -0700228 uint8_t __n = (uint8_t) (n) & 0x0f; \
Dheeraj Shetty27976c42014-07-02 21:27:57 +0200229 __nibble >= 10 ? 'A' + __n - 10: '0' + __n; \
230})
231
232#define HEX_HIGH(b) ({ \
Chih-Hung Hsieh434554c2016-05-12 10:01:16 -0700233 uint8_t __b = (uint8_t) (b); \
Dheeraj Shetty27976c42014-07-02 21:27:57 +0200234 uint8_t __nibble = (__b >> 4) & 0x0f; \
235 NIBBLE_TO_HEX(__nibble); \
236})
237
238#define HEX_LOW(b) ({ \
Chih-Hung Hsieh434554c2016-05-12 10:01:16 -0700239 uint8_t __b = (uint8_t) (b); \
Dheeraj Shetty27976c42014-07-02 21:27:57 +0200240 uint8_t __nibble = __b & 0x0f; \
241 NIBBLE_TO_HEX(__nibble); \
242})
243
244void log_hex(const char *who, const uint8_t *buffer, int length) {
245 char out[80];
246 int source = 0;
247 int dest = 0;
248 int dest_len = sizeof(out);
249 int per_line = 0;
250
251 do {
252 dest += sprintf(out, "%8.8s [%8.8x] ", who, source);
253 for(; source < length && dest_len - dest > 3 && per_line < BYTES_PER_LINE; source++,
254 per_line ++) {
255 out[dest++] = HEX_HIGH(buffer[source]);
256 out[dest++] = HEX_LOW(buffer[source]);
257 out[dest++] = ' ';
258 }
259 if (dest < dest_len && (per_line == BYTES_PER_LINE || source >= length)) {
260 out[dest++] = 0;
261 per_line = 0;
262 dest = 0;
263 RLOGD("%s\n", out);
264 }
265 } while(source < length && dest < dest_len);
266}
267
268void RilSapSocket::dispatchRequest(MsgHeader *req) {
Pavel Zhamaitsiakd33397b2015-08-18 11:40:01 -0700269 // SapSocketRequest will be deallocated in onRequestComplete()
Dheeraj Shetty27976c42014-07-02 21:27:57 +0200270 SapSocketRequest* currRequest=(SapSocketRequest*)malloc(sizeof(SapSocketRequest));
Pavel Zhamaitsiakd33397b2015-08-18 11:40:01 -0700271 if (!currRequest) {
272 RLOGE("dispatchRequest: OOM");
273 // Free MsgHeader allocated in pushRecord()
274 free(req);
275 return;
276 }
Dheeraj Shetty27976c42014-07-02 21:27:57 +0200277 currRequest->token = req->token;
278 currRequest->curr = req;
279 currRequest->p_next = NULL;
280 currRequest->socketId = id;
281
282 pendingResponseQueue.enqueue(currRequest);
283
284 if (uimFuncs) {
285 RLOGI("[%d] > SAP REQUEST type: %d. id: %d. error: %d",
286 req->token,
287 req->type,
288 req->id,
289 req->error );
290
291#if defined(ANDROID_MULTI_SIM)
292 uimFuncs->onRequest(req->id, req->payload->bytes, req->payload->size, currRequest, id);
293#else
294 uimFuncs->onRequest(req->id, req->payload->bytes, req->payload->size, currRequest);
295#endif
296 }
297}
298
299void 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;
Dheeraj Shetty27976c42014-07-02 21:27:57 +0200303
Sanket Padawe638a7232016-01-26 16:26:30 -0800304 MsgHeader rsp;
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);
310 if (!rsp.payload) {
311 RLOGE("onRequestComplete: OOM");
312 } else {
313 if (response && response_len > 0) {
Pavel Zhamaitsiakd33397b2015-08-18 11:40:01 -0700314 memcpy(rsp.payload->bytes, response, response_len);
315 rsp.payload->size = response_len;
Sanket Padawe638a7232016-01-26 16:26:30 -0800316 } else {
317 rsp.payload->size = 0;
Pavel Zhamaitsiakd33397b2015-08-18 11:40:01 -0700318 }
Sanket Padawe638a7232016-01-26 16:26:30 -0800319
320 RLOGE("Token:%d, MessageId:%d", hdr->token, hdr->id);
321
322 sendResponse(&rsp);
323 free(rsp.payload);
Dheeraj Shetty27976c42014-07-02 21:27:57 +0200324 }
Pavel Zhamaitsiakd33397b2015-08-18 11:40:01 -0700325
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");
330 }
331
332 // Deallocate MsgHeader
333 free(hdr);
Dheeraj Shetty27976c42014-07-02 21:27:57 +0200334}
335
336void 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;
342
343 pthread_mutex_lock(&write_lock);
344
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[buffer_size];
349 written_size = htonl((uint32_t) encoded_size);
350 ostream = pb_ostream_from_buffer(buffer, buffer_size);
351 pb_write(&ostream, (uint8_t *)&written_size, sizeof(written_size));
352 success = pb_encode(&ostream, MsgHeader_fields, hdr);
353
354 if (success) {
355 RLOGD("Size: %d (0x%x) Size as written: 0x%x", encoded_size, encoded_size,
356 written_size);
357 log_hex("onRequestComplete", &buffer[sizeof(written_size)], encoded_size);
358 RLOGI("[%d] < SAP RESPONSE type: %d. id: %d. error: %d",
359 hdr->token, hdr->type, hdr->id,hdr->error );
360
361 if ( 0 != blockingWrite_helper(commandFd, buffer, buffer_size)) {
362 RLOGE("Error %d while writing to fd", errno);
363 } else {
364 RLOGD("Write successful");
365 }
366 } else {
367 RLOGE("Error while encoding response of type %d id %d buffer_size: %d: %s.",
368 hdr->type, hdr->id, buffer_size, PB_GET_ERROR(&ostream));
369 }
370 } else {
371 RLOGE("Not sending response type %d: encoded_size: %u. commandFd: %d. encoded size result: %d",
372 hdr->type, encoded_size, commandFd, success);
373 }
374
375 pthread_mutex_unlock(&write_lock);
376}
377
378void RilSapSocket::onUnsolicitedResponse(int unsolResponse, void *data, size_t datalen) {
Pavel Zhamaitsiakd33397b2015-08-18 11:40:01 -0700379 if (data && datalen > 0) {
380 pb_bytes_array_t *payload = (pb_bytes_array_t *)calloc(1,
381 sizeof(pb_bytes_array_t) + datalen);
382 if (!payload) {
383 RLOGE("onUnsolicitedResponse: OOM");
384 return;
385 }
Dheeraj Shetty27976c42014-07-02 21:27:57 +0200386 memcpy(payload->bytes, data, datalen);
387 payload->size = datalen;
Pavel Zhamaitsiakd33397b2015-08-18 11:40:01 -0700388 MsgHeader rsp;
389 rsp.payload = payload;
390 rsp.type = MsgType_UNSOL_RESPONSE;
391 rsp.id = (MsgId)unsolResponse;
392 rsp.error = Error_RIL_E_SUCCESS;
393 sendResponse(&rsp);
394 free(payload);
Dheeraj Shetty27976c42014-07-02 21:27:57 +0200395 }
396}
397
398void RilSapSocket::pushRecord(void *p_record, size_t recordlen) {
Pavel Zhamaitsiakd33397b2015-08-18 11:40:01 -0700399 pb_istream_t stream = pb_istream_from_buffer((uint8_t *)p_record, recordlen);
400 // MsgHeader will be deallocated in onRequestComplete()
401 MsgHeader *reqHeader = (MsgHeader *)malloc(sizeof (MsgHeader));
402 if (!reqHeader) {
403 RLOGE("pushRecord: OOM");
404 return;
405 }
Dheeraj Shetty27976c42014-07-02 21:27:57 +0200406 memset(reqHeader, 0, sizeof(MsgHeader));
407
408 log_hex("BtSapTest-Payload", (const uint8_t*)p_record, recordlen);
409
410 if (!pb_decode(&stream, MsgHeader_fields, reqHeader) ) {
411 RLOGE("Error decoding protobuf buffer : %s", PB_GET_ERROR(&stream));
Pavel Zhamaitsiakd33397b2015-08-18 11:40:01 -0700412 free(reqHeader);
Dheeraj Shetty27976c42014-07-02 21:27:57 +0200413 } else {
Pavel Zhamaitsiakd33397b2015-08-18 11:40:01 -0700414 // SapSocketRequest will be deallocated in processRequestsLoop()
415 SapSocketRequest *recv = (SapSocketRequest*)malloc(sizeof(SapSocketRequest));
416 if (!recv) {
417 RLOGE("pushRecord: OOM");
418 free(reqHeader);
419 return;
420 }
Dheeraj Shetty27976c42014-07-02 21:27:57 +0200421 recv->token = reqHeader->token;
422 recv->curr = reqHeader;
423 recv->socketId = id;
424
425 dispatchQueue.enqueue(recv);
426 }
427}
428
429void RilSapSocket::sendDisconnect() {
Dheeraj Shetty27976c42014-07-02 21:27:57 +0200430 size_t encoded_size = 0;
431 uint32_t written_size;
432 size_t buffer_size = 0;
433 pb_ostream_t ostream;
434 bool success = false;
Dheeraj Shetty27976c42014-07-02 21:27:57 +0200435
436 RIL_SIM_SAP_DISCONNECT_REQ disconnectReq;
437
438 if ((success = pb_get_encoded_size(&encoded_size, RIL_SIM_SAP_DISCONNECT_REQ_fields,
439 &disconnectReq)) && encoded_size <= INT32_MAX) {
440 buffer_size = encoded_size + sizeof(uint32_t);
441 uint8_t buffer[buffer_size];
442 written_size = htonl((uint32_t) encoded_size);
443 ostream = pb_ostream_from_buffer(buffer, buffer_size);
444 pb_write(&ostream, (uint8_t *)&written_size, sizeof(written_size));
445 success = pb_encode(&ostream, RIL_SIM_SAP_DISCONNECT_REQ_fields, buffer);
446
447 if(success) {
Pavel Zhamaitsiakd33397b2015-08-18 11:40:01 -0700448 // Buffer will be deallocated in sOnRequestComplete()
449 pb_bytes_array_t *payload = (pb_bytes_array_t *)calloc(1,
450 sizeof(pb_bytes_array_t) + written_size);
451 if (!payload) {
452 RLOGE("sendDisconnect: OOM");
453 return;
454 }
Dheeraj Shetty27976c42014-07-02 21:27:57 +0200455 memcpy(payload->bytes, buffer, written_size);
456 payload->size = written_size;
Pavel Zhamaitsiakd33397b2015-08-18 11:40:01 -0700457 // MsgHeader will be deallocated in sOnRequestComplete()
458 MsgHeader *hdr = (MsgHeader *)malloc(sizeof(MsgHeader));
459 if (!hdr) {
460 RLOGE("sendDisconnect: OOM");
461 free(payload);
462 return;
463 }
Dheeraj Shetty27976c42014-07-02 21:27:57 +0200464 hdr->payload = payload;
465 hdr->type = MsgType_REQUEST;
466 hdr->id = MsgId_RIL_SIM_SAP_DISCONNECT;
467 hdr->error = Error_RIL_E_SUCCESS;
468 dispatchDisconnect(hdr);
469 }
470 else {
471 RLOGE("Encode failed in send disconnect!");
Dheeraj Shetty27976c42014-07-02 21:27:57 +0200472 }
473 }
474}
475
476void RilSapSocket::dispatchDisconnect(MsgHeader *req) {
Pavel Zhamaitsiakd33397b2015-08-18 11:40:01 -0700477 // SapSocketRequest will be deallocated in sOnRequestComplete()
Dheeraj Shetty27976c42014-07-02 21:27:57 +0200478 SapSocketRequest* currRequest=(SapSocketRequest*)malloc(sizeof(SapSocketRequest));
Pavel Zhamaitsiakd33397b2015-08-18 11:40:01 -0700479 if (!currRequest) {
480 RLOGE("dispatchDisconnect: OOM");
481 // Free memory allocated in sendDisconnect
482 free(req->payload);
483 free(req);
484 return;
485 }
Dheeraj Shetty27976c42014-07-02 21:27:57 +0200486 currRequest->token = -1;
487 currRequest->curr = req;
488 currRequest->p_next = NULL;
489 currRequest->socketId = (RIL_SOCKET_ID)99;
490
491 RLOGD("Sending disconnect on command close!");
492
493#if defined(ANDROID_MULTI_SIM)
494 uimFuncs->onRequest(req->id, req->payload->bytes, req->payload->size, currRequest, id);
495#else
496 uimFuncs->onRequest(req->id, req->payload->bytes, req->payload->size, currRequest);
497#endif
498}
499
500void RilSapSocket::onCommandsSocketClosed() {
501 sendDisconnect();
502 RLOGE("Socket command closed");
503}