1 /* 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 #undef LOG_TAG 25 #define LOG_TAG "RIL_UIM_SOCKET" 26 #include <utils/Log.h> 27 #include <arpa/inet.h> 28 #include <errno.h> 29 30 static RilSapSocket::RilSapSocketList *head = NULL; 31 32 void ril_sap_on_request_complete ( 33 RIL_Token t, RIL_Errno e, 34 void *response, size_t responselen 35 ); 36 37 void ril_sap_on_unsolicited_response ( 38 int unsolResponse, const void *data, 39 size_t datalen 40 ); 41 extern "C" void 42 RIL_requestTimedCallback (RIL_TimedCallback callback, void *param, 43 const struct timeval *relativeTime); 44 45 struct RIL_Env RilSapSocket::uimRilEnv = { 46 .OnRequestComplete = RilSapSocket::sOnRequestComplete, 47 .OnUnsolicitedResponse = RilSapSocket::sOnUnsolicitedResponse, 48 .RequestTimedCallback = RIL_requestTimedCallback 49 }; 50 51 void RilSapSocket::sOnRequestComplete (RIL_Token t, 52 RIL_Errno e, 53 void *response, 54 size_t responselen) { 55 RilSapSocket *sap_socket; 56 SapSocketRequest *request = (SapSocketRequest*) t; 57 58 RLOGD("Socket id:%d", request->socketId); 59 60 sap_socket = getSocketById(request->socketId); 61 62 if (sap_socket) { 63 sap_socket->onRequestComplete(t,e,response,responselen); 64 } else { 65 RLOGE("Invalid socket id"); 66 if (request->curr->payload) { 67 free(request->curr->payload); 68 } 69 free(request->curr); 70 free(request); 71 } 72 } 73 74 #if defined(ANDROID_MULTI_SIM) 75 void RilSapSocket::sOnUnsolicitedResponse(int unsolResponse, 76 const void *data, 77 size_t datalen, 78 RIL_SOCKET_ID socketId) { 79 RilSapSocket *sap_socket = getSocketById(socketId); 80 if (sap_socket) { 81 sap_socket->onUnsolicitedResponse(unsolResponse, (void *)data, datalen); 82 } 83 } 84 #else 85 void RilSapSocket::sOnUnsolicitedResponse(int unsolResponse, 86 const void *data, 87 size_t datalen) { 88 RilSapSocket *sap_socket = getSocketById(RIL_SOCKET_1); 89 sap_socket->onUnsolicitedResponse(unsolResponse, (void *)data, datalen); 90 } 91 #endif 92 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; 100 } 101 } 102 103 RilSapSocket *RilSapSocket::getSocketById(RIL_SOCKET_ID socketId) { 104 RilSapSocket *sap_socket; 105 RilSapSocketList *current = head; 106 107 RLOGD("Entered getSocketById"); 108 printList(); 109 110 while(NULL != current) { 111 if(socketId == current->socket->id) { 112 sap_socket = current->socket; 113 return sap_socket; 114 } 115 current = current->next; 116 } 117 return NULL; 118 } 119 120 void RilSapSocket::initSapSocket(const char *socketName, 121 RIL_RadioFunctions *uimFuncs) { 122 123 if (strcmp(socketName, "sap_uim_socket1") == 0) { 124 if(!SocketExists(socketName)) { 125 addSocketToList(socketName, RIL_SOCKET_1, uimFuncs); 126 } 127 } 128 129 #if (SIM_COUNT >= 2) 130 if (strcmp(socketName, "sap_uim_socket2") == 0) { 131 if(!SocketExists(socketName)) { 132 addSocketToList(socketName, RIL_SOCKET_2, uimFuncs); 133 } 134 } 135 #endif 136 137 #if (SIM_COUNT >= 3) 138 if (strcmp(socketName, "sap_uim_socket3") == 0) { 139 if(!SocketExists(socketName)) { 140 addSocketToList(socketName, RIL_SOCKET_3, uimFuncs); 141 } 142 } 143 #endif 144 145 #if (SIM_COUNT >= 4) 146 if (strcmp(socketName, "sap_uim_socket4") == 0) { 147 if(!SocketExists(socketName)) { 148 addSocketToList(socketName, RIL_SOCKET_4, uimFuncs); 149 } 150 } 151 #endif 152 } 153 154 void RilSapSocket::addSocketToList(const char *socketName, RIL_SOCKET_ID socketid, 155 RIL_RadioFunctions *uimFuncs) { 156 RilSapSocket* socket = NULL; 157 RilSapSocketList *current; 158 159 if(!SocketExists(socketName)) { 160 socket = new RilSapSocket(socketName, socketid, uimFuncs); 161 RilSapSocketList* listItem = (RilSapSocketList*)malloc(sizeof(RilSapSocketList)); 162 if (!listItem) { 163 RLOGE("addSocketToList: OOM"); 164 return; 165 } 166 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 186 bool 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 198 void* RilSapSocket::processRequestsLoop(void) { 199 RLOGI("UIM_SOCKET:Request loop started"); 200 201 while(true) { 202 SapSocketRequest *req = dispatchQueue.dequeue(); 203 204 RLOGI("New request from the dispatch Queue"); 205 206 if (req != NULL) { 207 dispatchRequest(req->curr); 208 free(req); 209 } else { 210 RLOGE("Fetched null buffer from queue!"); 211 } 212 } 213 return NULL; 214 } 215 216 RilSapSocket::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 225 #define BYTES_PER_LINE 16 226 227 #define NIBBLE_TO_HEX(n) ({ \ 228 uint8_t __n = (uint8_t) n & 0x0f; \ 229 __nibble >= 10 ? 'A' + __n - 10: '0' + __n; \ 230 }) 231 232 #define HEX_HIGH(b) ({ \ 233 uint8_t __b = (uint8_t) b; \ 234 uint8_t __nibble = (__b >> 4) & 0x0f; \ 235 NIBBLE_TO_HEX(__nibble); \ 236 }) 237 238 #define HEX_LOW(b) ({ \ 239 uint8_t __b = (uint8_t) b; \ 240 uint8_t __nibble = __b & 0x0f; \ 241 NIBBLE_TO_HEX(__nibble); \ 242 }) 243 244 void 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 268 void RilSapSocket::dispatchRequest(MsgHeader *req) { 269 // SapSocketRequest will be deallocated in onRequestComplete() 270 SapSocketRequest* currRequest=(SapSocketRequest*)malloc(sizeof(SapSocketRequest)); 271 if (!currRequest) { 272 RLOGE("dispatchRequest: OOM"); 273 // Free MsgHeader allocated in pushRecord() 274 free(req); 275 return; 276 } 277 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 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; 303 304 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) { 314 memcpy(rsp.payload->bytes, response, response_len); 315 rsp.payload->size = response_len; 316 } else { 317 rsp.payload->size = 0; 318 } 319 320 RLOGE("Token:%d, MessageId:%d", hdr->token, hdr->id); 321 322 sendResponse(&rsp); 323 free(rsp.payload); 324 } 325 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); 334 } 335 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; 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 = (uint8_t*)malloc(buffer_size); 349 if (!buffer) { 350 RLOGE("sendResponse: OOM"); 351 pthread_mutex_unlock(&write_lock); 352 return; 353 } 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); 358 359 if (success) { 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 ); 365 366 if ( 0 != blockingWrite_helper(commandFd, buffer, buffer_size)) { 367 RLOGE("Error %d while writing to fd", errno); 368 } else { 369 RLOGD("Write successful"); 370 } 371 } else { 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)); 374 } 375 free(buffer); 376 } else { 377 RLOGE("Not sending response type %d: encoded_size: %zu. commandFd: %d. encoded size result:\ 378 %d", hdr->type, encoded_size, commandFd, success); 379 } 380 381 pthread_mutex_unlock(&write_lock); 382 } 383 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); 388 if (!payload) { 389 RLOGE("onUnsolicitedResponse: OOM"); 390 return; 391 } 392 memcpy(payload->bytes, data, datalen); 393 payload->size = datalen; 394 MsgHeader rsp; 395 rsp.payload = payload; 396 rsp.type = MsgType_UNSOL_RESPONSE; 397 rsp.id = (MsgId)unsolResponse; 398 rsp.error = Error_RIL_E_SUCCESS; 399 sendResponse(&rsp); 400 free(payload); 401 } 402 } 403 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)); 408 if (!reqHeader) { 409 RLOGE("pushRecord: OOM"); 410 return; 411 } 412 memset(reqHeader, 0, sizeof(MsgHeader)); 413 414 log_hex("BtSapTest-Payload", (const uint8_t*)p_record, recordlen); 415 416 if (!pb_decode(&stream, MsgHeader_fields, reqHeader) ) { 417 RLOGE("Error decoding protobuf buffer : %s", PB_GET_ERROR(&stream)); 418 free(reqHeader); 419 } else { 420 // SapSocketRequest will be deallocated in processRequestsLoop() 421 SapSocketRequest *recv = (SapSocketRequest*)malloc(sizeof(SapSocketRequest)); 422 if (!recv) { 423 RLOGE("pushRecord: OOM"); 424 free(reqHeader); 425 return; 426 } 427 recv->token = reqHeader->token; 428 recv->curr = reqHeader; 429 recv->socketId = id; 430 431 dispatchQueue.enqueue(recv); 432 } 433 } 434 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; 441 442 RIL_SIM_SAP_DISCONNECT_REQ disconnectReq; 443 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); 448 if (!buffer) { 449 RLOGE("sendDisconnect: OOM"); 450 return; 451 } 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); 456 457 if(success) { 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); 461 if (!payload) { 462 RLOGE("sendDisconnect: OOM"); 463 return; 464 } 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)); 469 if (!hdr) { 470 RLOGE("sendDisconnect: OOM"); 471 free(payload); 472 return; 473 } 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); 479 } 480 else { 481 RLOGE("Encode failed in send disconnect!"); 482 } 483 free(buffer); 484 } 485 } 486 487 void RilSapSocket::dispatchDisconnect(MsgHeader *req) { 488 // SapSocketRequest will be deallocated in sOnRequestComplete() 489 SapSocketRequest* currRequest=(SapSocketRequest*)malloc(sizeof(SapSocketRequest)); 490 if (!currRequest) { 491 RLOGE("dispatchDisconnect: OOM"); 492 // Free memory allocated in sendDisconnect 493 free(req->payload); 494 free(req); 495 return; 496 } 497 currRequest->token = -1; 498 currRequest->curr = req; 499 currRequest->p_next = NULL; 500 currRequest->socketId = (RIL_SOCKET_ID)99; 501 502 RLOGD("Sending disconnect on command close!"); 503 504 #if defined(ANDROID_MULTI_SIM) 505 uimFuncs->onRequest(req->id, req->payload->bytes, req->payload->size, currRequest, id); 506 #else 507 uimFuncs->onRequest(req->id, req->payload->bytes, req->payload->size, currRequest); 508 #endif 509 } 510 511 void RilSapSocket::onCommandsSocketClosed() { 512 sendDisconnect(); 513 RLOGE("Socket command closed"); 514 } 515