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 #define LOG_TAG "RIL_UIM_SOCKET" 25 #include <utils/Log.h> 26 #include <arpa/inet.h> 27 #include <errno.h> 28 29 static RilSapSocket::RilSapSocketList *head = NULL; 30 31 void ril_sap_on_request_complete ( 32 RIL_Token t, RIL_Errno e, 33 void *response, size_t responselen 34 ); 35 36 void ril_sap_on_unsolicited_response ( 37 int unsolResponse, const void *data, 38 size_t datalen 39 ); 40 extern "C" void 41 RIL_requestTimedCallback (RIL_TimedCallback callback, void *param, 42 const struct timeval *relativeTime); 43 44 struct RIL_Env RilSapSocket::uimRilEnv = { 45 .OnRequestComplete = RilSapSocket::sOnRequestComplete, 46 .OnUnsolicitedResponse = RilSapSocket::sOnUnsolicitedResponse, 47 .RequestTimedCallback = RIL_requestTimedCallback 48 }; 49 50 void 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 if (request->curr->payload) { 66 free(request->curr->payload); 67 } 68 free(request->curr); 69 free(request); 70 } 71 } 72 73 #if defined(ANDROID_MULTI_SIM) 74 void 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 84 void 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 92 void 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 102 RilSapSocket *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 119 void 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 153 void RilSapSocket::addSocketToList(const char *socketName, RIL_SOCKET_ID socketid, 154 RIL_RadioFunctions *uimFuncs) { 155 RilSapSocket* socket = NULL; 156 RilSapSocketList *current; 157 158 if(!SocketExists(socketName)) { 159 socket = new RilSapSocket(socketName, socketid, uimFuncs); 160 RilSapSocketList* listItem = (RilSapSocketList*)malloc(sizeof(RilSapSocketList)); 161 if (!listItem) { 162 RLOGE("addSocketToList: OOM"); 163 return; 164 } 165 listItem->socket = socket; 166 listItem->next = NULL; 167 168 RLOGD("Adding socket with id: %d", socket->id); 169 170 if(NULL == head) { 171 head = listItem; 172 head->next = NULL; 173 } 174 else { 175 current = head; 176 while(NULL != current->next) { 177 current = current->next; 178 } 179 current->next = listItem; 180 } 181 socket->socketInit(); 182 } 183 } 184 185 bool RilSapSocket::SocketExists(const char *socketName) { 186 RilSapSocketList* current = head; 187 188 while(NULL != current) { 189 if(strcmp(current->socket->name, socketName) == 0) { 190 return true; 191 } 192 current = current->next; 193 } 194 return false; 195 } 196 197 void* RilSapSocket::processRequestsLoop(void) { 198 RLOGI("UIM_SOCKET:Request loop started"); 199 200 while(true) { 201 SapSocketRequest *req = dispatchQueue.dequeue(); 202 203 RLOGI("New request from the dispatch Queue"); 204 205 if (req != NULL) { 206 dispatchRequest(req->curr); 207 free(req); 208 } else { 209 RLOGE("Fetched null buffer from queue!"); 210 } 211 } 212 return NULL; 213 } 214 215 RilSapSocket::RilSapSocket(const char *socketName, 216 RIL_SOCKET_ID socketId, 217 RIL_RadioFunctions *inputUimFuncs): 218 RilSocket(socketName, socketId) { 219 if (inputUimFuncs) { 220 uimFuncs = inputUimFuncs; 221 } 222 } 223 224 #define BYTES_PER_LINE 16 225 226 #define NIBBLE_TO_HEX(n) ({ \ 227 uint8_t __n = (uint8_t) n & 0x0f; \ 228 __nibble >= 10 ? 'A' + __n - 10: '0' + __n; \ 229 }) 230 231 #define HEX_HIGH(b) ({ \ 232 uint8_t __b = (uint8_t) b; \ 233 uint8_t __nibble = (__b >> 4) & 0x0f; \ 234 NIBBLE_TO_HEX(__nibble); \ 235 }) 236 237 #define HEX_LOW(b) ({ \ 238 uint8_t __b = (uint8_t) b; \ 239 uint8_t __nibble = __b & 0x0f; \ 240 NIBBLE_TO_HEX(__nibble); \ 241 }) 242 243 void log_hex(const char *who, const uint8_t *buffer, int length) { 244 char out[80]; 245 int source = 0; 246 int dest = 0; 247 int dest_len = sizeof(out); 248 int per_line = 0; 249 250 do { 251 dest += sprintf(out, "%8.8s [%8.8x] ", who, source); 252 for(; source < length && dest_len - dest > 3 && per_line < BYTES_PER_LINE; source++, 253 per_line ++) { 254 out[dest++] = HEX_HIGH(buffer[source]); 255 out[dest++] = HEX_LOW(buffer[source]); 256 out[dest++] = ' '; 257 } 258 if (dest < dest_len && (per_line == BYTES_PER_LINE || source >= length)) { 259 out[dest++] = 0; 260 per_line = 0; 261 dest = 0; 262 RLOGD("%s\n", out); 263 } 264 } while(source < length && dest < dest_len); 265 } 266 267 void RilSapSocket::dispatchRequest(MsgHeader *req) { 268 // SapSocketRequest will be deallocated in onRequestComplete() 269 SapSocketRequest* currRequest=(SapSocketRequest*)malloc(sizeof(SapSocketRequest)); 270 if (!currRequest) { 271 RLOGE("dispatchRequest: OOM"); 272 // Free MsgHeader allocated in pushRecord() 273 free(req); 274 return; 275 } 276 currRequest->token = req->token; 277 currRequest->curr = req; 278 currRequest->p_next = NULL; 279 currRequest->socketId = id; 280 281 pendingResponseQueue.enqueue(currRequest); 282 283 if (uimFuncs) { 284 RLOGI("[%d] > SAP REQUEST type: %d. id: %d. error: %d", 285 req->token, 286 req->type, 287 req->id, 288 req->error ); 289 290 #if defined(ANDROID_MULTI_SIM) 291 uimFuncs->onRequest(req->id, req->payload->bytes, req->payload->size, currRequest, id); 292 #else 293 uimFuncs->onRequest(req->id, req->payload->bytes, req->payload->size, currRequest); 294 #endif 295 } 296 } 297 298 void RilSapSocket::onRequestComplete(RIL_Token t, RIL_Errno e, void *response, 299 size_t response_len) { 300 SapSocketRequest* request= (SapSocketRequest*)t; 301 MsgHeader *hdr = request->curr; 302 303 MsgHeader rsp; 304 rsp.token = request->curr->token; 305 rsp.type = MsgType_RESPONSE; 306 rsp.id = request->curr->id; 307 rsp.error = (Error)e; 308 rsp.payload = (pb_bytes_array_t *)calloc(1, sizeof(pb_bytes_array_t) + response_len); 309 if (!rsp.payload) { 310 RLOGE("onRequestComplete: OOM"); 311 } else { 312 if (response && response_len > 0) { 313 memcpy(rsp.payload->bytes, response, response_len); 314 rsp.payload->size = response_len; 315 } else { 316 rsp.payload->size = 0; 317 } 318 319 RLOGE("Token:%d, MessageId:%d", hdr->token, hdr->id); 320 321 sendResponse(&rsp); 322 free(rsp.payload); 323 } 324 325 // Deallocate SapSocketRequest 326 if(!pendingResponseQueue.checkAndDequeue(hdr->id, hdr->token)) { 327 RLOGE("Token:%d, MessageId:%d", hdr->token, hdr->id); 328 RLOGE ("RilSapSocket::onRequestComplete: invalid Token or Message Id"); 329 } 330 331 // Deallocate MsgHeader 332 free(hdr); 333 } 334 335 void RilSapSocket::sendResponse(MsgHeader* hdr) { 336 size_t encoded_size = 0; 337 uint32_t written_size; 338 size_t buffer_size = 0; 339 pb_ostream_t ostream; 340 bool success = false; 341 342 pthread_mutex_lock(&write_lock); 343 344 if ((success = pb_get_encoded_size(&encoded_size, MsgHeader_fields, 345 hdr)) && encoded_size <= INT32_MAX && commandFd != -1) { 346 buffer_size = encoded_size + sizeof(uint32_t); 347 uint8_t buffer[buffer_size]; 348 written_size = htonl((uint32_t) encoded_size); 349 ostream = pb_ostream_from_buffer(buffer, buffer_size); 350 pb_write(&ostream, (uint8_t *)&written_size, sizeof(written_size)); 351 success = pb_encode(&ostream, MsgHeader_fields, hdr); 352 353 if (success) { 354 RLOGD("Size: %d (0x%x) Size as written: 0x%x", encoded_size, encoded_size, 355 written_size); 356 log_hex("onRequestComplete", &buffer[sizeof(written_size)], encoded_size); 357 RLOGI("[%d] < SAP RESPONSE type: %d. id: %d. error: %d", 358 hdr->token, hdr->type, hdr->id,hdr->error ); 359 360 if ( 0 != blockingWrite_helper(commandFd, buffer, buffer_size)) { 361 RLOGE("Error %d while writing to fd", errno); 362 } else { 363 RLOGD("Write successful"); 364 } 365 } else { 366 RLOGE("Error while encoding response of type %d id %d buffer_size: %d: %s.", 367 hdr->type, hdr->id, buffer_size, PB_GET_ERROR(&ostream)); 368 } 369 } else { 370 RLOGE("Not sending response type %d: encoded_size: %u. commandFd: %d. encoded size result: %d", 371 hdr->type, encoded_size, commandFd, success); 372 } 373 374 pthread_mutex_unlock(&write_lock); 375 } 376 377 void RilSapSocket::onUnsolicitedResponse(int unsolResponse, void *data, size_t datalen) { 378 if (data && datalen > 0) { 379 pb_bytes_array_t *payload = (pb_bytes_array_t *)calloc(1, 380 sizeof(pb_bytes_array_t) + datalen); 381 if (!payload) { 382 RLOGE("onUnsolicitedResponse: OOM"); 383 return; 384 } 385 memcpy(payload->bytes, data, datalen); 386 payload->size = datalen; 387 MsgHeader rsp; 388 rsp.payload = payload; 389 rsp.type = MsgType_UNSOL_RESPONSE; 390 rsp.id = (MsgId)unsolResponse; 391 rsp.error = Error_RIL_E_SUCCESS; 392 sendResponse(&rsp); 393 free(payload); 394 } 395 } 396 397 void RilSapSocket::pushRecord(void *p_record, size_t recordlen) { 398 pb_istream_t stream = pb_istream_from_buffer((uint8_t *)p_record, recordlen); 399 // MsgHeader will be deallocated in onRequestComplete() 400 MsgHeader *reqHeader = (MsgHeader *)malloc(sizeof (MsgHeader)); 401 if (!reqHeader) { 402 RLOGE("pushRecord: OOM"); 403 return; 404 } 405 memset(reqHeader, 0, sizeof(MsgHeader)); 406 407 log_hex("BtSapTest-Payload", (const uint8_t*)p_record, recordlen); 408 409 if (!pb_decode(&stream, MsgHeader_fields, reqHeader) ) { 410 RLOGE("Error decoding protobuf buffer : %s", PB_GET_ERROR(&stream)); 411 free(reqHeader); 412 } else { 413 // SapSocketRequest will be deallocated in processRequestsLoop() 414 SapSocketRequest *recv = (SapSocketRequest*)malloc(sizeof(SapSocketRequest)); 415 if (!recv) { 416 RLOGE("pushRecord: OOM"); 417 free(reqHeader); 418 return; 419 } 420 recv->token = reqHeader->token; 421 recv->curr = reqHeader; 422 recv->socketId = id; 423 424 dispatchQueue.enqueue(recv); 425 } 426 } 427 428 void RilSapSocket::sendDisconnect() { 429 size_t encoded_size = 0; 430 uint32_t written_size; 431 size_t buffer_size = 0; 432 pb_ostream_t ostream; 433 bool success = false; 434 435 RIL_SIM_SAP_DISCONNECT_REQ disconnectReq; 436 437 if ((success = pb_get_encoded_size(&encoded_size, RIL_SIM_SAP_DISCONNECT_REQ_fields, 438 &disconnectReq)) && encoded_size <= INT32_MAX) { 439 buffer_size = encoded_size + sizeof(uint32_t); 440 uint8_t buffer[buffer_size]; 441 written_size = htonl((uint32_t) encoded_size); 442 ostream = pb_ostream_from_buffer(buffer, buffer_size); 443 pb_write(&ostream, (uint8_t *)&written_size, sizeof(written_size)); 444 success = pb_encode(&ostream, RIL_SIM_SAP_DISCONNECT_REQ_fields, buffer); 445 446 if(success) { 447 // Buffer will be deallocated in sOnRequestComplete() 448 pb_bytes_array_t *payload = (pb_bytes_array_t *)calloc(1, 449 sizeof(pb_bytes_array_t) + written_size); 450 if (!payload) { 451 RLOGE("sendDisconnect: OOM"); 452 return; 453 } 454 memcpy(payload->bytes, buffer, written_size); 455 payload->size = written_size; 456 // MsgHeader will be deallocated in sOnRequestComplete() 457 MsgHeader *hdr = (MsgHeader *)malloc(sizeof(MsgHeader)); 458 if (!hdr) { 459 RLOGE("sendDisconnect: OOM"); 460 free(payload); 461 return; 462 } 463 hdr->payload = payload; 464 hdr->type = MsgType_REQUEST; 465 hdr->id = MsgId_RIL_SIM_SAP_DISCONNECT; 466 hdr->error = Error_RIL_E_SUCCESS; 467 dispatchDisconnect(hdr); 468 } 469 else { 470 RLOGE("Encode failed in send disconnect!"); 471 } 472 } 473 } 474 475 void RilSapSocket::dispatchDisconnect(MsgHeader *req) { 476 // SapSocketRequest will be deallocated in sOnRequestComplete() 477 SapSocketRequest* currRequest=(SapSocketRequest*)malloc(sizeof(SapSocketRequest)); 478 if (!currRequest) { 479 RLOGE("dispatchDisconnect: OOM"); 480 // Free memory allocated in sendDisconnect 481 free(req->payload); 482 free(req); 483 return; 484 } 485 currRequest->token = -1; 486 currRequest->curr = req; 487 currRequest->p_next = NULL; 488 currRequest->socketId = (RIL_SOCKET_ID)99; 489 490 RLOGD("Sending disconnect on command close!"); 491 492 #if defined(ANDROID_MULTI_SIM) 493 uimFuncs->onRequest(req->id, req->payload->bytes, req->payload->size, currRequest, id); 494 #else 495 uimFuncs->onRequest(req->id, req->payload->bytes, req->payload->size, currRequest); 496 #endif 497 } 498 499 void RilSapSocket::onCommandsSocketClosed() { 500 sendDisconnect(); 501 RLOGE("Socket command closed"); 502 } 503