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 result = SCARD_ERROR_IPC_FAILED;
164 result = SCARD_ERROR_OK;
166 /* TODO : invoke callback directly */
167 callback(atr.getBuffer(), atr.getLength(), 0, userData);
172 _ERR("unavailable session");
173 result = SCARD_ERROR_ILLEGAL_STATE;
179 void Session::closeSync()
180 throw (ExceptionBase &, ErrorIO &, ErrorSecurity &,
181 ErrorIllegalState &, ErrorIllegalParameter &)
186 #ifdef CLIENT_IPC_THREAD
187 if (isClosed() == false)
192 /* request channel handle from server */
193 msg.message = Message::MSG_REQUEST_CLOSE_SESSION;
194 msg.param1 = (unsigned long)handle;
195 msg.error = (unsigned long)context; /* using error to context */
196 msg.caller = (void *)this;
197 msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
200 if (ClientIPC::getInstance().sendMessage(&msg) == true)
202 rv = waitTimedCondition(0);
207 this->error = SCARD_ERROR_OPERATION_TIMEOUT;
212 _ERR("sendMessage failed");
213 this->error = SCARD_ERROR_IPC_FAILED;
217 if (this->error != SCARD_ERROR_OK)
219 ThrowError::throwError(this->error);
225 int Session::close(closeSessionCallback callback, void *userData)
227 int result = SCARD_ERROR_OK;
230 if (isClosed() == false)
235 /* request channel handle from server */
236 msg.message = Message::MSG_REQUEST_CLOSE_SESSION;
237 msg.param1 = (unsigned long)handle;
238 msg.error = (unsigned long)context; /* using error to context */
239 msg.caller = (void *)this;
240 msg.callback = (void *)callback;
241 msg.userParam = userData;
243 if (ClientIPC::getInstance().sendMessage(&msg) == false)
245 result = SCARD_ERROR_IPC_FAILED;
252 unsigned int Session::getChannelCountSync()
256 if (getReader()->isSecureElementPresent() == true)
262 #ifdef CLIENT_IPC_THREAD
263 /* request channel handle from server */
264 msg.message = Message::MSG_REQUEST_GET_CHANNEL_COUNT;
265 msg.param1 = (unsigned long)handle;
266 msg.error = (unsigned long)context; /* using error to context */
267 msg.caller = (void *)this;
268 msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
273 if (ClientIPC::getInstance().sendMessage(&msg) == true)
275 rv = waitTimedCondition(0);
279 this->error = SCARD_ERROR_OPERATION_TIMEOUT;
284 _ERR("sendMessage failed");
285 this->error = SCARD_ERROR_IPC_FAILED;
289 if (this->error != SCARD_ERROR_OK)
291 ThrowError::throwError(this->error);
297 _ERR("unavailable session");
298 throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE);
304 int Session::getChannelCount(getChannelCountCallback callback, void *userData)
308 if (getReader()->isSecureElementPresent() == true)
313 msg.message = Message::MSG_REQUEST_GET_CHANNEL_COUNT;
314 msg.param1 = (unsigned long)handle;
315 msg.error = (unsigned long)context; /* using error to context */
316 msg.caller = (void *)this;
317 msg.callback = (void *)callback;
318 msg.userParam = userData;
320 if (ClientIPC::getInstance().sendMessage(&msg) == true)
322 result = SCARD_ERROR_OK;
326 result = SCARD_ERROR_IPC_FAILED;
331 _ERR("unavailable session");
332 result = SCARD_ERROR_ILLEGAL_STATE;
338 Channel *Session::openChannelSync(int id, ByteArray aid)
339 throw (ExceptionBase &, ErrorIO &, ErrorIllegalState &,
340 ErrorIllegalParameter &, ErrorSecurity &)
342 openedChannel = NULL;
344 if (getReader()->isSecureElementPresent() == true)
349 #ifdef CLIENT_IPC_THREAD
350 /* request channel handle from server */
351 msg.message = Message::MSG_REQUEST_OPEN_CHANNEL;
353 msg.param2 = (unsigned long)handle;
355 msg.error = (unsigned long)context; /* using error to context */
356 msg.caller = (void *)this;
357 msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
360 if (ClientIPC::getInstance().sendMessage(&msg) == true)
362 rv = waitTimedCondition(0);
366 this->error = SCARD_ERROR_OPERATION_TIMEOUT;
371 _ERR("sendMessage failed");
372 this->error = SCARD_ERROR_IPC_FAILED;
376 if (this->error != SCARD_ERROR_OK)
378 ThrowError::throwError(this->error);
383 _ERR("unavailable session");
384 throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE);
387 return (Channel *)openedChannel;
390 int Session::openChannel(int id, ByteArray aid, openChannelCallback callback, void *userData)
394 if (getReader()->isSecureElementPresent() == true)
398 /* request channel handle from server */
399 msg.message = Message::MSG_REQUEST_OPEN_CHANNEL;
401 msg.param2 = (unsigned long)handle;
403 msg.error = (unsigned long)context; /* using error to context */
404 msg.caller = (void *)this;
405 msg.callback = (void *)callback;
406 msg.userParam = userData;
408 if (ClientIPC::getInstance().sendMessage(&msg) == true)
410 result = SCARD_ERROR_OK;
414 result = SCARD_ERROR_IPC_FAILED;
419 _ERR("unavailable session");
420 result = SCARD_ERROR_ILLEGAL_STATE;
426 Channel *Session::openBasicChannelSync(ByteArray aid)
427 throw (ErrorIO &, ErrorIllegalState &, ErrorIllegalParameter &, ErrorSecurity &)
429 return openChannelSync(0, aid);
432 Channel *Session::openBasicChannelSync(unsigned char *aid, unsigned int length)
433 throw (ErrorIO &, ErrorIllegalState &, ErrorIllegalParameter &, ErrorSecurity &)
435 return openBasicChannelSync(ByteArray(aid, length));
438 int Session::openBasicChannel(ByteArray aid, openChannelCallback callback, void *userData)
440 return openChannel(0, aid, callback, userData);
443 int Session::openBasicChannel(unsigned char *aid, unsigned int length,
444 openChannelCallback callback, void *userData)
446 return openBasicChannel(ByteArray(aid, length), callback, userData);
449 Channel *Session::openLogicalChannelSync(ByteArray aid)
450 throw (ErrorIO &, ErrorIllegalState &, ErrorIllegalParameter &, ErrorSecurity &)
452 return openChannelSync(1, aid);
455 Channel *Session::openLogicalChannelSync(unsigned char *aid, unsigned int length)
456 throw (ErrorIO &, ErrorIllegalState &, ErrorIllegalParameter &, ErrorSecurity &)
458 return openLogicalChannelSync(ByteArray(aid, length));
461 int Session::openLogicalChannel(ByteArray aid, openChannelCallback callback, void *userData)
463 return openChannel(1, aid, callback, userData);
466 int Session::openLogicalChannel(unsigned char *aid, unsigned int length,
467 openChannelCallback callback, void *userData)
469 return openLogicalChannel(ByteArray(aid, length), callback, userData);
472 bool Session::dispatcherCallback(void *message)
474 Message *msg = (Message *)message;
475 Session *session = NULL;
480 _ERR("message is null");
484 session = (Session *)msg->caller;
486 switch (msg->message)
488 case Message::MSG_REQUEST_OPEN_CHANNEL :
490 Channel *channel = NULL;
492 _DBG("MSG_REQUEST_OPEN_CHANNEL");
494 if (msg->param1 != 0)
496 /* create new instance of channel */
497 channel = new ClientChannel(session->context,
498 session, msg->param2, msg->data, (void *)msg->param1);
501 session->channels.push_back(channel);
505 _ERR("alloc failed");
507 msg->error = SCARD_ERROR_OUT_OF_MEMORY;
511 if (msg->isSynchronousCall() == true) /* synchronized call */
517 session->error = msg->error;
518 session->openedChannel = channel;
520 session->signalCondition();
521 session->syncUnlock();
523 else if (msg->callback != NULL)
525 openChannelCallback cb = (openChannelCallback)msg->callback;
528 cb(channel, msg->error, msg->userParam);
533 case Message::MSG_REQUEST_GET_ATR :
535 _DBG("MSG_REQUEST_GET_ATR");
537 if (msg->isSynchronousCall() == true) /* synchronized call */
542 session->error = msg->error;
543 session->atr = msg->data;
545 session->signalCondition();
546 session->syncUnlock();
548 else if (msg->callback != NULL)
550 getATRCallback cb = (getATRCallback)msg->callback;
553 cb(msg->data.getBuffer(), msg->data.getLength(), msg->error, msg->userParam);
558 case Message::MSG_REQUEST_CLOSE_SESSION :
560 _DBG("MSG_REQUEST_CLOSE_SESSION");
562 if (msg->isSynchronousCall() == true) /* synchronized call */
567 session->error = msg->error;
569 session->signalCondition();
570 session->syncUnlock();
572 else if (msg->callback != NULL)
574 closeSessionCallback cb = (closeSessionCallback)msg->callback;
577 cb(msg->error, msg->userParam);
582 case Message::MSG_REQUEST_GET_CHANNEL_COUNT :
584 _DBG("MSG_REQUEST_GET_CHANNEL_COUNT");
586 if (msg->isSynchronousCall() == true) /* synchronized call */
591 session->error = msg->error;
592 session->channelCount = msg->param1;
594 session->signalCondition();
595 session->syncUnlock();
597 else if (msg->callback != NULL)
599 getChannelCountCallback cb = (getChannelCountCallback)msg->callback;
602 cb(msg->param1, msg->error, msg->userParam);
608 _DBG("unknown message : %s", msg->toString());
614 } /* namespace smartcard_service_api */
617 #define SESSION_EXTERN_BEGIN \
618 if (handle != NULL) \
620 Session *session = (Session *)handle;
622 #define SESSION_EXTERN_END \
626 _ERR("Invalid param"); \
629 using namespace smartcard_service_api;
631 EXTERN_API reader_h session_get_reader(session_h handle)
633 reader_h reader = NULL;
635 SESSION_EXTERN_BEGIN;
636 reader = session->getReader();
642 EXTERN_API int session_get_atr(session_h handle, session_get_atr_cb callback, void *userData)
646 SESSION_EXTERN_BEGIN;
647 result = session->getATR((getATRCallback)callback, userData);
653 EXTERN_API int session_close(session_h handle, session_close_session_cb callback, void *userData)
657 SESSION_EXTERN_BEGIN;
658 result = session->close((closeSessionCallback)callback, userData);
664 EXTERN_API bool session_is_closed(session_h handle)
668 SESSION_EXTERN_BEGIN;
669 result = session->isClosed();
675 EXTERN_API void session_close_channels(session_h handle)
677 SESSION_EXTERN_BEGIN;
678 session->closeChannels();
682 EXTERN_API int session_open_basic_channel(session_h handle, unsigned char *aid,
683 unsigned int length, session_open_channel_cb callback, void *userData)
687 SESSION_EXTERN_BEGIN;
688 result = session->openBasicChannel(aid, length, (openChannelCallback)callback, userData);
694 EXTERN_API int session_open_logical_channel(session_h handle, unsigned char *aid,
695 unsigned int length, session_open_channel_cb callback, void *userData)
699 SESSION_EXTERN_BEGIN;
700 result = session->openLogicalChannel(aid, length, (openChannelCallback)callback, userData);
706 EXTERN_API int session_get_channel_count(session_h handle, session_get_channel_count_cb callback, void * userData)
710 SESSION_EXTERN_BEGIN;
711 result = session->getChannelCount((getChannelCountCallback)callback, userData);
717 EXTERN_API void session_destroy_instance(session_h handle)
721 EXTERN_API int session_get_atr_sync(session_h handle, unsigned char **buffer, unsigned int *length)
726 #ifdef CLIENT_IPC_THREAD
727 if (buffer == NULL || length == NULL)
730 SESSION_EXTERN_BEGIN;
731 temp = session->getATRSync();
732 if (temp.getLength() > 0)
734 *length = temp.getLength();
735 *buffer = (unsigned char *)calloc(1, *length);
736 memcpy(*buffer, temp.getBuffer(), *length);
746 EXTERN_API void session_close_sync(session_h handle)
748 #ifdef CLIENT_IPC_THREAD
749 SESSION_EXTERN_BEGIN;
750 session->closeSync();
755 EXTERN_API channel_h session_open_basic_channel_sync(session_h handle, unsigned char *aid, unsigned int length)
757 channel_h result = NULL;
759 #ifdef CLIENT_IPC_THREAD
760 SESSION_EXTERN_BEGIN;
761 result = session->openBasicChannelSync(aid, length);
768 EXTERN_API channel_h session_open_logical_channel_sync(session_h handle, unsigned char *aid, unsigned int length)
770 channel_h result = NULL;
772 #ifdef CLIENT_IPC_THREAD
773 SESSION_EXTERN_BEGIN;
774 result = session->openLogicalChannelSync(aid, length);
781 EXTERN_API unsigned int session_get_channel_count_sync(session_h handle)
783 unsigned int result = 0;
785 #ifdef CLIENT_IPC_THREAD
786 SESSION_EXTERN_BEGIN;
787 result = session->getChannelCountSync();