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 "smartcard-service-gdbus.h"
34 #include "GDBusHelper.h"
37 #include "ClientIPC.h"
41 #define EXTERN_API __attribute__((visibility("default")))
44 namespace smartcard_service_api
46 ClientChannel::ClientChannel(void *context, Session *session,
47 int channelNum, const ByteArray &selectResponse, void *handle)
50 this->channelNum = -1;
56 _ERR("ClientIPC::getInstance() failed");
61 this->channelNum = channelNum;
62 this->handle = handle;
63 this->selectResponse = selectResponse;
64 this->context = context;
66 /* initialize client */
67 if (!g_thread_supported())
74 /* init default context */
77 proxy = smartcard_service_channel_proxy_new_for_bus_sync(
78 G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
79 "org.tizen.SmartcardService",
80 "/org/tizen/SmartcardService/Channel",
84 _ERR("Can not create proxy : %s", error->message);
91 ClientChannel::~ClientChannel()
97 void ClientChannel::channel_transmit_cb(GObject *source_object,
98 GAsyncResult *res, gpointer user_data)
100 CallbackParam *param = (CallbackParam *)user_data;
101 transmitCallback callback;
103 GVariant *var_response;
104 GError *error = NULL;
107 _INFO("MSG_REQUEST_TRANSMIT");
110 _ERR("null parameter!!!");
114 callback = (transmitCallback)param->callback;
116 if (smartcard_service_channel_call_transmit_finish(
117 SMARTCARD_SERVICE_CHANNEL(source_object),
118 &result, &var_response, res, &error) == true) {
119 if (result == SCARD_ERROR_OK) {
120 GDBusHelper::convertVariantToByteArray(var_response, response);
122 _ERR("smartcard_service_channel_call_transmit failed, [%d]", result);
125 _ERR("smartcard_service_channel_call_transmit failed, [%s]", error->message);
128 result = SCARD_ERROR_IPC_FAILED;
131 if (callback != NULL) {
132 callback(response.getBuffer(),
134 result, param->user_param);
140 void ClientChannel::channel_close_cb(GObject *source_object,
141 GAsyncResult *res, gpointer user_data)
143 CallbackParam *param = (CallbackParam *)user_data;
144 ClientChannel *channel;
145 closeChannelCallback callback;
147 GError *error = NULL;
149 _INFO("MSG_REQUEST_CLOSE_CHANNEL");
152 _ERR("null parameter!!!");
156 channel = (ClientChannel *)param->instance;
157 callback = (closeChannelCallback)param->callback;
159 if (smartcard_service_channel_call_close_channel_finish(
160 SMARTCARD_SERVICE_CHANNEL(source_object),
161 &result, res, &error) == true) {
162 if (result == SCARD_ERROR_OK) {
163 channel->channelNum = -1;
165 _ERR("smartcard_service_channel_call_close_channel failed, [%d]", result);
168 _ERR("smartcard_service_channel_call_close_channel failed, [%s]", error->message);
171 result = SCARD_ERROR_IPC_FAILED;
174 if (callback != NULL) {
175 callback(result, param->user_param);
181 void ClientChannel::closeSync()
182 throw(ExceptionBase &, ErrorIO &, ErrorSecurity &,
183 ErrorIllegalState &, ErrorIllegalParameter &)
185 if (isClosed() == false)
187 if (getSession()->getReader()->isSecureElementPresent() == true)
191 GError *error = NULL;
194 _ERR("dbus proxy is not initialized yet");
195 throw ErrorIllegalState(SCARD_ERROR_NOT_INITIALIZED);
198 if (smartcard_service_channel_call_close_channel_sync(
199 (SmartcardServiceChannel *)proxy,
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 GPOINTER_TO_UINT(context),
276 GPOINTER_TO_UINT(handle), NULL,
277 &ClientChannel::channel_close_cb, param);
282 /* send message to server */
283 msg.message = Message::MSG_REQUEST_CLOSE_CHANNEL;
284 msg.param1 = (unsigned long)handle;
285 msg.error = (unsigned long)context; /* using error to context */
286 msg.caller = (void *)this;
287 msg.callback = (void *)callback;
288 msg.userParam = userParam;
290 if (ClientIPC::getInstance().sendMessage(msg) == false)
292 _ERR("sendMessage failed");
293 result = SCARD_ERROR_IPC_FAILED;
299 _ERR("unavailable channel");
300 result = SCARD_ERROR_ILLEGAL_STATE;
307 int ClientChannel::transmitSync(const ByteArray &command, ByteArray &result)
308 throw(ExceptionBase &, ErrorIO &, ErrorIllegalState &,
309 ErrorIllegalParameter &, ErrorSecurity &)
311 int rv = SCARD_ERROR_OK;
313 if (getSession()->getReader()->isSecureElementPresent() == true)
316 GVariant *var_command = NULL, *var_response = NULL;
317 GError *error = NULL;
319 var_command = GDBusHelper::convertByteArrayToVariant(command);
321 if (smartcard_service_channel_call_transmit_sync(
322 (SmartcardServiceChannel *)proxy,
323 GPOINTER_TO_UINT(context),
324 GPOINTER_TO_UINT(handle),
325 var_command, &rv, &var_response,
326 NULL, &error) == true) {
328 if (rv == SCARD_ERROR_OK) {
329 GDBusHelper::convertVariantToByteArray(var_response, result);
331 _ERR("smartcard_service_session_call_get_atr_sync failed, [%d]", rv);
335 _ERR("smartcard_service_session_call_get_atr_sync failed, [%s]", error->message);
338 throw ErrorIO(SCARD_ERROR_IPC_FAILED);
342 #ifdef CLIENT_IPC_THREAD
343 /* send message to server */
344 msg.message = Message::MSG_REQUEST_TRANSMIT;
345 msg.param1 = (unsigned long)handle;
348 msg.error = (unsigned long)context; /* using error to context */
349 msg.caller = (void *)this;
350 msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
353 if (ClientIPC::getInstance().sendMessage(msg) == true)
355 rv = waitTimedCondition(0);
363 _ERR("timeout [%d]", rv);
364 this->error = SCARD_ERROR_OPERATION_TIMEOUT;
369 _ERR("sendMessage failed");
373 if (this->error != SCARD_ERROR_OK)
375 ThrowError::throwError(this->error);
382 _ERR("unavailable channel");
383 throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE);
389 int ClientChannel::transmit(const ByteArray &command, transmitCallback callback, void *userParam)
393 if (getSession()->getReader()->isSecureElementPresent() == true)
396 GVariant *var_command;
397 CallbackParam *param = new CallbackParam();
399 param->instance = this;
400 param->callback = (void *)callback;
401 param->user_param = userParam;
403 var_command = GDBusHelper::convertByteArrayToVariant(command);
405 smartcard_service_channel_call_transmit(
406 (SmartcardServiceChannel *)proxy,
407 GPOINTER_TO_UINT(context),
408 GPOINTER_TO_UINT(handle),
410 &ClientChannel::channel_close_cb, param);
412 result = SCARD_ERROR_OK;
416 /* send message to server */
417 msg.message = Message::MSG_REQUEST_TRANSMIT;
418 msg.param1 = (unsigned long)handle;
421 msg.error = (unsigned long)context; /* using error to context */
422 msg.caller = (void *)this;
423 msg.callback = (void *)callback;
424 msg.userParam = userParam;
426 if (ClientIPC::getInstance().sendMessage(msg) == true)
428 result = SCARD_ERROR_OK;
432 _ERR("sendMessage failed");
433 result = SCARD_ERROR_IPC_FAILED;
439 _ERR("unavailable channel");
440 result = SCARD_ERROR_ILLEGAL_STATE;
447 bool ClientChannel::dispatcherCallback(void *message)
449 Message *msg = (Message *)message;
450 ClientChannel *channel = NULL;
455 _ERR("message is null");
459 channel = (ClientChannel *)msg->caller;
461 switch (msg->message)
463 case Message::MSG_REQUEST_TRANSMIT :
465 /* transmit result */
466 _INFO("MSG_REQUEST_TRANSMIT");
468 if (msg->isSynchronousCall() == true) /* synchronized call */
474 channel->error = msg->error;
475 channel->response = msg->data;
477 channel->signalCondition();
478 channel->syncUnlock();
480 else if (msg->callback != NULL)
482 transmitCallback cb = (transmitCallback)msg->callback;
485 cb(msg->data.getBuffer(),
493 case Message::MSG_REQUEST_CLOSE_CHANNEL :
495 _INFO("MSG_REQUEST_CLOSE_CHANNEL");
497 if (msg->isSynchronousCall() == true) /* synchronized call */
502 channel->error = msg->error;
504 channel->signalCondition();
505 channel->syncUnlock();
507 else if (msg->callback != NULL)
509 closeChannelCallback cb = (closeChannelCallback)msg->callback;
512 cb(msg->error, msg->userParam);
518 _DBG("Unknown message : %s", msg->toString().c_str());
526 #endif /* USE_GDBUS */
527 } /* namespace smartcard_service_api */
530 #define CHANNEL_EXTERN_BEGIN \
531 if (handle != NULL) \
533 ClientChannel *channel = (ClientChannel *)handle;
535 #define CHANNEL_EXTERN_END \
539 _ERR("Invalid param"); \
542 using namespace smartcard_service_api;
544 EXTERN_API int channel_close(channel_h handle, channel_close_cb callback, void *userParam)
548 CHANNEL_EXTERN_BEGIN;
549 result = channel->close((closeChannelCallback)callback, userParam);
555 EXTERN_API int channel_transmit(channel_h handle, unsigned char *command,
556 unsigned int length, channel_transmit_cb callback, void *userParam)
560 CHANNEL_EXTERN_BEGIN;
563 temp.assign(command, length);
564 result = channel->transmit(temp, (transmitCallback)callback, userParam);
570 EXTERN_API void channel_close_sync(channel_h handle)
572 #ifdef CLIENT_IPC_THREAD
573 CHANNEL_EXTERN_BEGIN;
576 channel->closeSync();
585 EXTERN_API int channel_transmit_sync(channel_h handle, unsigned char *command,
586 unsigned int cmd_len, unsigned char **response, unsigned int *resp_len)
590 #ifdef CLIENT_IPC_THREAD
591 if (command == NULL || cmd_len == 0 || response == NULL || resp_len == NULL)
594 CHANNEL_EXTERN_BEGIN;
595 ByteArray temp, resp;
597 temp.assign(command, cmd_len);
601 result = channel->transmitSync(temp, resp);
604 *resp_len = resp.size();
605 *response = (unsigned char *)calloc(1, *resp_len);
606 memcpy(*response, resp.getBuffer(), *resp_len);
619 EXTERN_API bool channel_is_basic_channel(channel_h handle)
623 CHANNEL_EXTERN_BEGIN;
624 result = channel->isBasicChannel();
630 EXTERN_API bool channel_is_closed(channel_h handle)
634 CHANNEL_EXTERN_BEGIN;
635 result = channel->isClosed();
641 EXTERN_API unsigned int channel_get_select_response_length(channel_h handle)
643 unsigned int result = 0;
645 CHANNEL_EXTERN_BEGIN;
646 result = channel->getSelectResponse().size();
652 EXTERN_API bool channel_get_select_response(channel_h handle,
653 unsigned char *buffer, unsigned int length)
657 if (buffer == NULL || length == 0)
662 CHANNEL_EXTERN_BEGIN;
665 response = channel->getSelectResponse();
666 if (response.size() > 0)
668 memcpy(buffer, response.getBuffer(), MIN(length, response.size()));
676 EXTERN_API session_h channel_get_session(channel_h handle)
678 session_h session = NULL;
680 CHANNEL_EXTERN_BEGIN;
681 session = channel->getSession();
687 EXTERN_API void channel_destroy_instance(channel_h handle)