blob: 36277cf0d9fee257280e387ff3f746ba8a12faa0 [file] [log] [blame]
Dheeraj Shettycc231012014-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 Deshpande5257b142015-04-15 13:31:05 -070027#include <errno.h>
Dheeraj Shettycc231012014-07-02 21:27:57 +020028
29RilSapSocket::RilSapSocketList *head;
30
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");
65 free(request->curr);
66 free(request);
67 }
68}
69
70#if defined(ANDROID_MULTI_SIM)
71void RilSapSocket::sOnUnsolicitedResponse(int unsolResponse,
72 const void *data,
73 size_t datalen,
74 RIL_SOCKET_ID socketId) {
75 RilSapSocket *sap_socket = getSocketById(socketId);
76 if (sap_socket) {
77 sap_socket->onUnsolicitedResponse(unsolResponse, (void *)data, datalen);
78 }
79}
80#else
81void RilSapSocket::sOnUnsolicitedResponse(int unsolResponse,
82 const void *data,
83 size_t datalen) {
84 RilSapSocket *sap_socket = getSocketById(RIL_SOCKET_1);
85 sap_socket->onUnsolicitedResponse(unsolResponse, (void *)data, datalen);
86}
87#endif
88
89void RilSapSocket::printList() {
90 RilSapSocketList *current = head;
91 RLOGD("Printing socket list");
92 while(NULL != current) {
93 RLOGD("SocketName:%s",current->socket->name);
94 RLOGD("Socket id:%d",current->socket->id);
95 current = current->next;
96 }
97}
98
99RilSapSocket *RilSapSocket::getSocketById(RIL_SOCKET_ID socketId) {
100 RilSapSocket *sap_socket;
101 RilSapSocketList *current = head;
102
103 RLOGD("Entered getSocketById");
104 printList();
105
106 while(NULL != current) {
107 if(socketId == current->socket->id) {
108 sap_socket = current->socket;
109 return sap_socket;
110 }
111 current = current->next;
112 }
113 return NULL;
114}
115
116void RilSapSocket::initSapSocket(const char *socketName,
117 RIL_RadioFunctions *uimFuncs) {
118
119 if (strcmp(socketName, "sap_uim_socket1") == 0) {
120 if(!SocketExists(socketName)) {
121 addSocketToList(socketName, RIL_SOCKET_1, uimFuncs);
122 }
123 }
124
125#if (SIM_COUNT >= 2)
126 if (strcmp(socketName, "sap_uim_socket2") == 0) {
127 if(!SocketExists(socketName)) {
128 addSocketToList(socketName, RIL_SOCKET_2, uimFuncs);
129 }
130 }
131#endif
132
133#if (SIM_COUNT >= 3)
134 if (strcmp(socketName, "sap_uim_socket3") == 0) {
135 if(!SocketExists(socketName)) {
136 addSocketToList(socketName, RIL_SOCKET_3, uimFuncs);
137 }
138 }
139#endif
140
141#if (SIM_COUNT >= 4)
142 if (strcmp(socketName, "sap_uim_socket4") == 0) {
143 if(!SocketExists(socketName)) {
144 addSocketToList(socketName, RIL_SOCKET_4, uimFuncs);
145 }
146 }
147#endif
148}
149
150void RilSapSocket::addSocketToList(const char *socketName, RIL_SOCKET_ID socketid,
151 RIL_RadioFunctions *uimFuncs) {
152 RilSapSocket* socket = NULL;
153 RilSapSocketList* listItem = (RilSapSocketList*)malloc(sizeof(RilSapSocketList));
154 RilSapSocketList *current;
155
156 if(!SocketExists(socketName)) {
157 socket = new RilSapSocket(socketName, socketid, uimFuncs);
158 listItem->socket = socket;
159 listItem->next = NULL;
160
161 RLOGD("Adding socket with id: %d", socket->id);
162
163 if(NULL == head) {
164 head = listItem;
165 head->next = NULL;
166 }
167 else {
168 current = head;
169 while(NULL != current->next) {
170 current = current->next;
171 }
172 current->next = listItem;
173 }
174 socket->socketInit();
175 }
176}
177
178bool RilSapSocket::SocketExists(const char *socketName) {
179 RilSapSocketList* current = head;
180
181 while(NULL != current) {
182 if(strcmp(current->socket->name, socketName) == 0) {
183 return true;
184 }
185 current = current->next;
186 }
187 return false;
188}
189
190void* RilSapSocket::processRequestsLoop(void) {
191 SapSocketRequest *req = (SapSocketRequest*)malloc(sizeof(SapSocketRequest));
192 RLOGI("UIM_SOCKET:Request loop started");
193
194 while(true) {
195 req = dispatchQueue.dequeue();
196
197 RLOGI("New request from the dispatch Queue");
198
199 if (req != NULL) {
200 processRequest(req->curr);
201 free(req);
202 } else {
203 RLOGE("Fetched null buffer from queue!");
204 }
205 }
206 return NULL;
207}
208
209RilSapSocket::RilSapSocket(const char *socketName,
210 RIL_SOCKET_ID socketId,
211 RIL_RadioFunctions *inputUimFuncs):
212 RilSocket(socketName, socketId) {
213 if (inputUimFuncs) {
214 uimFuncs = inputUimFuncs;
215 }
216}
217
218int RilSapSocket::processRequest(MsgHeader *request) {
219 dispatchRequest(request);
220 return 0;
221}
222
223#define BYTES_PER_LINE 16
224
225#define NIBBLE_TO_HEX(n) ({ \
226 uint8_t __n = (uint8_t) n & 0x0f; \
227 __nibble >= 10 ? 'A' + __n - 10: '0' + __n; \
228})
229
230#define HEX_HIGH(b) ({ \
231 uint8_t __b = (uint8_t) b; \
232 uint8_t __nibble = (__b >> 4) & 0x0f; \
233 NIBBLE_TO_HEX(__nibble); \
234})
235
236#define HEX_LOW(b) ({ \
237 uint8_t __b = (uint8_t) b; \
238 uint8_t __nibble = __b & 0x0f; \
239 NIBBLE_TO_HEX(__nibble); \
240})
241
242void log_hex(const char *who, const uint8_t *buffer, int length) {
243 char out[80];
244 int source = 0;
245 int dest = 0;
246 int dest_len = sizeof(out);
247 int per_line = 0;
248
249 do {
250 dest += sprintf(out, "%8.8s [%8.8x] ", who, source);
251 for(; source < length && dest_len - dest > 3 && per_line < BYTES_PER_LINE; source++,
252 per_line ++) {
253 out[dest++] = HEX_HIGH(buffer[source]);
254 out[dest++] = HEX_LOW(buffer[source]);
255 out[dest++] = ' ';
256 }
257 if (dest < dest_len && (per_line == BYTES_PER_LINE || source >= length)) {
258 out[dest++] = 0;
259 per_line = 0;
260 dest = 0;
261 RLOGD("%s\n", out);
262 }
263 } while(source < length && dest < dest_len);
264}
265
266void RilSapSocket::dispatchRequest(MsgHeader *req) {
267 SapSocketRequest* currRequest=(SapSocketRequest*)malloc(sizeof(SapSocketRequest));
268 currRequest->token = req->token;
269 currRequest->curr = req;
270 currRequest->p_next = NULL;
271 currRequest->socketId = id;
272
273 pendingResponseQueue.enqueue(currRequest);
274
275 if (uimFuncs) {
276 RLOGI("[%d] > SAP REQUEST type: %d. id: %d. error: %d",
277 req->token,
278 req->type,
279 req->id,
280 req->error );
281
282#if defined(ANDROID_MULTI_SIM)
283 uimFuncs->onRequest(req->id, req->payload->bytes, req->payload->size, currRequest, id);
284#else
285 uimFuncs->onRequest(req->id, req->payload->bytes, req->payload->size, currRequest);
286#endif
287 }
288}
289
290void RilSapSocket::onRequestComplete(RIL_Token t, RIL_Errno e, void *response,
291 size_t response_len) {
292 SapSocketRequest* request= (SapSocketRequest*)t;
293 MsgHeader *hdr = request->curr;
294 pb_bytes_array_t *payload = (pb_bytes_array_t *)
295 calloc(1,sizeof(pb_bytes_array_t) + response_len);
296
297 if (hdr && payload) {
298 memcpy(payload->bytes, response, response_len);
299 payload->size = response_len;
300 hdr->payload = payload;
301 hdr->type = MsgType_RESPONSE;
302 hdr->error = (Error) e;
303
304 RLOGE("Token:%d, MessageId:%d", hdr->token, hdr->id);
305
306 if(!pendingResponseQueue.checkAndDequeue(hdr->id, hdr->token)) {
307 RLOGE("Token:%d, MessageId:%d", hdr->token, hdr->id);
308 RLOGE ("RilSapSocket::onRequestComplete: invalid Token or Message Id");
309 return;
310 }
311
312 sendResponse(hdr);
313 free(hdr);
314 }
315}
316
317void RilSapSocket::sendResponse(MsgHeader* hdr) {
318 size_t encoded_size = 0;
319 uint32_t written_size;
320 size_t buffer_size = 0;
321 pb_ostream_t ostream;
322 bool success = false;
323
324 pthread_mutex_lock(&write_lock);
325
326 if ((success = pb_get_encoded_size(&encoded_size, MsgHeader_fields,
327 hdr)) && encoded_size <= INT32_MAX && commandFd != -1) {
328 buffer_size = encoded_size + sizeof(uint32_t);
329 uint8_t buffer[buffer_size];
330 written_size = htonl((uint32_t) encoded_size);
331 ostream = pb_ostream_from_buffer(buffer, buffer_size);
332 pb_write(&ostream, (uint8_t *)&written_size, sizeof(written_size));
333 success = pb_encode(&ostream, MsgHeader_fields, hdr);
334
335 if (success) {
336 RLOGD("Size: %d (0x%x) Size as written: 0x%x", encoded_size, encoded_size,
337 written_size);
338 log_hex("onRequestComplete", &buffer[sizeof(written_size)], encoded_size);
339 RLOGI("[%d] < SAP RESPONSE type: %d. id: %d. error: %d",
340 hdr->token, hdr->type, hdr->id,hdr->error );
341
342 if ( 0 != blockingWrite_helper(commandFd, buffer, buffer_size)) {
343 RLOGE("Error %d while writing to fd", errno);
344 } else {
345 RLOGD("Write successful");
346 }
347 } else {
348 RLOGE("Error while encoding response of type %d id %d buffer_size: %d: %s.",
349 hdr->type, hdr->id, buffer_size, PB_GET_ERROR(&ostream));
350 }
351 } else {
352 RLOGE("Not sending response type %d: encoded_size: %u. commandFd: %d. encoded size result: %d",
353 hdr->type, encoded_size, commandFd, success);
354 }
355
356 pthread_mutex_unlock(&write_lock);
357}
358
359void RilSapSocket::onUnsolicitedResponse(int unsolResponse, void *data, size_t datalen) {
360 MsgHeader *hdr = new MsgHeader;
361 pb_bytes_array_t *payload = (pb_bytes_array_t *)
362 calloc(1, sizeof(pb_bytes_array_t) + datalen);
363 if (hdr && payload) {
364 memcpy(payload->bytes, data, datalen);
365 payload->size = datalen;
366 hdr->payload = payload;
367 hdr->type = MsgType_UNSOL_RESPONSE;
368 hdr->id = (MsgId)unsolResponse;
369 hdr->error = Error_RIL_E_SUCCESS;
370 sendResponse(hdr);
371 delete hdr;
372 }
373}
374
375void RilSapSocket::pushRecord(void *p_record, size_t recordlen) {
376 int ret;
377 SapSocketRequest *recv = (SapSocketRequest*)malloc(sizeof(SapSocketRequest));
378 MsgHeader *reqHeader;
379 pb_istream_t stream;
380
381 stream = pb_istream_from_buffer((uint8_t *)p_record, recordlen);
382 reqHeader = (MsgHeader *)malloc(sizeof (MsgHeader));
383 memset(reqHeader, 0, sizeof(MsgHeader));
384
385 log_hex("BtSapTest-Payload", (const uint8_t*)p_record, recordlen);
386
387 if (!pb_decode(&stream, MsgHeader_fields, reqHeader) ) {
388 RLOGE("Error decoding protobuf buffer : %s", PB_GET_ERROR(&stream));
389 } else {
390 recv->token = reqHeader->token;
391 recv->curr = reqHeader;
392 recv->socketId = id;
393
394 dispatchQueue.enqueue(recv);
395 }
396}
397
398void RilSapSocket::sendDisconnect() {
399 MsgHeader *hdr = new MsgHeader;
400 pb_bytes_array_t *payload ;
401 size_t encoded_size = 0;
402 uint32_t written_size;
403 size_t buffer_size = 0;
404 pb_ostream_t ostream;
405 bool success = false;
406 ssize_t written_bytes;
407
408 RIL_SIM_SAP_DISCONNECT_REQ disconnectReq;
409
410 if ((success = pb_get_encoded_size(&encoded_size, RIL_SIM_SAP_DISCONNECT_REQ_fields,
411 &disconnectReq)) && encoded_size <= INT32_MAX) {
412 buffer_size = encoded_size + sizeof(uint32_t);
413 uint8_t buffer[buffer_size];
414 written_size = htonl((uint32_t) encoded_size);
415 ostream = pb_ostream_from_buffer(buffer, buffer_size);
416 pb_write(&ostream, (uint8_t *)&written_size, sizeof(written_size));
417 success = pb_encode(&ostream, RIL_SIM_SAP_DISCONNECT_REQ_fields, buffer);
418
419 if(success) {
420 pb_bytes_array_t *payload = (pb_bytes_array_t *)
421 calloc(1,sizeof(pb_bytes_array_t) + written_size);
422
423 memcpy(payload->bytes, buffer, written_size);
424 payload->size = written_size;
425 hdr->payload = payload;
426 hdr->type = MsgType_REQUEST;
427 hdr->id = MsgId_RIL_SIM_SAP_DISCONNECT;
428 hdr->error = Error_RIL_E_SUCCESS;
429 dispatchDisconnect(hdr);
430 }
431 else {
432 RLOGE("Encode failed in send disconnect!");
433 delete hdr;
434 free(payload);
435 }
436 }
437}
438
439void RilSapSocket::dispatchDisconnect(MsgHeader *req) {
440 SapSocketRequest* currRequest=(SapSocketRequest*)malloc(sizeof(SapSocketRequest));
441 currRequest->token = -1;
442 currRequest->curr = req;
443 currRequest->p_next = NULL;
444 currRequest->socketId = (RIL_SOCKET_ID)99;
445
446 RLOGD("Sending disconnect on command close!");
447
448#if defined(ANDROID_MULTI_SIM)
449 uimFuncs->onRequest(req->id, req->payload->bytes, req->payload->size, currRequest, id);
450#else
451 uimFuncs->onRequest(req->id, req->payload->bytes, req->payload->size, currRequest);
452#endif
453}
454
455void RilSapSocket::onCommandsSocketClosed() {
456 sendDisconnect();
457 RLOGE("Socket command closed");
458}