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 _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()
80 throw (ExceptionBase &, ErrorIO &, ErrorSecurity &,
81 ErrorIllegalState &, ErrorIllegalParameter &)
84 if (getReader()->isSecureElementPresent() == true)
86 if (atr.isEmpty() == true)
91 #ifdef CLIENT_IPC_THREAD
92 /* request channel handle from server */
93 msg.message = Message::MSG_REQUEST_GET_ATR;
94 msg.param1 = (unsigned long)handle;
95 msg.error = (unsigned long)context; /* using error to context */
96 msg.caller = (void *)this;
97 msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
100 if (ClientIPC::getInstance().sendMessage(&msg) == true)
102 rv = waitTimedCondition(0);
106 this->error = SCARD_ERROR_OPERATION_TIMEOUT;
111 _ERR("sendMessage failed");
112 this->error = SCARD_ERROR_IPC_FAILED;
116 if (this->error != SCARD_ERROR_OK)
118 ThrowError::throwError(this->error);
127 _ERR("unavailable session");
128 throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE);
134 int Session::getATR(getATRCallback callback, void *userData)
138 if (getReader()->isSecureElementPresent() == true)
140 if (atr.isEmpty() == true)
145 /* request channel handle from server */
146 msg.message = Message::MSG_REQUEST_GET_ATR;
147 msg.param1 = (unsigned long)handle;
148 msg.error = (unsigned long)context; /* using error to context */
149 msg.caller = (void *)this;
150 msg.callback = (void *)callback;
151 msg.userParam = userData;
153 if (ClientIPC::getInstance().sendMessage(&msg) == true)
155 result = SCARD_ERROR_OK;
159 _ERR("sendMessage failed");
160 result = SCARD_ERROR_IPC_FAILED;
165 result = SCARD_ERROR_OK;
167 /* TODO : invoke callback directly */
168 callback(atr.getBuffer(), atr.getLength(), 0, userData);
173 _ERR("unavailable session");
174 result = SCARD_ERROR_ILLEGAL_STATE;
180 void Session::closeSync()
181 throw (ExceptionBase &, ErrorIO &, ErrorSecurity &,
182 ErrorIllegalState &, ErrorIllegalParameter &)
187 #ifdef CLIENT_IPC_THREAD
188 if (isClosed() == false)
193 /* request channel handle from server */
194 msg.message = Message::MSG_REQUEST_CLOSE_SESSION;
195 msg.param1 = (unsigned long)handle;
196 msg.error = (unsigned long)context; /* using error to context */
197 msg.caller = (void *)this;
198 msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
201 if (ClientIPC::getInstance().sendMessage(&msg) == true)
203 rv = waitTimedCondition(0);
208 this->error = SCARD_ERROR_OPERATION_TIMEOUT;
213 _ERR("sendMessage failed");
214 this->error = SCARD_ERROR_IPC_FAILED;
218 if (this->error != SCARD_ERROR_OK)
220 ThrowError::throwError(this->error);
226 int Session::close(closeSessionCallback callback, void *userData)
228 int result = SCARD_ERROR_OK;
231 if (isClosed() == false)
236 /* request channel handle from server */
237 msg.message = Message::MSG_REQUEST_CLOSE_SESSION;
238 msg.param1 = (unsigned long)handle;
239 msg.error = (unsigned long)context; /* using error to context */
240 msg.caller = (void *)this;
241 msg.callback = (void *)callback;
242 msg.userParam = userData;
244 if (ClientIPC::getInstance().sendMessage(&msg) == false)
246 _ERR("sendMessage failed");
247 result = SCARD_ERROR_IPC_FAILED;
254 unsigned int Session::getChannelCountSync()
258 if (getReader()->isSecureElementPresent() == true)
264 #ifdef CLIENT_IPC_THREAD
265 /* request channel handle from server */
266 msg.message = Message::MSG_REQUEST_GET_CHANNEL_COUNT;
267 msg.param1 = (unsigned long)handle;
268 msg.error = (unsigned long)context; /* using error to context */
269 msg.caller = (void *)this;
270 msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
275 if (ClientIPC::getInstance().sendMessage(&msg) == true)
277 rv = waitTimedCondition(0);
281 this->error = SCARD_ERROR_OPERATION_TIMEOUT;
286 _ERR("sendMessage failed");
287 this->error = SCARD_ERROR_IPC_FAILED;
291 if (this->error != SCARD_ERROR_OK)
293 ThrowError::throwError(this->error);
299 _ERR("unavailable session");
300 throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE);
306 int Session::getChannelCount(getChannelCountCallback callback, void *userData)
310 if (getReader()->isSecureElementPresent() == true)
315 msg.message = Message::MSG_REQUEST_GET_CHANNEL_COUNT;
316 msg.param1 = (unsigned long)handle;
317 msg.error = (unsigned long)context; /* using error to context */
318 msg.caller = (void *)this;
319 msg.callback = (void *)callback;
320 msg.userParam = userData;
322 if (ClientIPC::getInstance().sendMessage(&msg) == true)
324 result = SCARD_ERROR_OK;
328 _ERR("sendMessage failed");
329 result = SCARD_ERROR_IPC_FAILED;
334 _ERR("unavailable session");
335 result = SCARD_ERROR_ILLEGAL_STATE;
341 Channel *Session::openChannelSync(int id, ByteArray aid)
342 throw (ExceptionBase &, ErrorIO &, ErrorIllegalState &,
343 ErrorIllegalParameter &, ErrorSecurity &)
345 openedChannel = NULL;
347 if (getReader()->isSecureElementPresent() == true)
352 #ifdef CLIENT_IPC_THREAD
353 /* request channel handle from server */
354 msg.message = Message::MSG_REQUEST_OPEN_CHANNEL;
356 msg.param2 = (unsigned long)handle;
358 msg.error = (unsigned long)context; /* using error to context */
359 msg.caller = (void *)this;
360 msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
363 if (ClientIPC::getInstance().sendMessage(&msg) == true)
365 rv = waitTimedCondition(0);
369 this->error = SCARD_ERROR_OPERATION_TIMEOUT;
374 _ERR("sendMessage failed");
375 this->error = SCARD_ERROR_IPC_FAILED;
379 if (this->error != SCARD_ERROR_OK)
381 ThrowError::throwError(this->error);
386 _ERR("unavailable session");
387 throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE);
390 return (Channel *)openedChannel;
393 int Session::openChannel(int id, ByteArray aid, openChannelCallback callback, void *userData)
397 if (getReader()->isSecureElementPresent() == true)
401 /* request channel handle from server */
402 msg.message = Message::MSG_REQUEST_OPEN_CHANNEL;
404 msg.param2 = (unsigned long)handle;
406 msg.error = (unsigned long)context; /* using error to context */
407 msg.caller = (void *)this;
408 msg.callback = (void *)callback;
409 msg.userParam = userData;
411 if (ClientIPC::getInstance().sendMessage(&msg) == true)
413 result = SCARD_ERROR_OK;
417 _ERR("sendMessage failed");
418 result = SCARD_ERROR_IPC_FAILED;
423 _ERR("unavailable session");
424 result = SCARD_ERROR_ILLEGAL_STATE;
430 Channel *Session::openBasicChannelSync(ByteArray aid)
431 throw (ErrorIO &, ErrorIllegalState &, ErrorIllegalParameter &, ErrorSecurity &)
433 return openChannelSync(0, aid);
436 Channel *Session::openBasicChannelSync(unsigned char *aid, unsigned int length)
437 throw (ErrorIO &, ErrorIllegalState &, ErrorIllegalParameter &, ErrorSecurity &)
439 return openBasicChannelSync(ByteArray(aid, length));
442 int Session::openBasicChannel(ByteArray aid, openChannelCallback callback, void *userData)
444 return openChannel(0, aid, callback, userData);
447 int Session::openBasicChannel(unsigned char *aid, unsigned int length,
448 openChannelCallback callback, void *userData)
450 return openBasicChannel(ByteArray(aid, length), callback, userData);
453 Channel *Session::openLogicalChannelSync(ByteArray aid)
454 throw (ErrorIO &, ErrorIllegalState &, ErrorIllegalParameter &, ErrorSecurity &)
456 return openChannelSync(1, aid);
459 Channel *Session::openLogicalChannelSync(unsigned char *aid, unsigned int length)
460 throw (ErrorIO &, ErrorIllegalState &, ErrorIllegalParameter &, ErrorSecurity &)
462 return openLogicalChannelSync(ByteArray(aid, length));
465 int Session::openLogicalChannel(ByteArray aid, openChannelCallback callback, void *userData)
467 return openChannel(1, aid, callback, userData);
470 int Session::openLogicalChannel(unsigned char *aid, unsigned int length,
471 openChannelCallback callback, void *userData)
473 return openLogicalChannel(ByteArray(aid, length), callback, userData);
476 bool Session::dispatcherCallback(void *message)
478 Message *msg = (Message *)message;
484 _ERR("message is null");
488 session = (Session *)msg->caller;
490 switch (msg->message)
492 case Message::MSG_REQUEST_OPEN_CHANNEL :
494 Channel *channel = NULL;
496 _INFO("MSG_REQUEST_OPEN_CHANNEL");
498 if (msg->param1 != 0)
500 /* create new instance of channel */
501 channel = new ClientChannel(session->context,
502 session, msg->param2, msg->data, (void *)msg->param1);
505 session->channels.push_back(channel);
509 _ERR("alloc failed");
511 msg->error = SCARD_ERROR_OUT_OF_MEMORY;
515 if (msg->isSynchronousCall() == true) /* synchronized call */
521 session->error = msg->error;
522 session->openedChannel = channel;
524 session->signalCondition();
525 session->syncUnlock();
527 else if (msg->callback != NULL)
529 openChannelCallback cb = (openChannelCallback)msg->callback;
532 cb(channel, msg->error, msg->userParam);
537 case Message::MSG_REQUEST_GET_ATR :
539 _INFO("MSG_REQUEST_GET_ATR");
541 if (msg->isSynchronousCall() == true) /* synchronized call */
546 session->error = msg->error;
547 session->atr = msg->data;
549 session->signalCondition();
550 session->syncUnlock();
552 else if (msg->callback != NULL)
554 getATRCallback cb = (getATRCallback)msg->callback;
557 cb(msg->data.getBuffer(), msg->data.getLength(), msg->error, msg->userParam);
562 case Message::MSG_REQUEST_CLOSE_SESSION :
564 _INFO("MSG_REQUEST_CLOSE_SESSION");
566 if (msg->isSynchronousCall() == true) /* synchronized call */
571 session->error = msg->error;
573 session->signalCondition();
574 session->syncUnlock();
576 else if (msg->callback != NULL)
578 closeSessionCallback cb = (closeSessionCallback)msg->callback;
581 cb(msg->error, msg->userParam);
586 case Message::MSG_REQUEST_GET_CHANNEL_COUNT :
588 _INFO("MSG_REQUEST_GET_CHANNEL_COUNT");
590 if (msg->isSynchronousCall() == true) /* synchronized call */
595 session->error = msg->error;
596 session->channelCount = msg->param1;
598 session->signalCondition();
599 session->syncUnlock();
601 else if (msg->callback != NULL)
603 getChannelCountCallback cb = (getChannelCountCallback)msg->callback;
606 cb(msg->param1, msg->error, msg->userParam);
612 _DBG("unknown message : %s", msg->toString());
620 } /* namespace smartcard_service_api */
623 #define SESSION_EXTERN_BEGIN \
624 if (handle != NULL) \
626 Session *session = (Session *)handle;
628 #define SESSION_EXTERN_END \
632 _ERR("Invalid param"); \
635 using namespace smartcard_service_api;
637 EXTERN_API reader_h session_get_reader(session_h handle)
639 reader_h reader = NULL;
641 SESSION_EXTERN_BEGIN;
642 reader = session->getReader();
648 EXTERN_API int session_get_atr(session_h handle, session_get_atr_cb callback, void *userData)
652 SESSION_EXTERN_BEGIN;
653 result = session->getATR((getATRCallback)callback, userData);
659 EXTERN_API int session_close(session_h handle, session_close_session_cb callback, void *userData)
663 SESSION_EXTERN_BEGIN;
664 result = session->close((closeSessionCallback)callback, userData);
670 EXTERN_API bool session_is_closed(session_h handle)
674 SESSION_EXTERN_BEGIN;
675 result = session->isClosed();
681 EXTERN_API void session_close_channels(session_h handle)
683 SESSION_EXTERN_BEGIN;
684 session->closeChannels();
688 EXTERN_API int session_open_basic_channel(session_h handle, unsigned char *aid,
689 unsigned int length, session_open_channel_cb callback, void *userData)
693 SESSION_EXTERN_BEGIN;
694 result = session->openBasicChannel(aid, length, (openChannelCallback)callback, userData);
700 EXTERN_API int session_open_logical_channel(session_h handle, unsigned char *aid,
701 unsigned int length, session_open_channel_cb callback, void *userData)
705 SESSION_EXTERN_BEGIN;
706 result = session->openLogicalChannel(aid, length, (openChannelCallback)callback, userData);
712 EXTERN_API int session_get_channel_count(session_h handle, session_get_channel_count_cb callback, void * userData)
716 SESSION_EXTERN_BEGIN;
717 result = session->getChannelCount((getChannelCountCallback)callback, userData);
723 EXTERN_API void session_destroy_instance(session_h handle)
727 EXTERN_API int session_get_atr_sync(session_h handle, unsigned char **buffer, unsigned int *length)
732 #ifdef CLIENT_IPC_THREAD
733 if (buffer == NULL || length == NULL)
736 SESSION_EXTERN_BEGIN;
737 temp = session->getATRSync();
738 if (temp.getLength() > 0)
740 *length = temp.getLength();
741 *buffer = (unsigned char *)calloc(1, *length);
742 memcpy(*buffer, temp.getBuffer(), *length);
752 EXTERN_API void session_close_sync(session_h handle)
754 #ifdef CLIENT_IPC_THREAD
755 SESSION_EXTERN_BEGIN;
756 session->closeSync();
761 EXTERN_API channel_h session_open_basic_channel_sync(session_h handle, unsigned char *aid, unsigned int length)
763 channel_h result = NULL;
765 #ifdef CLIENT_IPC_THREAD
766 SESSION_EXTERN_BEGIN;
767 result = session->openBasicChannelSync(aid, length);
774 EXTERN_API channel_h session_open_logical_channel_sync(session_h handle, unsigned char *aid, unsigned int length)
776 channel_h result = NULL;
778 #ifdef CLIENT_IPC_THREAD
779 SESSION_EXTERN_BEGIN;
780 result = session->openLogicalChannelSync(aid, length);
787 EXTERN_API unsigned int session_get_channel_count_sync(session_h handle)
789 unsigned int result = 0;
791 #ifdef CLIENT_IPC_THREAD
792 SESSION_EXTERN_BEGIN;
793 result = session->getChannelCountSync();