OSDN Git Service

DO NOT MERGE
[android-x86/hardware-ril.git] / libril / RilSapSocket.cpp
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 }