Fixed the build error for riscv64
[platform/core/connectivity/smartcard-plugin-uicc.git] / UICCTerminal.cpp
1 /*
2  * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
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 /* standard library header */
18 #include <cstdio>
19 #include <cstring>
20 #include <unistd.h>
21 #include <sys/time.h>
22
23 /* SLP library header */
24
25 /* local header */
26 #include "smartcard-types.h"
27 #include "Debug.h"
28 #include "TerminalInterface.h"
29 #include "UICCTerminal.h"
30
31 #ifndef EXPORT_API
32 #define EXPORT_API __attribute__((visibility("default")))
33 #endif
34
35 typedef struct _callback_param_t
36 {
37         void *callback;
38         void *param;
39 }
40 callback_param_t;
41
42 using namespace smartcard_service_api;
43
44 static const char *se_name = "SIM1";
45
46 /* below functions will be called when dlopen or dlclose is called */
47
48 typedef struct _context_s
49 {
50         GMainLoop *loop;
51         void *resp;
52 }
53 context_s;
54
55 void __attribute__ ((constructor)) lib_init()
56 {
57 }
58
59 void __attribute__ ((destructor)) lib_fini()
60 {
61 }
62
63 /* below three functions must be implemented */
64 extern "C" EXPORT_API const char *get_name()
65 {
66         return se_name;
67 }
68
69 extern "C" EXPORT_API void *create_instance()
70 {
71         return (void *)UICCTerminal::getInstance();
72 }
73
74 extern "C" EXPORT_API void destroy_instance(void *instance)
75 {
76         UICCTerminal *inst = (UICCTerminal *)instance;
77         if (inst == UICCTerminal::getInstance())
78         {
79                 inst->finalize();
80         }
81         else
82         {
83                 _ERR("instance is invalid : getInstance [%p], instance [%p]",
84                         UICCTerminal::getInstance(), instance);
85         }
86 }
87
88 /* LCOV_EXCL_START */
89 static void _uiccTransmitCallback(TapiHandle *handle, int result,
90         void *data, void *user_data)
91 {
92         TelSimAccessResult_t access_rt = (TelSimAccessResult_t)result;
93         TelSimApduResp_t *apdu = (TelSimApduResp_t *)data;
94         callback_param_t *param = (callback_param_t *)user_data;
95
96         if (param != NULL)
97         {
98                 if (param->callback != NULL)
99                 {
100                         terminalTransmitCallback callback =
101                                 (terminalTransmitCallback)param->callback;
102
103                         if (apdu != NULL && apdu->apdu_resp_len > 0)
104                         {
105                                 callback(apdu->apdu_resp, apdu->apdu_resp_len,
106                                         access_rt, param->param);
107                         }
108                         else
109                         {
110                                 callback(NULL, 0, access_rt, param->param);
111                         }
112                 }
113
114                 delete param;
115         }
116         else
117         {
118                 _ERR("invalid param");
119         }
120 }
121
122 static void _uiccGetATRCallback(TapiHandle *handle, int result,
123         void *data, void *user_data)
124 {
125         TelSimAccessResult_t access_rt = (TelSimAccessResult_t)result;
126         TelSimAtrResp_t *atr  = (TelSimAtrResp_t *)data;
127         callback_param_t *param = (callback_param_t *)user_data;
128
129         if (param != NULL)
130         {
131                 if (param->callback != NULL)
132                 {
133                         terminalGetATRCallback callback =
134                                 (terminalGetATRCallback)param->callback;
135
136                         if (atr != NULL && atr->atr_resp_len > 0)
137                         {
138                                 callback(atr->atr_resp, atr->atr_resp_len,
139                                         access_rt, param->param);
140                         }
141                         else
142                         {
143                                 callback(NULL, 0, access_rt, param->param);
144                         }
145                 }
146
147                 delete param;
148         }
149         else
150         {
151                 _ERR("invalid param");
152         }
153 }
154
155 static void _uiccCallback_sync(TapiHandle *handle, int result,
156         void *data, void *user_data)
157 {
158         context_s* context = (context_s*)user_data;
159
160         if(result == TAPI_SIM_ACCESS_SUCCESS)
161                 context->resp = data;
162
163         g_main_loop_quit(context->loop);
164         g_main_loop_unref(context->loop);
165 }
166 /* LCOV_EXCL_STOP */
167
168 namespace smartcard_service_api
169 {
170         UICCTerminal::UICCTerminal() : Terminal()
171         {
172                 name = (char *)se_name;
173
174                 initialize();
175         }
176
177         UICCTerminal::~UICCTerminal()
178         {
179                 finalize();
180         }
181
182         UICCTerminal *UICCTerminal::getInstance()
183         {
184                 static UICCTerminal instance;
185
186                 return &instance;
187         }
188
189         bool UICCTerminal::initialize()
190         {
191                 _BEGIN();
192
193                 if (initialized == false)
194                 {
195 //                      char **cpList = NULL;
196 //
197 //                      cpList = tel_get_cp_name_list();
198
199                         handle = tel_init(NULL);
200                         if (handle != NULL)
201                         {
202                                 int error;
203
204                                 error = tel_register_noti_event(handle,
205                                         TAPI_NOTI_SIM_STATUS,
206                                         &UICCTerminal::uiccStatusNotiCallback,
207                                         this);
208                                 if (error < 0) {
209                                         _ERR("tel_register_noti_event failed, [%d]", error);
210                                 }
211
212                                 initialized = true;
213                         }
214                         else
215                         {
216                                 _ERR("tel_init failed");
217                         }
218                 }
219
220                 _END();
221
222                 return initialized;
223         }
224
225         void UICCTerminal::finalize()
226         {
227                 _BEGIN();
228
229                 if (isInitialized())
230                 {
231                         if (tel_deregister_noti_event(handle,
232                                 TAPI_NOTI_SIM_STATUS) < 0) {
233                                 _ERR("tel_deregister_noti_event failed");
234                         }
235
236                         tel_deinit(handle);
237
238                         initialized = false;
239                 }
240
241                 _END();
242         }
243
244         bool UICCTerminal::open()
245         {
246                 /* no need to open */
247                 return true;
248         }
249
250         void UICCTerminal::close()
251         {
252                 /* no need to close */
253         }
254
255         int UICCTerminal::transmitSync(const ByteArray &command,
256                 ByteArray &response)
257         {
258                 int result = SCARD_ERROR_OK;
259
260                 _BEGIN();
261
262                 SCOPE_LOCK(mutex)
263                 {
264                         if (command.size() > 0)
265                         {
266                                 TelSimApduResp_t *resp = NULL;
267                                 TelSimApdu_t apdu_data = { 0, };
268                                 context_s context = { NULL, resp };
269
270                                 context.loop = g_main_loop_new(NULL, false);
271
272                                 apdu_data.apdu = (uint8_t *)command.getBuffer();
273                                 apdu_data.apdu_len = command.size();
274
275                                 result = tel_req_sim_apdu(handle, &apdu_data,
276                                         _uiccCallback_sync, &context);
277                                 if (result != 0)
278                                 {
279                                         _ERR("tel_req_sim_apdu failed [%d]", result);
280
281                                         result = SCARD_ERROR_IO_FAILED;
282                                 }
283                                 else
284                                 {
285                                         g_main_loop_run(context.loop);
286                                         response.assign(((TelSimApduResp_t *)context.resp)->apdu_resp,
287                                                 ((TelSimApduResp_t *)context.resp)->apdu_resp_len);
288                                 }
289                         }
290                         else
291                         {
292                                 _ERR("apdu is empty");
293
294                                 result = SCARD_ERROR_ILLEGAL_PARAM;
295                         }
296                 }
297
298                 _END();
299
300                 return result;
301         }
302
303         int UICCTerminal::getATRSync(ByteArray &atr)
304         {
305                 int result = SCARD_ERROR_OK;
306
307                 _BEGIN();
308
309                 SCOPE_LOCK(mutex)
310                 {
311                         TelSimAtrResp_t *resp = NULL;
312                         context_s context = { NULL, resp };
313
314                         context.loop = g_main_loop_new(NULL, false);
315
316                         result = tel_req_sim_atr(handle,
317                                 _uiccCallback_sync, &context);
318                         if(result != 0)
319                         {
320                                 _ERR("tel_req_sim_atr failed [%d]", result);
321
322                                 result = SCARD_ERROR_IO_FAILED;
323                         }
324                         else
325                         {
326                                 g_main_loop_run(context.loop);
327
328                                 if((TelSimAtrResp_t *)context.resp != NULL &&
329                                                 ((TelSimAtrResp_t *)context.resp)->atr_resp != NULL )
330                                 {
331                                         atr.assign(((TelSimAtrResp_t *)context.resp)->atr_resp,
332                                                 ((TelSimAtrResp_t *)context.resp)->atr_resp_len);
333                                 }
334                         }
335                 }
336
337                 _END();
338
339                 return result;
340         }
341
342         /* LCOV_EXCL_START */
343         int UICCTerminal::transmit(const ByteArray &command,
344                 terminalTransmitCallback callback, void *userParam)
345         {
346                 int result = SCARD_ERROR_OK;
347
348                 _BEGIN();
349
350                 SCOPE_LOCK(mutex)
351                 {
352                         if (command.size() > 0)
353                         {
354                                 TelSimApdu_t apdu_data = { 0, };
355                                 callback_param_t *param = NULL;
356
357                                 apdu_data.apdu = (uint8_t *)command.getBuffer();
358                                 apdu_data.apdu_len = command.size();
359
360                                 param = new callback_param_t();
361                                 param->callback = (void *)callback;
362                                 param->param = userParam;
363
364                                 result = tel_req_sim_apdu(handle, &apdu_data,
365                                         _uiccTransmitCallback, param);
366                                 if (result == 0)
367                                 {
368                                         _DBG("tel_req_sim_apdu request is success");
369                                 }
370                                 else
371                                 {
372                                         _ERR("tel_req_sim_apdu failed [%d]", result);
373                                         result = SCARD_ERROR_IO_FAILED;
374                                 }
375                         }
376                         else
377                         {
378                                 _ERR("apdu is empty");
379                                 result = SCARD_ERROR_ILLEGAL_PARAM;
380                         }
381                 }
382
383                 _END();
384
385                 return result;
386         }
387
388         int UICCTerminal::getATR(terminalGetATRCallback callback,
389                 void *userParam)
390         {
391                 int result = SCARD_ERROR_OK;
392
393                 _BEGIN();
394
395                 SCOPE_LOCK(mutex)
396                 {
397                         callback_param_t *param = NULL;
398
399                         param = new callback_param_t();
400                         param->callback = (void *)callback;
401                         param->param = userParam;
402
403                         result = tel_req_sim_atr(handle,
404                                 _uiccGetATRCallback, param);
405                         if (result == 0)
406                         {
407                                 _DBG("tel_req_sim_atr request is success");
408                         }
409                         else
410                         {
411                                 _ERR("tel_req_sim_atr failed [%d]", result);
412                                 result = SCARD_ERROR_IO_FAILED;
413                         }
414                 }
415
416                 _END();
417
418                 return result;
419         }
420         /* LCOV_EXCL_STOP */
421
422         bool UICCTerminal::isSecureElementPresence() const
423         {
424                 bool result = false;
425                 int error = 0;
426                 TelSimCardStatus_t state = (TelSimCardStatus_t)0;
427                 int cardChanged = 0;
428
429                 _BEGIN();
430
431                 error = tel_get_sim_init_info(handle, &state, &cardChanged);
432                 if (error == 0)
433                 {
434                         if (state == TAPI_SIM_STATUS_SIM_INIT_COMPLETED)
435                         {
436                                 result = true;
437                         }
438                         else
439                         {
440                                 _ERR("sim is not initialized, state [%d]", state);
441                         }
442                 }
443                 else
444                 {
445                         _ERR("tel_get_sim_init_info failed, [%d]", error);
446                 }
447
448                 _END();
449
450                 return result;
451         }
452
453         /* LCOV_EXCL_START */
454         void UICCTerminal::uiccStatusNotiCallback(TapiHandle *handle,
455                 const char *noti_id, void *data, void *user_data)
456         {
457                 UICCTerminal *instance = (UICCTerminal *)user_data;
458                 TelSimCardStatus_t *status = (TelSimCardStatus_t *)data;
459
460                 switch (*status)
461                 {
462                 case TAPI_SIM_STATUS_SIM_INIT_COMPLETED :
463                         _DBG("TAPI_SIM_STATUS_SIM_INIT_COMPLETED");
464
465                         if (instance->statusCallback != NULL)
466                         {
467                                 instance->statusCallback((void *)se_name,
468                                         NOTIFY_SE_AVAILABLE, 0, NULL);
469                         }
470                         break;
471
472                 case TAPI_SIM_STATUS_CARD_REMOVED :
473                         _DBG("TAPI_SIM_STATUS_CARD_REMOVED");
474
475                         if (instance->statusCallback != NULL)
476                         {
477                                 instance->statusCallback((void *)se_name,
478                                         NOTIFY_SE_NOT_AVAILABLE, 0, NULL);
479                         }
480                         break;
481
482                 default :
483                         /* ignore notification */
484                         break;
485                 }
486         }
487         /* LCOV_EXCL_STOP */
488 } /* namespace smartcard_service_api */