code cleanup and fix build problems
[platform/core/connectivity/smartcard-service.git] / client / 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
23 /* SLP library header */
24
25 /* local header */
26 #include "Debug.h"
27 #include "SEService.h"
28 #include "Reader.h"
29 #include "ClientGDBus.h"
30
31 #ifndef EXTERN_API
32 #define EXTERN_API __attribute__((visibility("default")))
33 #endif
34
35 #define SHUTDOWN_DELAY          500000 /* us */
36
37 namespace smartcard_service_api
38 {
39         SEService::SEService() : SEServiceHelper(),
40                 handle(-1), context(NULL), handler(NULL), listener(NULL)
41         {
42                 proxy = NULL;
43         }
44
45         SEService::SEService(void *user_data, serviceConnected handler)
46                 throw(ErrorIO &, ErrorIllegalParameter &) :
47                 SEServiceHelper(), handle(-1),
48                 listener(NULL)
49         {
50                 initialize(user_data, handler);
51         }
52
53         SEService::SEService(void *user_data, SEServiceListener *listener)
54                 throw(ErrorIO &, ErrorIllegalParameter &) :
55                 SEServiceHelper(), handle(-1),
56                 handler(NULL)
57         {
58                 initialize(user_data, listener);
59         }
60
61         SEService::~SEService()
62         {
63                 uint32_t i;
64
65                 try
66                 {
67                         shutdownSync();
68                 }
69                 catch(ExceptionBase &e)
70                 {
71                         _ERR("EXCEPTION : %s", e.what());
72                 }
73                 catch(...)
74                 {
75                         _ERR("EXCEPTION!!!");
76                 }
77
78                 for (i = 0; i < readers.size(); i++)
79                 {
80                         delete (Reader *)readers[i];
81                 }
82                 readers.clear();
83         }
84
85         SEService *SEService::createInstance(void *user_data,
86                 SEServiceListener *listener)
87                 throw(ErrorIO &, ErrorIllegalParameter &)
88         {
89                 return new SEService(user_data, listener);
90         }
91
92         SEService *SEService::createInstance(void *user_data,
93                 serviceConnected handler)
94                 throw(ErrorIO &, ErrorIllegalParameter &)
95         {
96                 return new SEService(user_data, handler);
97         }
98
99         void SEService::reader_inserted(GObject *source_object,
100                 guint reader_id, gchar *reader_name, gpointer user_data)
101         {
102                 Reader *reader = NULL;
103                 SEService *service = (SEService *)user_data;
104
105                 _INFO("[MSG_NOTIFY_SE_INSERTED]");
106
107                 /* add readers */
108                 reader = new Reader(service->context,
109                         reader_name, GUINT_TO_POINTER(reader_id));
110                 if (reader != NULL)
111                 {
112                         service->readers.push_back(reader);
113                 }
114                 else
115                 {
116                         _ERR("alloc failed");
117                 }
118
119                 if (service->listener != NULL)
120                 {
121                         service->listener->eventHandler(service,
122                                 reader_name, 1, service->context);
123                 }
124                 else
125                 {
126                         _DBG("listener is null");
127                 }
128         }
129
130         void SEService::reader_removed(GObject *source_object,
131                 guint reader_id, gchar *reader_name, gpointer user_data)
132         {
133                 SEService *service = (SEService *)user_data;
134                 size_t i;
135
136                 _INFO("[MSG_NOTIFY_SE_REMOVED]");
137
138                 for (i = 0; i < service->readers.size(); i++)
139                 {
140                         if (((Reader *)service->readers[i])->handle ==
141                                 GUINT_TO_POINTER(reader_id))
142                         {
143                                 ((Reader *)service->readers[i])->unavailable();
144                                 break;
145                         }
146                 }
147
148                 if (service->listener != NULL)
149                 {
150                         service->listener->eventHandler(service,
151                                 reader_name, 2, service->context);
152                 }
153                 else
154                 {
155                         _DBG("listener is null");
156                 }
157         }
158
159         void SEService::se_service_shutdown_cb(GObject *source_object,
160                 GAsyncResult *res, gpointer user_data)
161         {
162                 SEService *service = (SEService *)user_data;
163                 gint result;
164                 GError *error = NULL;
165
166                 if (smartcard_service_se_service_call_shutdown_finish(
167                         SMARTCARD_SERVICE_SE_SERVICE(source_object),
168                         &result, res, &error) == true) {
169                         if (result == SCARD_ERROR_OK) {
170                                 service->connected = false;
171                         } else {
172                                 _ERR("smartcard_service_se_service_call_shutdown failed, [%d]", result);
173                         }
174                 } else {
175                         _ERR("smartcard_service_se_service_call_shutdown failed, [%s]", error->message);
176                         g_error_free(error);
177                 }
178         }
179
180         void SEService::se_service_cb(GObject *source_object,
181                 GAsyncResult *res, gpointer user_data)
182         {
183                 SEService *service = (SEService *)user_data;
184                 gint result;
185                 guint handle;
186                 GVariant *readers = NULL;
187                 GError *error = NULL;
188
189                 if (service == NULL) {
190                         _ERR("null parameter!!!");
191                         return;
192                 }
193
194                 if (smartcard_service_se_service_call_se_service_finish(
195                         SMARTCARD_SERVICE_SE_SERVICE(source_object),
196                         &result, &handle, &readers, res, &error) == true) {
197                         if (result == SCARD_ERROR_OK) {
198                                 service->connected = true;
199                                 service->handle = handle;
200                                 service->parseReaderInformation(readers);
201                         }
202                 } else {
203                         _ERR("smartcard_service_se_service_call_se_service failed, [%s]", error->message);
204                         g_error_free(error);
205
206                         result = SCARD_ERROR_IPC_FAILED;
207                 }
208
209                 if (service->handler != NULL) {
210                         service->handler(service, service->context);
211                 } else if (service->listener != NULL) {
212                         if (result == SCARD_ERROR_OK) {
213                                 service->listener->serviceConnected(service, service->context);
214                         } else {
215                                 service->listener->errorHandler(service, result, service->context);
216                         }
217                 }
218         }
219
220         void SEService::shutdown()
221         {
222                 shutdownSync();
223         }
224
225         void SEService::shutdownSync()
226         {
227                 if (connected == true)
228                 {
229                         uint32_t i;
230
231                         for (i = 0; i < readers.size(); i++)
232                         {
233                                 readers[i]->closeSessions();
234                         }
235
236                         gint result;
237                         GError *error = NULL;
238
239                         if (smartcard_service_se_service_call_shutdown_sync(
240                                 (SmartcardServiceSeService *)proxy,
241                                 handle,
242                                 &result,
243                                 NULL,
244                                 &error) == false) {
245                                 _ERR("smartcard_service_se_service_call_shutdown_sync failed, [%s]", error->message);
246
247                                 g_error_free(error);
248                         }
249
250                         /* wait at least 500ms */
251                         usleep(SHUTDOWN_DELAY);
252
253                         connected = false;
254                 }
255         }
256
257         bool SEService::_initialize() throw(ErrorIO &)
258         {
259                 bool result = false;
260
261                 _BEGIN();
262
263                 /* init default context */
264                 GError *error = NULL;
265
266                 proxy = smartcard_service_se_service_proxy_new_for_bus_sync(
267                         G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
268                         "org.tizen.SmartcardService",
269                         "/org/tizen/SmartcardService/SeService",
270                         NULL, &error);
271                 if (proxy == NULL)
272                 {
273                         _ERR("Can not create proxy : %s", error->message);
274                         g_error_free(error);
275                         return false;
276                 }
277
278                 g_signal_connect(proxy, "reader-inserted",
279                                 G_CALLBACK(&SEService::reader_inserted), this);
280
281                 g_signal_connect(proxy, "reader-removed",
282                                 G_CALLBACK(&SEService::reader_removed), this);
283
284                 /* request reader */
285                 smartcard_service_se_service_call_se_service(
286                         (SmartcardServiceSeService *)proxy,
287                         NULL,
288                         &SEService::se_service_cb,
289                         this);
290
291                 _END();
292
293                 return result;
294         }
295
296         bool SEService::initialize(void *context, serviceConnected handler)
297                 throw(ErrorIO &, ErrorIllegalParameter &)
298         {
299                 if (context == NULL)
300                 {
301                         throw ErrorIllegalParameter(SCARD_ERROR_ILLEGAL_PARAM);
302                 }
303
304                 this->context = context;
305                 this->handler = handler;
306
307                 return _initialize();
308         }
309
310         bool SEService::initialize(void *context, SEServiceListener *listener)
311                 throw(ErrorIO &, ErrorIllegalParameter &)
312         {
313                 if (context == NULL)
314                 {
315                         throw ErrorIllegalParameter(SCARD_ERROR_ILLEGAL_PARAM);
316                 }
317
318                 this->context = context;
319                 this->listener = listener;
320
321                 return _initialize();
322         }
323
324         bool SEService::parseReaderInformation(GVariant *variant)
325         {
326                 Reader *reader = NULL;
327
328                 GVariantIter *iter;
329                 gsize count;
330                 guint handle;
331                 gchar *name;
332
333                 g_variant_get(variant, "a(us)", &iter);
334
335                 count = g_variant_iter_n_children(iter);
336                 while (g_variant_iter_loop(iter, "(us)", &handle, &name) == true)
337                 {
338                         /* add readers */
339                         reader = new Reader((void *)this->handle, name, GUINT_TO_POINTER(handle));
340                         if (reader == NULL)
341                         {
342                                 _ERR("alloc failed");
343                                 continue;
344                         }
345
346                         readers.push_back(reader);
347                 }
348
349                 g_variant_iter_free(iter);
350
351                 return true;
352         }
353
354         bool SEService::parseReaderInformation(unsigned int count,
355                 const ByteArray &data)
356         {
357                 size_t i;
358                 unsigned int offset = 0;
359                 unsigned int len = 0;
360                 void *handle = NULL;
361                 Reader *reader = NULL;
362                 char name[100];
363
364                 for (i = 0; i < count && offset < data.size(); i++)
365                 {
366                         memset(name, 0, sizeof(name));
367
368                         memcpy(&len, data.getBuffer(offset), sizeof(len));
369                         offset += sizeof(len);
370
371                         memcpy(name, data.getBuffer(offset), len);
372                         offset += len;
373
374                         memcpy(&handle, data.getBuffer(offset), sizeof(handle));
375                         offset += sizeof(handle);
376
377                         /* add readers */
378                         reader = new Reader(context, name, handle);
379                         if (reader == NULL)
380                         {
381                                 _ERR("alloc failed");
382                                 continue;
383                         }
384
385                         readers.push_back(reader);
386                 }
387
388                 return true;
389         }
390 } /* namespace smartcard_service_api */
391
392 /* export C API */
393 #define SE_SERVICE_EXTERN_BEGIN \
394         if (handle != NULL) \
395         { \
396                 SEService *service = (SEService *)handle;
397
398 #define SE_SERVICE_EXTERN_END \
399         } \
400         else \
401         { \
402                 _ERR("Invalid param"); \
403         }
404
405 using namespace smartcard_service_api;
406
407 EXTERN_API se_service_h se_service_create_instance(void *user_data, se_service_connected_cb callback)
408 {
409         SEService *service;
410
411         try
412         {
413                 service = new SEService(user_data, (serviceConnected)callback);
414         }
415         catch (...)
416         {
417                 service = NULL;
418         }
419
420         return (se_service_h)service;
421 }
422
423 EXTERN_API se_service_h se_service_create_instance_with_event_callback(void *user_data,
424         se_service_connected_cb connected, se_service_event_cb event, se_sesrvice_error_cb error)
425 {
426         SEService *service;
427
428         try
429         {
430                 service = new SEService(user_data, (serviceConnected)connected);
431         }
432         catch (...)
433         {
434                 service = NULL;
435         }
436
437         return (se_service_h)service;
438 }
439
440 EXTERN_API int se_service_get_readers_count(se_service_h handle)
441 {
442         int count = 0;
443
444         SE_SERVICE_EXTERN_BEGIN;
445
446         vector<ReaderHelper *> temp_readers;
447
448         temp_readers = service->getReaders();
449         count = temp_readers.size();
450
451         SE_SERVICE_EXTERN_END;
452
453         return count;
454 }
455
456 EXTERN_API bool se_service_get_readers(se_service_h handle, reader_h *readers, int *count)
457 {
458         bool result = false;
459
460         SE_SERVICE_EXTERN_BEGIN;
461
462         vector<ReaderHelper *> temp_readers;
463         size_t i;
464         int temp = 0;
465
466         temp_readers = service->getReaders();
467
468         for (i = 0; i < temp_readers.size() && i < (size_t)*count; i++)
469         {
470                 if (temp_readers[i]->isSecureElementPresent())
471                 {
472                         readers[i] = (reader_h)temp_readers[i];
473                         temp++;
474                 }
475         }
476         *count = temp;
477
478         SE_SERVICE_EXTERN_END;
479
480         return result;
481 }
482
483 EXTERN_API bool se_service_is_connected(se_service_h handle)
484 {
485         bool result = false;
486
487         SE_SERVICE_EXTERN_BEGIN;
488
489         result = service->isConnected();
490
491         SE_SERVICE_EXTERN_END;
492
493         return result;
494 }
495
496 EXTERN_API void se_service_shutdown(se_service_h handle)
497 {
498         SE_SERVICE_EXTERN_BEGIN;
499
500         service->shutdownSync();
501
502         SE_SERVICE_EXTERN_END;
503 }
504
505 EXTERN_API void se_service_destroy_instance(se_service_h handle)
506 {
507         SE_SERVICE_EXTERN_BEGIN;
508
509         delete service;
510
511         SE_SERVICE_EXTERN_END;
512 }