/*
-* Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
-
+ * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
/* standard library header */
+#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "Message.h"
#include "ClientIPC.h"
#include "ClientChannel.h"
+#include "ReaderHelper.h"
+#include "APDUHelper.h"
#ifndef EXTERN_API
#define EXTERN_API __attribute__((visibility("default")))
namespace smartcard_service_api
{
- ClientChannel::ClientChannel(void *context, Session *session, int channelNum, ByteArray selectResponse, void *handle):Channel(session)
+ ClientChannel::ClientChannel(void *context, Session *session,
+ int channelNum, ByteArray selectResponse, void *handle)
+ : Channel(session)
{
this->channelNum = -1;
this->handle = NULL;
if (handle == NULL)
{
- SCARD_DEBUG_ERR("ClientIPC::getInstance() failed");
+ _ERR("ClientIPC::getInstance() failed");
return;
}
ClientChannel::~ClientChannel()
{
- close(NULL, this);
+ closeSync();
}
void ClientChannel::closeSync()
+ throw(ExceptionBase &, ErrorIO &, ErrorSecurity &,
+ ErrorIllegalState &, ErrorIllegalParameter &)
{
- Message msg;
- int rv;
-
+#ifdef CLIENT_IPC_THREAD
if (isClosed() == false)
{
- /* send message to server */
- msg.message = Message::MSG_REQUEST_CLOSE_CHANNEL;
- msg.param1 = (int)handle;
- msg.error = (unsigned int)context; /* using error to context */
- msg.caller = (void *)this;
- msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
-
- ClientIPC::getInstance().sendMessage(&msg);
+ if (getSession()->getReader()->isSecureElementPresent() == true)
+ {
+ Message msg;
+ int rv;
+
+ /* send message to server */
+ msg.message = Message::MSG_REQUEST_CLOSE_CHANNEL;
+ msg.param1 = (unsigned long)handle;
+ msg.error = (unsigned long)context; /* using error to context */
+ msg.caller = (void *)this;
+ msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
+
+ syncLock();
+ if (ClientIPC::getInstance().sendMessage(&msg) == true)
+ {
+ rv = waitTimedCondition(0);
+ if (rv < 0)
+ {
+ _ERR("timeout [%d]", rv);
+ this->error = SCARD_ERROR_OPERATION_TIMEOUT;
+ }
+ }
+ else
+ {
+ _ERR("sendMessage failed");
+ this->error = SCARD_ERROR_IPC_FAILED;
+ }
+ syncUnlock();
- syncLock();
- rv = waitTimedCondition(0);
- syncUnlock();
+ channelNum = -1;
- if (rv < 0)
+ if (this->error != SCARD_ERROR_OK)
+ {
+ ThrowError::throwError(this->error);
+ }
+ }
+ else
{
- SCARD_DEBUG_ERR("closeSync failed [%d]", rv);
+ _INFO("unavailable channel");
}
-
- channelNum = -1;
}
+#endif
}
int ClientChannel::close(closeCallback callback, void *userParam)
{
- Message msg;
+ int result = SCARD_ERROR_OK;
if (isClosed() == false)
{
- channelNum = -1;
-
- /* send message to server */
- msg.message = Message::MSG_REQUEST_CLOSE_CHANNEL;
- msg.param1 = (int)handle;
- msg.error = (unsigned int)context; /* using error to context */
- msg.caller = (void *)this;
- msg.callback = (void *)callback;
- msg.userParam = userParam;
-
- ClientIPC::getInstance().sendMessage(&msg);
+ if (getSession()->getReader()->isSecureElementPresent() == true)
+ {
+ Message msg;
+ channelNum = -1;
+
+ /* send message to server */
+ msg.message = Message::MSG_REQUEST_CLOSE_CHANNEL;
+ msg.param1 = (unsigned long)handle;
+ msg.error = (unsigned long)context; /* using error to context */
+ msg.caller = (void *)this;
+ msg.callback = (void *)callback;
+ msg.userParam = userParam;
+
+ if (ClientIPC::getInstance().sendMessage(&msg) == false)
+ {
+ _ERR("sendMessage failed");
+ result = SCARD_ERROR_IPC_FAILED;
+ }
+ }
+ else
+ {
+ _ERR("unavailable channel");
+ result = SCARD_ERROR_ILLEGAL_STATE;
+ }
}
- return 0;
+ return result;
}
int ClientChannel::transmitSync(ByteArray command, ByteArray &result)
+ throw(ExceptionBase &, ErrorIO &, ErrorIllegalState &,
+ ErrorIllegalParameter &, ErrorSecurity &)
{
- Message msg;
- int rv;
-
- /* send message to server */
- msg.message = Message::MSG_REQUEST_TRANSMIT;
- msg.param1 = (int)handle;
- msg.param2 = 0;
- msg.data = command;
- msg.error = (unsigned int)context; /* using error to context */
- msg.caller = (void *)this;
- msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
+ int rv = SCARD_ERROR_OK;
+ if (getSession()->getReader()->isSecureElementPresent() == true)
+ {
+ Message msg;
- ClientIPC::getInstance().sendMessage(&msg);
+#ifdef CLIENT_IPC_THREAD
+ /* send message to server */
+ msg.message = Message::MSG_REQUEST_TRANSMIT;
+ msg.param1 = (unsigned long)handle;
+ msg.param2 = 0;
+ msg.data = command;
+ msg.error = (unsigned long)context; /* using error to context */
+ msg.caller = (void *)this;
+ msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
- syncLock();
- rv = waitTimedCondition(0);
- syncUnlock();
+ syncLock();
+ if (ClientIPC::getInstance().sendMessage(&msg) == true)
+ {
+ rv = waitTimedCondition(0);
+ if (rv >= 0)
+ {
+ result = response;
+ rv = SCARD_ERROR_OK;
+ }
+ else
+ {
+ _ERR("timeout [%d]", rv);
+ this->error = SCARD_ERROR_OPERATION_TIMEOUT;
+ }
+ }
+ else
+ {
+ _ERR("sendMessage failed");
+ }
+ syncUnlock();
- if (rv < 0)
+ if (this->error != SCARD_ERROR_OK)
+ {
+ ThrowError::throwError(this->error);
+ }
+#endif
+ }
+ else
{
- SCARD_DEBUG_ERR("clientIPC is null");
-
- return -1;
+ _ERR("unavailable channel");
+ throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE);
}
- result = response;
-
- return 0;
+ return rv;
}
int ClientChannel::transmit(ByteArray command, transmitCallback callback, void *userParam)
{
- Message msg;
+ int result;
- /* send message to server */
- msg.message = Message::MSG_REQUEST_TRANSMIT;
- msg.param1 = (int)handle;
- msg.param2 = 0;
- msg.data = command;
- msg.error = (unsigned int)context; /* using error to context */
- msg.caller = (void *)this;
- msg.callback = (void *)callback;
- msg.userParam = userParam;
+ if (getSession()->getReader()->isSecureElementPresent() == true)
+ {
+ Message msg;
- ClientIPC::getInstance().sendMessage(&msg);
+ /* send message to server */
+ msg.message = Message::MSG_REQUEST_TRANSMIT;
+ msg.param1 = (unsigned long)handle;
+ msg.param2 = 0;
+ msg.data = command;
+ msg.error = (unsigned long)context; /* using error to context */
+ msg.caller = (void *)this;
+ msg.callback = (void *)callback;
+ msg.userParam = userParam;
- return 0;
+ if (ClientIPC::getInstance().sendMessage(&msg) == true)
+ {
+ result = SCARD_ERROR_OK;
+ }
+ else
+ {
+ _ERR("sendMessage failed");
+ result = SCARD_ERROR_IPC_FAILED;
+ }
+ }
+ else
+ {
+ _ERR("unavailable channel");
+ result = SCARD_ERROR_ILLEGAL_STATE;
+ }
+
+ return result;
}
bool ClientChannel::dispatcherCallback(void *message)
if (msg == NULL)
{
- SCARD_DEBUG_ERR("message is null");
+ _ERR("message is null");
return result;
}
case Message::MSG_REQUEST_TRANSMIT :
{
/* transmit result */
- SCARD_DEBUG("MSG_REQUEST_TRANSMIT");
+ _INFO("MSG_REQUEST_TRANSMIT");
- if (msg->callback == (void *)channel) /* synchronized call */
+ if (msg->isSynchronousCall() == true) /* synchronized call */
{
/* sync call */
channel->syncLock();
case Message::MSG_REQUEST_CLOSE_CHANNEL :
{
- SCARD_DEBUG("MSG_REQUEST_CLOSE_CHANNEL");
+ _INFO("MSG_REQUEST_CLOSE_CHANNEL");
- if (msg->callback == (void *)channel) /* synchronized call */
+ if (msg->isSynchronousCall() == true) /* synchronized call */
{
/* sync call */
channel->syncLock();
break;
default:
- SCARD_DEBUG("unknwon message : %s", msg->toString());
+ _DBG("Unknown message : %s", msg->toString());
break;
}
} \
else \
{ \
- SCARD_DEBUG_ERR("Invalid param"); \
+ _ERR("Invalid param"); \
}
using namespace smartcard_service_api;
return result;
}
-EXTERN_API int channel_transmit(channel_h handle, unsigned char *command, unsigned int length, channel_transmit_cb callback, void *userParam)
+EXTERN_API int channel_transmit(channel_h handle, unsigned char *command,
+ unsigned int length, channel_transmit_cb callback, void *userParam)
{
int result = -1;
return result;
}
+EXTERN_API void channel_close_sync(channel_h handle)
+{
+#ifdef CLIENT_IPC_THREAD
+ CHANNEL_EXTERN_BEGIN;
+ try
+ {
+ channel->closeSync();
+ }
+ catch (...)
+ {
+ }
+ CHANNEL_EXTERN_END;
+#endif
+}
+
+EXTERN_API int channel_transmit_sync(channel_h handle, unsigned char *command,
+ unsigned int cmd_len, unsigned char **response, unsigned int *resp_len)
+{
+ int result = -1;
+
+#ifdef CLIENT_IPC_THREAD
+ if (command == NULL || cmd_len == 0 || response == NULL || resp_len == NULL)
+ return result;
+
+ CHANNEL_EXTERN_BEGIN;
+ ByteArray temp, resp;
+
+ temp.setBuffer(command, cmd_len);
+
+ try
+ {
+ result = channel->transmitSync(temp, resp);
+ if (resp.getLength() > 0)
+ {
+ *resp_len = resp.getLength();
+ *response = (unsigned char *)calloc(1, *resp_len);
+ memcpy(*response, resp.getBuffer(), *resp_len);
+ }
+ }
+ catch (...)
+ {
+ result = -1;
+ }
+ CHANNEL_EXTERN_END;
+#endif
+
+ return result;
+}
+
EXTERN_API bool channel_is_basic_channel(channel_h handle)
{
bool result = false;
return result;
}
-EXTERN_API bool channel_get_select_response(channel_h handle, unsigned char *buffer, unsigned int length)
+EXTERN_API bool channel_get_select_response(channel_h handle,
+ unsigned char *buffer, unsigned int length)
{
bool result = false;
EXTERN_API void channel_destroy_instance(channel_h handle)
{
- CHANNEL_EXTERN_BEGIN;
- delete channel;
- CHANNEL_EXTERN_END;
+ /* do nothing */
}