Home | History | Annotate | Download | only in libril
      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 RilSapSocket::RilSapSocketList *head;
     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         free(request->curr);
     66         free(request);
     67     }
     68 }
     69 
     70 #if defined(ANDROID_MULTI_SIM)
     71 void 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
     81 void 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 
     89 void 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 
     99 RilSapSocket *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 
    116 void 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 
    150 void 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 
    178 bool 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 
    190 void* 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 
    209 RilSapSocket::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 
    218 int 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 
    242 void 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 
    266 void 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 
    290 void 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 
    317 void 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 
    359 void 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 
    375 void 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 
    398 void 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 
    439 void 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 
    455 void RilSapSocket::onCommandsSocketClosed() {
    456     sendDisconnect();
    457     RLOGE("Socket command closed");
    458 }
    459