2 * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
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 */
25 /* SLP library header */
29 #include "ClientChannel.h"
30 #include "ReaderHelper.h"
31 #include "APDUHelper.h"
33 #include "ClientGDBus.h"
36 #include "ClientIPC.h"
40 #define EXTERN_API __attribute__((visibility("default")))
43 namespace smartcard_service_api
45 ClientChannel::ClientChannel(void *context, Session *session,
46 int channelNum, const ByteArray &selectResponse, void *handle)
49 this->channelNum = -1;
55 _ERR("ClientIPC::getInstance() failed");
60 this->channelNum = channelNum;
61 this->handle = handle;
62 this->selectResponse = selectResponse;
63 this->context = context;
65 /* initialize client */
66 if (!g_thread_supported())
73 /* init default context */
76 proxy = smartcard_service_channel_proxy_new_for_bus_sync(
77 G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
78 "org.tizen.SmartcardService",
79 "/org/tizen/SmartcardService/Channel",
83 _ERR("Can not create proxy : %s", error->message);
90 ClientChannel::~ClientChannel()
96 void ClientChannel::channel_transmit_cb(GObject *source_object,
97 GAsyncResult *res, gpointer user_data)
99 CallbackParam *param = (CallbackParam *)user_data;
100 transmitCallback callback;
102 GVariant *var_response;
103 GError *error = NULL;
106 _INFO("MSG_REQUEST_TRANSMIT");
109 _ERR("null parameter!!!");
113 callback = (transmitCallback)param->callback;
115 if (smartcard_service_channel_call_transmit_finish(
116 SMARTCARD_SERVICE_CHANNEL(source_object),
117 &result, &var_response, res, &error) == true) {
118 if (result == SCARD_ERROR_OK) {
119 GDBusHelper::convertVariantToByteArray(var_response, response);
121 _ERR("smartcard_service_channel_call_transmit failed, [%d]", result);
124 _ERR("smartcard_service_channel_call_transmit failed, [%s]", error->message);
127 result = SCARD_ERROR_IPC_FAILED;
130 if (callback != NULL) {
131 callback(response.getBuffer(),
133 result, param->user_param);
139 void ClientChannel::channel_close_cb(GObject *source_object,
140 GAsyncResult *res, gpointer user_data)
142 CallbackParam *param = (CallbackParam *)user_data;
143 ClientChannel *channel;
144 closeChannelCallback callback;
146 GError *error = NULL;
148 _INFO("MSG_REQUEST_CLOSE_CHANNEL");
151 _ERR("null parameter!!!");
155 channel = (ClientChannel *)param->instance;
156 callback = (closeChannelCallback)param->callback;
158 if (smartcard_service_channel_call_close_channel_finish(
159 SMARTCARD_SERVICE_CHANNEL(source_object),
160 &result, res, &error) == true) {
161 if (result == SCARD_ERROR_OK) {
162 channel->channelNum = -1;
164 _ERR("smartcard_service_channel_call_close_channel failed, [%d]", result);
167 _ERR("smartcard_service_channel_call_close_channel failed, [%s]", error->message);
170 result = SCARD_ERROR_IPC_FAILED;
173 if (callback != NULL) {
174 callback(result, param->user_param);
180 void ClientChannel::closeSync()
181 throw(ExceptionBase &, ErrorIO &, ErrorSecurity &,
182 ErrorIllegalState &, ErrorIllegalParameter &)
184 if (isClosed() == false)
186 if (getSession()->getReader()->isSecureElementPresent() == true)
190 GError *error = NULL;
193 _ERR("dbus proxy is not initialized yet");
194 throw ErrorIllegalState(SCARD_ERROR_NOT_INITIALIZED);
197 if (smartcard_service_channel_call_close_channel_sync(
198 (SmartcardServiceChannel *)proxy,
199 ClientGDBus::getCookie(),
200 GPOINTER_TO_UINT(context),
201 GPOINTER_TO_UINT(handle),
202 &ret, NULL, &error) == true) {
203 if (ret != SCARD_ERROR_OK) {
204 _ERR("smartcard_service_channel_call_close_channel_sync failed, [%d]", ret);
208 _ERR("smartcard_service_channel_call_close_channel_sync failed, [%s]", error->message);
211 throw ErrorIO(SCARD_ERROR_IPC_FAILED);
217 #ifdef CLIENT_IPC_THREAD
218 /* send message to server */
219 msg.message = Message::MSG_REQUEST_CLOSE_CHANNEL;
220 msg.param1 = (unsigned long)handle;
221 msg.error = (unsigned long)context; /* using error to context */
222 msg.caller = (void *)this;
223 msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
226 if (ClientIPC::getInstance().sendMessage(msg) == true)
228 rv = waitTimedCondition(0);
231 _ERR("timeout [%d]", rv);
232 this->error = SCARD_ERROR_OPERATION_TIMEOUT;
237 _ERR("sendMessage failed");
238 this->error = SCARD_ERROR_IPC_FAILED;
244 if (this->error != SCARD_ERROR_OK)
246 ThrowError::throwError(this->error);
253 _INFO("unavailable channel");
258 int ClientChannel::close(closeChannelCallback callback, void *userParam)
260 int result = SCARD_ERROR_OK;
262 if (isClosed() == false)
264 if (getSession()->getReader()->isSecureElementPresent() == true)
267 CallbackParam *param = new CallbackParam();
269 param->instance = this;
270 param->callback = (void *)callback;
271 param->user_param = userParam;
273 smartcard_service_channel_call_close_channel(
274 (SmartcardServiceChannel *)proxy,
275 ClientGDBus::getCookie(),
276 GPOINTER_TO_UINT(context),
277 GPOINTER_TO_UINT(handle), NULL,
278 &ClientChannel::channel_close_cb, param);
283 /* send message to server */
284 msg.message = Message::MSG_REQUEST_CLOSE_CHANNEL;
285 msg.param1 = (unsigned long)handle;
286 msg.error = (unsigned long)context; /* using error to context */
287 msg.caller = (void *)this;
288 msg.callback = (void *)callback;
289 msg.userParam = userParam;
291 if (ClientIPC::getInstance().sendMessage(msg) == false)
293 _ERR("sendMessage failed");
294 result = SCARD_ERROR_IPC_FAILED;
300 _ERR("unavailable channel");
301 result = SCARD_ERROR_ILLEGAL_STATE;
308 int ClientChannel::transmitSync(const ByteArray &command, ByteArray &result)
309 throw(ExceptionBase &, ErrorIO &, ErrorIllegalState &,
310 ErrorIllegalParameter &, ErrorSecurity &)
312 int rv = SCARD_ERROR_OK;
314 if (getSession()->getReader()->isSecureElementPresent() == true)
317 GVariant *var_command = NULL, *var_response = NULL;
318 GError *error = NULL;
320 var_command = GDBusHelper::convertByteArrayToVariant(command);
322 if (smartcard_service_channel_call_transmit_sync(
323 (SmartcardServiceChannel *)proxy,
324 ClientGDBus::getCookie(),
325 GPOINTER_TO_UINT(context),
326 GPOINTER_TO_UINT(handle),
327 var_command, &rv, &var_response,
328 NULL, &error) == true) {
330 if (rv == SCARD_ERROR_OK) {
331 GDBusHelper::convertVariantToByteArray(var_response, result);
333 _ERR("smartcard_service_session_call_get_atr_sync failed, [%d]", rv);
337 _ERR("smartcard_service_session_call_get_atr_sync failed, [%s]", error->message);
340 throw ErrorIO(SCARD_ERROR_IPC_FAILED);
344 #ifdef CLIENT_IPC_THREAD
345 /* send message to server */
346 msg.message = Message::MSG_REQUEST_TRANSMIT;
347 msg.param1 = (unsigned long)handle;
350 msg.error = (unsigned long)context; /* using error to context */
351 msg.caller = (void *)this;
352 msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
355 if (ClientIPC::getInstance().sendMessage(msg) == true)
357 rv = waitTimedCondition(0);
365 _ERR("timeout [%d]", rv);
366 this->error = SCARD_ERROR_OPERATION_TIMEOUT;
371 _ERR("sendMessage failed");
375 if (this->error != SCARD_ERROR_OK)
377 ThrowError::throwError(this->error);
384 _ERR("unavailable channel");
385 throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE);
391 int ClientChannel::transmit(const ByteArray &command, transmitCallback callback, void *userParam)
395 if (getSession()->getReader()->isSecureElementPresent() == true)
398 GVariant *var_command;
399 CallbackParam *param = new CallbackParam();
401 param->instance = this;
402 param->callback = (void *)callback;
403 param->user_param = userParam;
405 var_command = GDBusHelper::convertByteArrayToVariant(command);
407 smartcard_service_channel_call_transmit(
408 (SmartcardServiceChannel *)proxy,
409 ClientGDBus::getCookie(),
410 GPOINTER_TO_UINT(context),
411 GPOINTER_TO_UINT(handle),
413 &ClientChannel::channel_close_cb, param);
415 result = SCARD_ERROR_OK;
419 /* send message to server */
420 msg.message = Message::MSG_REQUEST_TRANSMIT;
421 msg.param1 = (unsigned long)handle;
424 msg.error = (unsigned long)context; /* using error to context */
425 msg.caller = (void *)this;
426 msg.callback = (void *)callback;
427 msg.userParam = userParam;
429 if (ClientIPC::getInstance().sendMessage(msg) == true)
431 result = SCARD_ERROR_OK;
435 _ERR("sendMessage failed");
436 result = SCARD_ERROR_IPC_FAILED;
442 _ERR("unavailable channel");
443 result = SCARD_ERROR_ILLEGAL_STATE;
450 bool ClientChannel::dispatcherCallback(void *message)
452 Message *msg = (Message *)message;
453 ClientChannel *channel = NULL;
458 _ERR("message is null");
462 channel = (ClientChannel *)msg->caller;
464 switch (msg->message)
466 case Message::MSG_REQUEST_TRANSMIT :
468 /* transmit result */
469 _INFO("MSG_REQUEST_TRANSMIT");
471 if (msg->isSynchronousCall() == true) /* synchronized call */
477 channel->error = msg->error;
478 channel->response = msg->data;
480 channel->signalCondition();
481 channel->syncUnlock();
483 else if (msg->callback != NULL)
485 transmitCallback cb = (transmitCallback)msg->callback;
488 cb(msg->data.getBuffer(),
496 case Message::MSG_REQUEST_CLOSE_CHANNEL :
498 _INFO("MSG_REQUEST_CLOSE_CHANNEL");
500 if (msg->isSynchronousCall() == true) /* synchronized call */
505 channel->error = msg->error;
507 channel->signalCondition();
508 channel->syncUnlock();
510 else if (msg->callback != NULL)
512 closeChannelCallback cb = (closeChannelCallback)msg->callback;
515 cb(msg->error, msg->userParam);
521 _DBG("Unknown message : %s", msg->toString().c_str());
529 #endif /* USE_GDBUS */
530 } /* namespace smartcard_service_api */
533 #define CHANNEL_EXTERN_BEGIN \
534 if (handle != NULL) \
536 ClientChannel *channel = (ClientChannel *)handle;
538 #define CHANNEL_EXTERN_END \
542 _ERR("Invalid param"); \
545 using namespace smartcard_service_api;
547 EXTERN_API int channel_close(channel_h handle, channel_close_cb callback, void *userParam)
551 CHANNEL_EXTERN_BEGIN;
552 result = channel->close((closeChannelCallback)callback, userParam);
558 EXTERN_API int channel_transmit(channel_h handle, unsigned char *command,
559 unsigned int length, channel_transmit_cb callback, void *userParam)
563 CHANNEL_EXTERN_BEGIN;
566 temp.assign(command, length);
567 result = channel->transmit(temp, (transmitCallback)callback, userParam);
573 EXTERN_API void channel_close_sync(channel_h handle)
575 #ifdef CLIENT_IPC_THREAD
576 CHANNEL_EXTERN_BEGIN;
579 channel->closeSync();
588 EXTERN_API int channel_transmit_sync(channel_h handle, unsigned char *command,
589 unsigned int cmd_len, unsigned char **response, unsigned int *resp_len)
593 #ifdef CLIENT_IPC_THREAD
594 if (command == NULL || cmd_len == 0 || response == NULL || resp_len == NULL)
597 CHANNEL_EXTERN_BEGIN;
598 ByteArray temp, resp;
600 temp.assign(command, cmd_len);
604 result = channel->transmitSync(temp, resp);
607 *resp_len = resp.size();
608 *response = (unsigned char *)calloc(1, *resp_len);
609 memcpy(*response, resp.getBuffer(), *resp_len);
622 EXTERN_API bool channel_is_basic_channel(channel_h handle)
626 CHANNEL_EXTERN_BEGIN;
627 result = channel->isBasicChannel();
633 EXTERN_API bool channel_is_closed(channel_h handle)
637 CHANNEL_EXTERN_BEGIN;
638 result = channel->isClosed();
644 EXTERN_API unsigned int channel_get_select_response_length(channel_h handle)
646 unsigned int result = 0;
648 CHANNEL_EXTERN_BEGIN;
649 result = channel->getSelectResponse().size();
655 EXTERN_API bool channel_get_select_response(channel_h handle,
656 unsigned char *buffer, unsigned int length)
660 if (buffer == NULL || length == 0)
665 CHANNEL_EXTERN_BEGIN;
668 response = channel->getSelectResponse();
669 if (response.size() > 0)
671 memcpy(buffer, response.getBuffer(), MIN(length, response.size()));
679 EXTERN_API session_h channel_get_session(channel_h handle)
681 session_h session = NULL;
683 CHANNEL_EXTERN_BEGIN;
684 session = channel->getSession();
690 EXTERN_API void channel_destroy_instance(channel_h handle)