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 */
23 /* SLP library header */
29 #include "ClientChannel.h"
30 #include "ClientIPC.h"
33 #define EXTERN_API __attribute__((visibility("default")))
36 namespace smartcard_service_api
38 Session::Session(void *context, Reader *reader, void *handle) :
43 if (context == NULL || handle == NULL)
45 SCARD_DEBUG_ERR("handle is null");
50 this->context = context;
51 this->handle = handle;
61 for (i = 0; i < channels.size(); i++)
63 delete (ClientChannel *)channels[i];
69 void Session::closeChannels() throw (ErrorIO &, ErrorIllegalState &)
73 for (i = 0; i < channels.size(); i++)
75 channels[i]->closeSync();
79 ByteArray Session::getATRSync() throw (ErrorIO &, ErrorIllegalState &)
82 if (getReader()->isSecureElementPresent() == true)
84 if (atr.isEmpty() == true)
89 #ifdef CLIENT_IPC_THREAD
90 /* request channel handle from server */
91 msg.message = Message::MSG_REQUEST_GET_ATR;
92 msg.param1 = (unsigned long)handle;
93 msg.error = (unsigned long)context; /* using error to context */
94 msg.caller = (void *)this;
95 msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
98 if (ClientIPC::getInstance().sendMessage(&msg) == true)
100 rv = waitTimedCondition(0);
103 SCARD_DEBUG_ERR("time over");
104 this->error = SCARD_ERROR_OPERATION_TIMEOUT;
109 SCARD_DEBUG_ERR("sendMessage failed");
110 this->error = SCARD_ERROR_IPC_FAILED;
114 if (this->error != SCARD_ERROR_OK)
116 ThrowError::throwError(this->error);
125 SCARD_DEBUG_ERR("unavailable session");
126 throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE);
132 int Session::getATR(getATRCallback callback, void *userData)
136 if (getReader()->isSecureElementPresent() == true)
138 if (atr.isEmpty() == true)
143 /* request channel handle from server */
144 msg.message = Message::MSG_REQUEST_GET_ATR;
145 msg.param1 = (unsigned long)handle;
146 msg.error = (unsigned long)context; /* using error to context */
147 msg.caller = (void *)this;
148 msg.callback = (void *)callback;
149 msg.userParam = userData;
151 if (ClientIPC::getInstance().sendMessage(&msg) == true)
153 result = SCARD_ERROR_OK;
157 result = SCARD_ERROR_IPC_FAILED;
162 result = SCARD_ERROR_OK;
164 /* TODO : invoke callback directly */
165 callback(atr.getBuffer(), atr.getLength(), 0, userData);
170 SCARD_DEBUG_ERR("unavailable session");
171 result = SCARD_ERROR_ILLEGAL_STATE;
177 void Session::closeSync() throw (ErrorIO &, ErrorIllegalState &)
182 #ifdef CLIENT_IPC_THREAD
183 if (isClosed() == false)
188 /* request channel handle from server */
189 msg.message = Message::MSG_REQUEST_CLOSE_SESSION;
190 msg.param1 = (unsigned long)handle;
191 msg.error = (unsigned long)context; /* using error to context */
192 msg.caller = (void *)this;
193 msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
196 if (ClientIPC::getInstance().sendMessage(&msg) == true)
198 rv = waitTimedCondition(0);
202 SCARD_DEBUG_ERR("time over");
203 this->error = SCARD_ERROR_OPERATION_TIMEOUT;
208 SCARD_DEBUG_ERR("sendMessage failed");
209 this->error = SCARD_ERROR_IPC_FAILED;
213 if (this->error != SCARD_ERROR_OK)
215 ThrowError::throwError(this->error);
221 int Session::close(closeSessionCallback callback, void *userData)
223 int result = SCARD_ERROR_OK;
226 if (isClosed() == false)
231 /* request channel handle from server */
232 msg.message = Message::MSG_REQUEST_CLOSE_SESSION;
233 msg.param1 = (unsigned long)handle;
234 msg.error = (unsigned long)context; /* using error to context */
235 msg.caller = (void *)this;
236 msg.callback = (void *)callback;
237 msg.userParam = userData;
239 if (ClientIPC::getInstance().sendMessage(&msg) == false)
241 result = SCARD_ERROR_IPC_FAILED;
248 unsigned int Session::getChannelCountSync()
252 if (getReader()->isSecureElementPresent() == true)
258 #ifdef CLIENT_IPC_THREAD
259 /* request channel handle from server */
260 msg.message = Message::MSG_REQUEST_GET_CHANNEL_COUNT;
261 msg.param1 = (unsigned long)handle;
262 msg.error = (unsigned long)context; /* using error to context */
263 msg.caller = (void *)this;
264 msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
269 if (ClientIPC::getInstance().sendMessage(&msg) == true)
271 rv = waitTimedCondition(0);
274 SCARD_DEBUG_ERR("time over");
275 this->error = SCARD_ERROR_OPERATION_TIMEOUT;
280 SCARD_DEBUG_ERR("sendMessage failed");
281 this->error = SCARD_ERROR_IPC_FAILED;
285 if (this->error != SCARD_ERROR_OK)
287 ThrowError::throwError(this->error);
293 SCARD_DEBUG_ERR("unavailable session");
294 throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE);
300 int Session::getChannelCount(getChannelCountCallback callback, void *userData)
304 if (getReader()->isSecureElementPresent() == true)
309 msg.message = Message::MSG_REQUEST_GET_CHANNEL_COUNT;
310 msg.param1 = (unsigned long)handle;
311 msg.error = (unsigned long)context; /* using error to context */
312 msg.caller = (void *)this;
313 msg.callback = (void *)callback;
314 msg.userParam = userData;
316 if (ClientIPC::getInstance().sendMessage(&msg) == true)
318 result = SCARD_ERROR_OK;
322 result = SCARD_ERROR_IPC_FAILED;
327 SCARD_DEBUG_ERR("unavailable session");
328 result = SCARD_ERROR_ILLEGAL_STATE;
334 Channel *Session::openChannelSync(int id, ByteArray aid)
335 throw (ErrorIO &, ErrorIllegalState &, ErrorIllegalParameter &, ErrorSecurity &)
337 openedChannel = NULL;
339 if (getReader()->isSecureElementPresent() == true)
344 #ifdef CLIENT_IPC_THREAD
345 /* request channel handle from server */
346 msg.message = Message::MSG_REQUEST_OPEN_CHANNEL;
348 msg.param2 = (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);
360 SCARD_DEBUG_ERR("time over");
361 this->error = SCARD_ERROR_OPERATION_TIMEOUT;
366 SCARD_DEBUG_ERR("sendMessage failed");
367 this->error = SCARD_ERROR_IPC_FAILED;
371 if (this->error != SCARD_ERROR_OK)
373 ThrowError::throwError(this->error);
378 SCARD_DEBUG_ERR("unavailable session");
379 throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE);
382 return (Channel *)openedChannel;
385 int Session::openChannel(int id, ByteArray aid, openChannelCallback callback, void *userData)
389 if (getReader()->isSecureElementPresent() == true)
393 /* request channel handle from server */
394 msg.message = Message::MSG_REQUEST_OPEN_CHANNEL;
396 msg.param2 = (unsigned long)handle;
398 msg.error = (unsigned long)context; /* using error to context */
399 msg.caller = (void *)this;
400 msg.callback = (void *)callback;
401 msg.userParam = userData;
403 if (ClientIPC::getInstance().sendMessage(&msg) == true)
405 result = SCARD_ERROR_OK;
409 result = SCARD_ERROR_IPC_FAILED;
414 SCARD_DEBUG_ERR("unavailable session");
415 result = SCARD_ERROR_ILLEGAL_STATE;
421 Channel *Session::openBasicChannelSync(ByteArray aid)
422 throw (ErrorIO &, ErrorIllegalState &, ErrorIllegalParameter &, ErrorSecurity &)
424 return openChannelSync(0, aid);
427 Channel *Session::openBasicChannelSync(unsigned char *aid, unsigned int length)
428 throw (ErrorIO &, ErrorIllegalState &, ErrorIllegalParameter &, ErrorSecurity &)
430 return openBasicChannelSync(ByteArray(aid, length));
433 int Session::openBasicChannel(ByteArray aid, openChannelCallback callback, void *userData)
435 return openChannel(0, aid, callback, userData);
438 int Session::openBasicChannel(unsigned char *aid, unsigned int length,
439 openChannelCallback callback, void *userData)
441 return openBasicChannel(ByteArray(aid, length), callback, userData);
444 Channel *Session::openLogicalChannelSync(ByteArray aid)
445 throw (ErrorIO &, ErrorIllegalState &, ErrorIllegalParameter &, ErrorSecurity &)
447 return openChannelSync(1, aid);
450 Channel *Session::openLogicalChannelSync(unsigned char *aid, unsigned int length)
451 throw (ErrorIO &, ErrorIllegalState &, ErrorIllegalParameter &, ErrorSecurity &)
453 return openLogicalChannelSync(ByteArray(aid, length));
456 int Session::openLogicalChannel(ByteArray aid, openChannelCallback callback, void *userData)
458 return openChannel(1, aid, callback, userData);
461 int Session::openLogicalChannel(unsigned char *aid, unsigned int length,
462 openChannelCallback callback, void *userData)
464 return openLogicalChannel(ByteArray(aid, length), callback, userData);
467 bool Session::dispatcherCallback(void *message)
469 Message *msg = (Message *)message;
470 Session *session = NULL;
475 SCARD_DEBUG_ERR("message is null");
479 session = (Session *)msg->caller;
481 switch (msg->message)
483 case Message::MSG_REQUEST_OPEN_CHANNEL :
485 Channel *channel = NULL;
487 SCARD_DEBUG("MSG_REQUEST_OPEN_CHANNEL");
489 if (msg->param1 != 0)
491 /* create new instance of channel */
492 channel = new ClientChannel(session->context,
493 session, msg->param2, msg->data, (void *)msg->param1);
496 session->channels.push_back(channel);
500 SCARD_DEBUG_ERR("alloc failed");
502 msg->error = SCARD_ERROR_OUT_OF_MEMORY;
506 if (msg->isSynchronousCall() == true) /* synchronized call */
512 session->error = msg->error;
513 session->openedChannel = channel;
515 session->signalCondition();
516 session->syncUnlock();
518 else if (msg->callback != NULL)
520 openChannelCallback cb = (openChannelCallback)msg->callback;
523 cb(channel, msg->error, msg->userParam);
528 case Message::MSG_REQUEST_GET_ATR :
530 SCARD_DEBUG("MSG_REQUEST_GET_ATR");
532 if (msg->isSynchronousCall() == true) /* synchronized call */
537 session->error = msg->error;
538 session->atr = msg->data;
540 session->signalCondition();
541 session->syncUnlock();
543 else if (msg->callback != NULL)
545 getATRCallback cb = (getATRCallback)msg->callback;
548 cb(msg->data.getBuffer(), msg->data.getLength(), msg->error, msg->userParam);
553 case Message::MSG_REQUEST_CLOSE_SESSION :
555 SCARD_DEBUG("MSG_REQUEST_CLOSE_SESSION");
557 if (msg->isSynchronousCall() == true) /* synchronized call */
562 session->error = msg->error;
564 session->signalCondition();
565 session->syncUnlock();
567 else if (msg->callback != NULL)
569 closeSessionCallback cb = (closeSessionCallback)msg->callback;
572 cb(msg->error, msg->userParam);
577 case Message::MSG_REQUEST_GET_CHANNEL_COUNT :
579 SCARD_DEBUG("MSG_REQUEST_GET_CHANNEL_COUNT");
581 if (msg->isSynchronousCall() == true) /* synchronized call */
586 session->error = msg->error;
587 session->channelCount = msg->param1;
589 session->signalCondition();
590 session->syncUnlock();
592 else if (msg->callback != NULL)
594 getChannelCountCallback cb = (getChannelCountCallback)msg->callback;
597 cb(msg->param1, msg->error, msg->userParam);
603 SCARD_DEBUG("unknown message : %s", msg->toString());
609 } /* namespace smartcard_service_api */
612 #define SESSION_EXTERN_BEGIN \
613 if (handle != NULL) \
615 Session *session = (Session *)handle;
617 #define SESSION_EXTERN_END \
621 SCARD_DEBUG_ERR("Invalid param"); \
624 using namespace smartcard_service_api;
626 EXTERN_API reader_h session_get_reader(session_h handle)
628 reader_h reader = NULL;
630 SESSION_EXTERN_BEGIN;
631 reader = session->getReader();
637 EXTERN_API int session_get_atr(session_h handle, session_get_atr_cb callback, void *userData)
641 SESSION_EXTERN_BEGIN;
642 result = session->getATR((getATRCallback)callback, userData);
648 EXTERN_API int session_close(session_h handle, session_close_session_cb callback, void *userData)
652 SESSION_EXTERN_BEGIN;
653 result = session->close((closeSessionCallback)callback, userData);
659 EXTERN_API bool session_is_closed(session_h handle)
663 SESSION_EXTERN_BEGIN;
664 result = session->isClosed();
670 EXTERN_API void session_close_channels(session_h handle)
672 SESSION_EXTERN_BEGIN;
673 session->closeChannels();
677 EXTERN_API int session_open_basic_channel(session_h handle, unsigned char *aid,
678 unsigned int length, session_open_channel_cb callback, void *userData)
682 SESSION_EXTERN_BEGIN;
683 result = session->openBasicChannel(aid, length, (openChannelCallback)callback, userData);
689 EXTERN_API int session_open_logical_channel(session_h handle, unsigned char *aid,
690 unsigned int length, session_open_channel_cb callback, void *userData)
694 SESSION_EXTERN_BEGIN;
695 result = session->openLogicalChannel(aid, length, (openChannelCallback)callback, userData);
701 EXTERN_API int session_get_channel_count(session_h handle, session_get_channel_count_cb callback, void * userData)
705 SESSION_EXTERN_BEGIN;
706 result = session->getChannelCount((getChannelCountCallback)callback, userData);
712 EXTERN_API void session_destroy_instance(session_h handle)
716 EXTERN_API int session_get_atr_sync(session_h handle, unsigned char **buffer, unsigned int *length)
721 #ifdef CLIENT_IPC_THREAD
722 if (buffer == NULL || length == NULL)
725 SESSION_EXTERN_BEGIN;
726 temp = session->getATRSync();
727 if (temp.getLength() > 0)
729 *length = temp.getLength();
730 *buffer = (unsigned char *)calloc(1, *length);
731 memcpy(*buffer, temp.getBuffer(), *length);
741 EXTERN_API void session_close_sync(session_h handle)
743 #ifdef CLIENT_IPC_THREAD
744 SESSION_EXTERN_BEGIN;
745 session->closeSync();
750 EXTERN_API channel_h session_open_basic_channel_sync(session_h handle, unsigned char *aid, unsigned int length)
752 channel_h result = NULL;
754 #ifdef CLIENT_IPC_THREAD
755 SESSION_EXTERN_BEGIN;
756 result = session->openBasicChannelSync(aid, length);
763 EXTERN_API channel_h session_open_logical_channel_sync(session_h handle, unsigned char *aid, unsigned int length)
765 channel_h result = NULL;
767 #ifdef CLIENT_IPC_THREAD
768 SESSION_EXTERN_BEGIN;
769 result = session->openLogicalChannelSync(aid, length);
776 EXTERN_API unsigned int session_get_channel_count_sync(session_h handle)
778 unsigned int result = 0;
780 #ifdef CLIENT_IPC_THREAD
781 SESSION_EXTERN_BEGIN;
782 result = session->getChannelCountSync();