2 * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 /* standard library header */
21 #include <glib-object.h>
23 /* SLP library header */
27 #include "SEService.h"
30 #include "ClientGDBus.h"
33 #include "ClientIPC.h"
34 #include "ClientDispatcher.h"
38 #define EXTERN_API __attribute__((visibility("default")))
41 #define SHUTDOWN_DELAY 500000 /* us */
43 namespace smartcard_service_api
45 SEService::SEService() : SEServiceHelper(),
46 handle(-1), context(NULL), handler(NULL), listener(NULL)
53 SEService::SEService(void *user_data, serviceConnected handler)
54 throw(ErrorIO &, ErrorIllegalParameter &) :
55 SEServiceHelper(), handle(-1),
58 initialize(user_data, handler);
61 SEService::SEService(void *user_data, SEServiceListener *listener)
62 throw(ErrorIO &, ErrorIllegalParameter &) :
63 SEServiceHelper(), handle(-1),
66 initialize(user_data, listener);
69 SEService::~SEService()
77 catch(ExceptionBase &e)
79 _ERR("EXCEPTION : %s", e.what());
86 for (i = 0; i < readers.size(); i++)
88 delete (Reader *)readers[i];
93 SEService *SEService::createInstance(void *user_data,
94 SEServiceListener *listener)
95 throw(ErrorIO &, ErrorIllegalParameter &)
97 return new SEService(user_data, listener);
100 SEService *SEService::createInstance(void *user_data,
101 serviceConnected handler)
102 throw(ErrorIO &, ErrorIllegalParameter &)
104 return new SEService(user_data, handler);
108 void SEService::reader_inserted(GObject *source_object,
109 guint reader_id, gchar *reader_name, gpointer user_data)
111 Reader *reader = NULL;
112 SEService *service = (SEService *)user_data;
114 _INFO("[MSG_NOTIFY_SE_INSERTED]");
117 reader = new Reader(service->context,
118 reader_name, GUINT_TO_POINTER(reader_id));
121 service->readers.push_back(reader);
125 _ERR("alloc failed");
128 if (service->listener != NULL)
130 service->listener->eventHandler(service,
131 reader_name, 1, service->context);
135 _DBG("listener is null");
139 void SEService::reader_removed(GObject *source_object,
140 guint reader_id, gchar *reader_name, gpointer user_data)
142 SEService *service = (SEService *)user_data;
145 _INFO("[MSG_NOTIFY_SE_REMOVED]");
147 for (i = 0; i < service->readers.size(); i++)
149 if (((Reader *)service->readers[i])->handle ==
150 GUINT_TO_POINTER(reader_id))
152 ((Reader *)service->readers[i])->unavailable();
157 if (service->listener != NULL)
159 service->listener->eventHandler(service,
160 reader_name, 2, service->context);
164 _DBG("listener is null");
168 void SEService::se_service_shutdown_cb(GObject *source_object,
169 GAsyncResult *res, gpointer user_data)
171 SEService *service = (SEService *)user_data;
173 GError *error = NULL;
175 if (smartcard_service_se_service_call_shutdown_finish(
176 SMARTCARD_SERVICE_SE_SERVICE(source_object),
177 &result, res, &error) == true) {
178 if (result == SCARD_ERROR_OK) {
179 service->connected = false;
181 _ERR("smartcard_service_se_service_call_shutdown failed, [%d]", result);
184 _ERR("smartcard_service_se_service_call_shutdown failed, [%s]", error->message);
189 void SEService::se_service_cb(GObject *source_object,
190 GAsyncResult *res, gpointer user_data)
192 SEService *service = (SEService *)user_data;
195 GVariant *readers = NULL;
196 GError *error = NULL;
198 if (service == NULL) {
199 _ERR("null parameter!!!");
203 if (smartcard_service_se_service_call_se_service_finish(
204 SMARTCARD_SERVICE_SE_SERVICE(source_object),
205 &result, &handle, &readers, res, &error) == true) {
206 if (result == SCARD_ERROR_OK) {
207 service->connected = true;
208 service->handle = handle;
209 service->parseReaderInformation(readers);
212 _ERR("smartcard_service_se_service_call_se_service failed, [%s]", error->message);
215 result = SCARD_ERROR_IPC_FAILED;
218 if (service->handler != NULL) {
219 service->handler(service, service->context);
220 } else if (service->listener != NULL) {
221 if (result == SCARD_ERROR_OK) {
222 service->listener->serviceConnected(service, service->context);
224 service->listener->errorHandler(service, result, service->context);
229 void SEService::shutdown()
234 void SEService::shutdownSync()
236 if (connected == true)
240 for (i = 0; i < readers.size(); i++)
242 readers[i]->closeSessions();
246 GError *error = NULL;
248 if (smartcard_service_se_service_call_shutdown_sync(
249 (SmartcardServiceSeService *)proxy,
254 _ERR("smartcard_service_se_service_call_shutdown_sync failed, [%s]", error->message);
259 /* wait at least 500ms */
260 usleep(SHUTDOWN_DELAY);
264 #ifdef CLIENT_IPC_THREAD
265 /* send message to load se */
268 msg.message = Message::MSG_REQUEST_SHUTDOWN;
269 msg.param1 = (unsigned long)handle;
270 msg.error = (unsigned long)this; /* using error to context */
271 msg.caller = (void *)this;
272 msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
275 if (ClientIPC::getInstance().sendMessage(msg) == true)
279 rv = waitTimedCondition(0);
282 ClientDispatcher::getInstance().removeSEService(handle);
293 _ERR("sendMessage failed");
301 bool SEService::_initialize() throw(ErrorIO &)
305 ClientIPC *clientIPC;
306 ClientDispatcher *clientDispatcher;
310 /* initialize client */
311 if (!g_thread_supported())
319 /* init default context */
320 GError *error = NULL;
322 proxy = smartcard_service_se_service_proxy_new_for_bus_sync(
323 G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
324 "org.tizen.SmartcardService",
325 "/org/tizen/SmartcardService/SeService",
329 _ERR("Can not create proxy : %s", error->message);
334 g_signal_connect(proxy, "reader-inserted",
335 G_CALLBACK(&SEService::reader_inserted), this);
337 g_signal_connect(proxy, "reader-removed",
338 G_CALLBACK(&SEService::reader_removed), this);
341 smartcard_service_se_service_call_se_service(
342 (SmartcardServiceSeService *)proxy,
344 &SEService::se_service_cb,
347 clientDispatcher = &ClientDispatcher::getInstance();
348 clientIPC = &ClientIPC::getInstance();
350 clientIPC->setDispatcher(clientDispatcher);
352 #ifndef CLIENT_IPC_THREAD
353 if (clientDispatcher->runDispatcherThread() == false)
355 _ERR("clientDispatcher->runDispatcherThread() failed");
361 if (clientIPC->createConnectSocket() == false)
363 _ERR("clientIPC->createConnectSocket() failed");
369 /* send message to load se */
372 msg.message = Message::MSG_REQUEST_READERS;
373 msg.error = getpid(); /* using error to pid */
374 msg.caller = (void *)this;
375 msg.userParam = context;
377 result = clientIPC->sendMessage(msg);
385 bool SEService::initialize(void *context, serviceConnected handler)
386 throw(ErrorIO &, ErrorIllegalParameter &)
390 throw ErrorIllegalParameter(SCARD_ERROR_ILLEGAL_PARAM);
393 this->context = context;
394 this->handler = handler;
396 return _initialize();
399 bool SEService::initialize(void *context, SEServiceListener *listener)
400 throw(ErrorIO &, ErrorIllegalParameter &)
404 throw ErrorIllegalParameter(SCARD_ERROR_ILLEGAL_PARAM);
407 this->context = context;
408 this->listener = listener;
410 return _initialize();
414 bool SEService::parseReaderInformation(GVariant *variant)
416 Reader *reader = NULL;
423 g_variant_get(variant, "a(us)", &iter);
425 count = g_variant_iter_n_children(iter);
426 while (g_variant_iter_loop(iter, "(us)", &handle, &name) == true)
429 reader = new Reader((void *)this->handle, name, GUINT_TO_POINTER(handle));
432 _ERR("alloc failed");
436 readers.push_back(reader);
439 g_variant_iter_free(iter);
444 bool SEService::parseReaderInformation(unsigned int count,
445 const ByteArray &data)
448 unsigned int offset = 0;
449 unsigned int len = 0;
451 Reader *reader = NULL;
454 for (i = 0; i < count && offset < data.size(); i++)
456 memset(name, 0, sizeof(name));
458 memcpy(&len, data.getBuffer(offset), sizeof(len));
459 offset += sizeof(len);
461 memcpy(name, data.getBuffer(offset), len);
464 memcpy(&handle, data.getBuffer(offset), sizeof(handle));
465 offset += sizeof(handle);
468 reader = new Reader(context, name, handle);
471 _ERR("alloc failed");
475 readers.push_back(reader);
482 bool SEService::dispatcherCallback(void *message)
484 Message *msg = (Message *)message;
492 _ERR("message is null");
496 service = (SEService *)msg->caller;
498 switch (msg->message)
500 case Message::MSG_REQUEST_READERS :
501 _INFO("[MSG_REQUEST_READERS]");
503 service->connected = true;
504 service->handle = (unsigned int)msg->param2;
506 ClientDispatcher::getInstance().addSEService(service->handle, service);
508 /* parse message data */
509 service->parseReaderInformation(msg->param1, msg->data);
511 /* call callback function */
512 if (service->listener != NULL)
514 service->listener->serviceConnected(service, service->context);
516 else if (service->handler != NULL)
518 service->handler(service, service->context);
522 case Message::MSG_REQUEST_SHUTDOWN :
523 _INFO("[MSG_REQUEST_SHUTDOWN]");
525 if (msg->isSynchronousCall() == true) /* synchronized call */
531 // service->error = msg->error;
532 service->signalCondition();
533 service->syncUnlock();
541 case Message::MSG_NOTIFY_SE_INSERTED :
543 Reader *reader = NULL;
545 _INFO("[MSG_NOTIFY_SE_INSERTED]");
548 reader = new Reader(service->context,
549 (char *)msg->data.getBuffer(), (void *)msg->param1);
552 service->readers.push_back(reader);
556 _ERR("alloc failed");
559 if (service->listener != NULL)
561 service->listener->eventHandler(service,
562 (char *)msg->data.getBuffer(), 1, service->context);
566 _DBG("listener is null");
571 case Message::MSG_NOTIFY_SE_REMOVED :
575 _INFO("[MSG_NOTIFY_SE_REMOVED]");
577 for (i = 0; i < service->readers.size(); i++)
579 if (((Reader *)service->readers[i])->handle == (void *)msg->param1)
581 ((Reader *)service->readers[i])->present = false;
586 if (service->listener != NULL)
588 service->listener->eventHandler(service,
589 (char *)msg->data.getBuffer(), 2, service->context);
593 _DBG("listener is null");
598 case Message::MSG_OPERATION_RELEASE_CLIENT :
599 _INFO("[MSG_OPERATION_RELEASE_CLIENT]");
601 if (service->listener != NULL)
603 service->listener->errorHandler(service, msg->error, service->context);
605 ClientDispatcher::getInstance().removeSEService(service->handle);
606 service->connected = false;
610 _ERR("service->listener is null");
615 _DBG("unknown message [%s]", msg->toString().c_str());
626 } /* namespace smartcard_service_api */
629 #define SE_SERVICE_EXTERN_BEGIN \
630 if (handle != NULL) \
632 SEService *service = (SEService *)handle;
634 #define SE_SERVICE_EXTERN_END \
638 _ERR("Invalid param"); \
641 using namespace smartcard_service_api;
643 EXTERN_API se_service_h se_service_create_instance(void *user_data, se_service_connected_cb callback)
649 service = new SEService(user_data, (serviceConnected)callback);
656 return (se_service_h)service;
659 EXTERN_API se_service_h se_service_create_instance_with_event_callback(void *user_data,
660 se_service_connected_cb connected, se_service_event_cb event, se_sesrvice_error_cb error)
666 service = new SEService(user_data, (serviceConnected)connected);
673 return (se_service_h)service;
676 EXTERN_API int se_service_get_readers_count(se_service_h handle)
680 SE_SERVICE_EXTERN_BEGIN;
682 vector<ReaderHelper *> temp_readers;
684 temp_readers = service->getReaders();
685 count = temp_readers.size();
687 SE_SERVICE_EXTERN_END;
692 EXTERN_API bool se_service_get_readers(se_service_h handle, reader_h *readers, int *count)
696 SE_SERVICE_EXTERN_BEGIN;
698 vector<ReaderHelper *> temp_readers;
702 temp_readers = service->getReaders();
704 for (i = 0; i < temp_readers.size() && i < (size_t)*count; i++)
706 if (temp_readers[i]->isSecureElementPresent())
708 readers[i] = (reader_h)temp_readers[i];
714 SE_SERVICE_EXTERN_END;
719 EXTERN_API bool se_service_is_connected(se_service_h handle)
723 SE_SERVICE_EXTERN_BEGIN;
725 result = service->isConnected();
727 SE_SERVICE_EXTERN_END;
732 EXTERN_API void se_service_shutdown(se_service_h handle)
734 SE_SERVICE_EXTERN_BEGIN;
736 service->shutdownSync();
738 SE_SERVICE_EXTERN_END;
741 EXTERN_API void se_service_destroy_instance(se_service_h handle)
743 SE_SERVICE_EXTERN_BEGIN;
747 SE_SERVICE_EXTERN_END;