Fixed a build error due to dlog update
[platform/core/api/smartcard.git] / src / SEService.cpp
1 /*
2  * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
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 <unistd.h>
19 #include <string.h>
20 #include <glib.h>
21 #include <glib-object.h>
22 #include <stdlib.h>
23
24 /* local header */
25 #include "Debug.h"
26 #include "SEService.h"
27 #include "ClientChannel.h"
28 #include "Reader.h"
29 #include "ClientGDBus.h"
30
31 /* LCOV_EXCL_START */
32
33 #ifndef EXTERN_API
34 #define EXTERN_API __attribute__((visibility("default")))
35 #endif
36
37 #define SHUTDOWN_DELAY          500000 /* us */
38 #define VERSION "3.2"
39
40 namespace smartcard_service_api
41 {
42         SEService::SEService() : SEServiceHelper(),
43                 handle(-1), context(NULL), handler(NULL), listener(NULL),
44                 version(VERSION)
45         {
46                 proxy = NULL;
47         }
48
49         SEService::SEService(void *user_data, serviceConnected handler)
50                 throw(ErrorIO &, ErrorIllegalParameter &) :
51                 SEServiceHelper(), handle(-1), context(NULL), listener(NULL),
52                 event_handler(NULL), event_handler_context(NULL),
53                 proxy(NULL), version(VERSION)
54         {
55                 initialize(user_data, handler);
56         }
57
58         SEService::SEService(void *user_data, SEServiceListener *listener)
59                 throw(ErrorIO &, ErrorIllegalParameter &) :
60                 SEServiceHelper(), handle(-1), handler(NULL),
61                 event_handler(NULL), event_handler_context(NULL),
62                 proxy(NULL), version(VERSION)
63         {
64                 initialize(user_data, listener);
65         }
66
67         SEService::SEService(void *user_data)
68                 throw(ErrorIO &, ErrorIllegalParameter &, ExceptionBase &) :
69                 SEServiceHelper(), handle(-1), handler(NULL), listener(NULL),
70                 event_handler(NULL), event_handler_context(NULL),
71                 proxy(NULL), version(VERSION)
72         {
73                 initializeSync(user_data);
74         }
75
76         SEService::~SEService()
77         {
78                 try
79                 {
80                         size_t i;
81
82                         shutdownSync();
83
84                         for (i = 0; i < readers.size(); i++)
85                         {
86                                 delete (Reader *)readers[i];
87                         }
88
89                         readers.clear();
90                 }
91                 catch (ExceptionBase &e)
92                 {
93                         _ERR("EXCEPTION : %s", e.what());
94                 }
95                 catch (...)
96                 {
97                         _ERR("EXCEPTION!!!");
98                 }
99         }
100
101         void SEService::reader_inserted(GObject *source_object,
102                 guint reader_id, gchar *reader_name, gpointer user_data)
103         {
104                 Reader *reader = NULL;
105                 SEService *service = (SEService *)user_data;
106
107                 _INFO("[MSG_NOTIFY_SE_INSERTED]");
108
109                 /* add readers */
110                 reader = new (std::nothrow)Reader(service->context,
111                         reader_name, GUINT_TO_POINTER(reader_id));
112
113                 if (reader != NULL) {
114                         service->readers.push_back(reader);
115                 } else {
116                         _ERR("alloc failed");
117                 }
118
119                 if (service->listener != NULL) {
120                         service->listener->eventHandler(service,
121                                 reader_name, 1, service->context);
122                 } else if (service->event_handler != NULL) {
123                         service->event_handler(reader_id, 1, service->context);
124                 } else {
125                         _DBG("listener is null");
126                 }
127         }
128
129         void SEService::reader_removed(GObject *source_object,
130                 guint reader_id, gchar *reader_name, gpointer user_data)
131         {
132                 SEService *service = (SEService *)user_data;
133                 size_t i;
134
135                 _INFO("[MSG_NOTIFY_SE_REMOVED]");
136
137                 for (i = 0; i < service->readers.size(); i++)
138                 {
139                         if (((Reader *)service->readers[i])->handle ==
140                                 GUINT_TO_POINTER(reader_id))
141                         {
142                                 ((Reader *)service->readers[i])->unavailable();
143                                 break;
144                         }
145                 }
146
147                 if (service->listener != NULL) {
148                         service->listener->eventHandler(service,
149                                 reader_name, 2, service->context);
150                 } else if (service->event_handler != NULL) {
151                         service->event_handler(reader_id, 2, service->context);
152                 } else {
153                         _DBG("listener is null");
154                 }
155         }
156
157         void SEService::se_service_shutdown_cb(GObject *source_object,
158                 GAsyncResult *res, gpointer user_data)
159         {
160                 SEService *service = (SEService *)user_data;
161                 gint result;
162                 GError *error = NULL;
163
164                 if (smartcard_service_se_service_call_shutdown_finish(
165                         SMARTCARD_SERVICE_SE_SERVICE(source_object),
166                         &result, res, &error) == true) {
167                         if (result == SCARD_ERROR_OK) {
168                                 service->connected = false;
169                         } else {
170                                 _ERR("smartcard_service_se_service_call_shutdown failed, [%d]", result);
171                         }
172                 } else {
173                         _ERR("smartcard_service_se_service_call_shutdown failed, [%s]", error->message);
174                         g_error_free(error);
175                 }
176         }
177
178         void SEService::se_service_cb(GObject *source_object,
179                 GAsyncResult *res, gpointer user_data)
180         {
181                 SEService *service = (SEService *)user_data;
182                 gint result;
183                 guint handle;
184                 GVariant *readers = NULL;
185                 GError *error = NULL;
186
187                 if (service == NULL) {
188                         _ERR("null parameter!!!");
189                         return;
190                 }
191
192                 if (smartcard_service_se_service_call_se_service_finish(
193                         SMARTCARD_SERVICE_SE_SERVICE(source_object),
194                         &result, &handle, &readers, res, &error) == true) {
195                         if (result == SCARD_ERROR_OK) {
196                                 service->connected = true;
197                                 service->handle = handle;
198                                 service->parseReaderInformation(readers);
199                         }
200                 } else {
201                         _ERR("smartcard_service_se_service_call_se_service failed, [%s]", error->message);
202                         g_error_free(error);
203
204                         result = SCARD_ERROR_IPC_FAILED;
205                 }
206
207                 if (service->handler != NULL) {
208                         service->handler(service, service->context);
209                 } else if (service->listener != NULL) {
210                         if (result == SCARD_ERROR_OK) {
211                                 service->listener->serviceConnected(service, service->context);
212                         } else {
213                                 service->listener->errorHandler(service, result, service->context);
214                         }
215                 }
216         }
217
218         void SEService::shutdown()
219         {
220                 shutdownSync();
221         }
222
223         void SEService::shutdownSync()
224         {
225                 if (connected == true)
226                 {
227                         uint32_t i;
228
229                         for (i = 0; i < readers.size(); i++)
230                         {
231                                 readers[i]->closeSessions();
232                         }
233
234                         gint result;
235                         GError *error = NULL;
236
237                         if (smartcard_service_se_service_call_shutdown_sync(
238                                 (SmartcardServiceSeService *)proxy,
239                                 handle,
240                                 &result,
241                                 NULL,
242                                 &error) == false) {
243                                 _ERR("smartcard_service_se_service_call_shutdown_sync failed, [%s]", error->message);
244
245                                 g_error_free(error);
246                         }
247
248                         /* wait at least 500ms */
249                         usleep(SHUTDOWN_DELAY);
250
251                         connected = false;
252                 }
253         }
254
255         bool SEService::_initialize() throw(ErrorIO &)
256         {
257                 bool result = false;
258
259                 _BEGIN();
260
261                 /* init default context */
262                 GError *error = NULL;
263
264                 proxy = smartcard_service_se_service_proxy_new_for_bus_sync(
265                         G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
266                         "org.tizen.SmartcardService",
267                         "/org/tizen/SmartcardService/SeService",
268                         NULL, &error);
269                 if (proxy == NULL)
270                 {
271                         _ERR("Can not create proxy : %s", error->message);
272                         g_error_free(error);
273                         return false;
274                 }
275
276                 g_signal_connect(proxy, "reader-inserted",
277                                 G_CALLBACK(&SEService::reader_inserted), this);
278
279                 g_signal_connect(proxy, "reader-removed",
280                                 G_CALLBACK(&SEService::reader_removed), this);
281
282                 /* request reader */
283                 smartcard_service_se_service_call_se_service(
284                         (SmartcardServiceSeService *)proxy,
285                         NULL,
286                         &SEService::se_service_cb,
287                         this);
288
289                 _END();
290
291                 return result;
292         }
293
294         int SEService::_initialize_sync_do_not_throw_exception()
295         {
296                 gint result;
297                 guint handle;
298                 GError *error = NULL;
299                 GVariant *readers = NULL;
300                 SEService *service = (SEService *)this;
301
302                 _BEGIN();
303
304                 /* init default context */
305
306                 proxy = smartcard_service_se_service_proxy_new_for_bus_sync(
307                         G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
308                         "org.tizen.SmartcardService",
309                         "/org/tizen/SmartcardService/SeService",
310                         NULL, &error);
311                 if (proxy == NULL)
312                 {
313                         _ERR("Can not create proxy : %s", error->message);
314                         g_error_free(error);
315                         return false;
316                 }
317
318                 g_signal_connect(proxy, "reader-inserted",
319                                 G_CALLBACK(&SEService::reader_inserted), this);
320
321                 g_signal_connect(proxy, "reader-removed",
322                                 G_CALLBACK(&SEService::reader_removed), this);
323
324                 /* request reader */
325                 if(smartcard_service_se_service_call_se_service_sync(
326                         (SmartcardServiceSeService *)proxy, &result, &handle, &readers, NULL, &error) == true)
327                 {
328                         if (result == SCARD_ERROR_OK) {
329                                 service->connected = true;
330                                 service->handle = handle;
331                                 service->parseReaderInformation(readers);
332                         } else {
333                                 _ERR("Initialize error : %d", result);
334                         }
335                 }
336
337                 if (service->handler != NULL) {
338                         service->handler(service, service->context);
339                 } else if (service->listener != NULL) {
340                         if (result == SCARD_ERROR_OK) {
341                                 service->listener->serviceConnected(service, service->context);
342                         } else {
343                                 service->listener->errorHandler(service, result, service->context);
344                         }
345                 }
346
347                 _END();
348
349                 return result;
350         }
351
352         int SEService::_initialize_sync() throw(ErrorIO &, ExceptionBase &)
353         {
354                 gint result;
355                 guint handle;
356                 GError *error = NULL;
357                 GVariant *readers = NULL;
358                 SEService *service = (SEService *)this;
359
360                 _BEGIN();
361
362                 /* init default context */
363
364                 proxy = smartcard_service_se_service_proxy_new_for_bus_sync(
365                         G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
366                         "org.tizen.SmartcardService",
367                         "/org/tizen/SmartcardService/SeService",
368                         NULL, &error);
369                 if (proxy == NULL)
370                 {
371                         _ERR("Can not create proxy : %s", error->message);
372                         g_error_free(error);
373                         return false;
374                 }
375
376                 g_signal_connect(proxy, "reader-inserted",
377                                 G_CALLBACK(&SEService::reader_inserted), this);
378
379                 g_signal_connect(proxy, "reader-removed",
380                                 G_CALLBACK(&SEService::reader_removed), this);
381
382                 /* request reader */
383                 if(smartcard_service_se_service_call_se_service_sync(
384                         (SmartcardServiceSeService *)proxy, &result, &handle, &readers, NULL, &error) == true) {
385                         if (result == SCARD_ERROR_OK) {
386                                 service->connected = true;
387                                 service->handle = handle;
388                                 service->parseReaderInformation(readers);
389                         } else {
390                                 throw ExceptionBase(result);
391                         }
392                 } else {
393                         _ERR("smartcard_service_se_service_call_se_service failed, [%s]", error->message);
394                         g_error_free(error);
395
396                         result = SCARD_ERROR_IPC_FAILED;
397                 }
398
399                 _END();
400
401                 return result;
402         }
403
404         bool SEService::initialize(void *context, serviceConnected handler)
405                 throw(ErrorIO &, ErrorIllegalParameter &)
406         {
407                 if (context == NULL)
408                 {
409                         throw ErrorIllegalParameter(SCARD_ERROR_ILLEGAL_PARAM);
410                 }
411
412                 this->context = context;
413                 this->handler = handler;
414
415                 return _initialize();
416         }
417
418         bool SEService::initialize(void *context, SEServiceListener *listener)
419                 throw(ErrorIO &, ErrorIllegalParameter &)
420         {
421                 if (context == NULL)
422                 {
423                         throw ErrorIllegalParameter(SCARD_ERROR_ILLEGAL_PARAM);
424                 }
425
426                 this->context = context;
427                 this->listener = listener;
428
429                 return _initialize_sync_do_not_throw_exception();
430         }
431
432         bool SEService::initializeSync(void *context)
433                 throw(ErrorIO &, ErrorIllegalParameter &, ExceptionBase &)
434         {
435                 this->context = context;
436
437                 _initialize_sync();
438                 return true;
439         }
440
441         void SEService::setEventHandler(se_service_event_cb cb, void *context)
442         {
443                 this->event_handler = cb;
444                 this->event_handler_context = context;
445         }
446
447         bool SEService::parseReaderInformation(GVariant *variant)
448         {
449                 Reader *reader = NULL;
450
451                 GVariantIter *iter;
452                 guint handle;
453                 gchar *name;
454
455                 g_variant_get(variant, "a(us)", &iter);
456
457                 while (g_variant_iter_loop(iter, "(us)", &handle, &name) == true)
458                 {
459                         SECURE_LOGD("Reader : name [%s], handle [%08x]", name, handle);
460
461                         /* add readers */
462                         reader = new (std::nothrow)Reader(GUINT_TO_POINTER(this->handle), name, GUINT_TO_POINTER(handle));
463                         if (reader == NULL)
464                         {
465                                 _ERR("alloc failed");
466                                 continue;
467                         }
468
469                         readers.push_back(reader);
470                 }
471
472                 g_variant_iter_free(iter);
473
474                 return true;
475         }
476
477         bool SEService::parseReaderInformation(unsigned int count,
478                 const ByteArray &data)
479         {
480                 size_t i;
481                 unsigned int offset = 0;
482                 unsigned int len = 0;
483                 void *handle = NULL;
484                 Reader *reader = NULL;
485                 char name[100];
486                 const uint8_t *buffer = NULL;
487
488
489                 for (i = 0; i < count && offset < data.size(); i++)
490                 {
491                         memset(name, 0, sizeof(name));
492
493                         buffer = data.getBuffer(offset);
494                         if(buffer == NULL)
495                                 continue;
496
497                         memcpy(&len, buffer, sizeof(len));
498                         offset += sizeof(len);
499
500                         buffer = data.getBuffer(offset);
501                         if(buffer == NULL)
502                                 return false;
503
504                         memcpy(name, buffer, len);
505                         offset += len;
506
507                         buffer = data.getBuffer(offset);
508                         if(buffer == NULL)
509                                 return false;
510
511                         memcpy(&handle, buffer, sizeof(handle));
512                         offset += sizeof(handle);
513
514                         SECURE_LOGD("Reader [%zu] : name [%s], handle [%p]", i, name, (void *)handle);
515
516                         /* add readers */
517                         reader = new (std::nothrow)Reader(context, name, handle);
518                         if (reader == NULL)
519                         {
520                                 _ERR("alloc failed");
521                                 continue;
522                         }
523
524                         readers.push_back(reader);
525                 }
526
527                 return true;
528         }
529 } /* namespace smartcard_service_api */
530
531 /* export C API */
532 #define SE_SERVICE_EXTERN_BEGIN \
533         if (handle != NULL) \
534         { \
535                 SEService *service = (SEService *)handle;
536
537 #define SE_SERVICE_EXTERN_END \
538         } \
539         else \
540         { \
541                 _ERR("Invalid param"); \
542         }
543
544 using namespace smartcard_service_api;
545
546 EXTERN_API se_service_h se_service_create_instance(void *user_data,
547         se_service_connected_cb callback)
548 {
549         SEService *service;
550
551         try
552         {
553                 service = new (std::nothrow)SEService(user_data, (serviceConnected)callback);
554         }
555         catch (...)
556         {
557                 service = NULL;
558         }
559
560         return (se_service_h)service;
561 }
562
563 EXTERN_API se_service_h se_service_create_instance_with_event_callback(
564         void *user_data, se_service_connected_cb connected,
565         se_service_event_cb event, se_sesrvice_error_cb error)
566 {
567         SEService *service;
568
569         try
570         {
571                 service = new (std::nothrow)SEService(user_data, (serviceConnected)connected);
572         }
573         catch (...)
574         {
575                 service = NULL;
576         }
577
578         return (se_service_h)service;
579 }
580
581 EXTERN_API se_service_h se_service_create_instance_sync(void *user_data,
582         int *result)
583 {
584         SEService *service;
585
586         try
587         {
588                 service = new (std::nothrow)SEService(user_data);
589         }
590         catch (ExceptionBase &e)
591         {
592                 *result = e.getErrorCode();
593                 service = NULL;
594         }
595         catch (...)
596         {
597                 *result = SCARD_ERROR_UNKNOWN;
598                 service = NULL;
599         }
600
601         return (se_service_h)service;
602 }
603
604 EXTERN_API int se_service_get_version(se_service_h handle, char **version_str)
605 {
606         int ret = 0;
607
608         SE_SERVICE_EXTERN_BEGIN;
609
610         *version_str = g_strdup(service->getVersion());
611
612         SE_SERVICE_EXTERN_END;
613
614         return ret;
615 }
616
617 EXTERN_API int se_service_get_readers_count(se_service_h handle)
618 {
619         int count = 0;
620
621         SE_SERVICE_EXTERN_BEGIN;
622
623         vector<ReaderHelper *> temp_readers;
624
625         temp_readers = service->getReaders();
626         count = temp_readers.size();
627
628         SE_SERVICE_EXTERN_END;
629
630         return count;
631 }
632
633 EXTERN_API int se_service_get_readers(se_service_h handle, int **readers, int *count)
634 {
635         int result = 0;
636
637         SE_SERVICE_EXTERN_BEGIN;
638
639         vector<ReaderHelper *> temp_readers;
640         size_t i;
641         int temp = 0;
642
643         temp_readers = service->getReaders();
644         if (temp_readers.size() > 0) {
645                 *readers = (int *)calloc(temp_readers.size(), sizeof(int));
646
647                 if(*readers == NULL)
648                 {
649                         *count = 0;
650                         return SCARD_ERROR_NOT_ENOUGH_RESOURCE;
651                 }
652
653                 for (i = 0; i < temp_readers.size(); i++)
654                 {
655                         if (temp_readers[i]->isSecureElementPresent()) {
656                                 (*readers)[i] = (long)temp_readers[i];
657                                 temp++;
658                         }
659                 }
660                 *count = temp;
661         } else {
662                 *count = 0;
663         }
664
665         SE_SERVICE_EXTERN_END;
666
667         return result;
668 }
669
670 EXTERN_API bool se_service_is_connected(se_service_h handle)
671 {
672         bool result = false;
673
674         SE_SERVICE_EXTERN_BEGIN;
675
676         result = service->isConnected();
677
678         SE_SERVICE_EXTERN_END;
679
680         return result;
681 }
682
683 EXTERN_API void se_service_shutdown(se_service_h handle)
684 {
685         SE_SERVICE_EXTERN_BEGIN;
686
687         service->shutdownSync();
688
689         SE_SERVICE_EXTERN_END;
690 }
691
692 EXTERN_API void se_service_set_event_handler(se_service_h handle,
693         se_service_event_cb event_handler, void *user_data)
694 {
695         SE_SERVICE_EXTERN_BEGIN;
696
697         service->setEventHandler(event_handler, user_data);
698
699         SE_SERVICE_EXTERN_END;
700 }
701
702 EXTERN_API void se_service_unset_event_handler(se_service_h handle)
703 {
704         SE_SERVICE_EXTERN_BEGIN;
705
706         service->setEventHandler(NULL, NULL);
707
708         SE_SERVICE_EXTERN_END;
709 }
710
711 EXTERN_API int se_service_destroy_instance(se_service_h handle)
712 {
713         int result = 0;
714
715         SE_SERVICE_EXTERN_BEGIN;
716
717         delete service;
718
719         SE_SERVICE_EXTERN_END;
720
721         return result;
722 }
723
724 /* LCOV_EXCL_STOP */
725