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 */
22 /* SLP library header */
27 #include "ClientIPC.h"
28 #include "ClientChannel.h"
29 #include "ReaderHelper.h"
30 #include "APDUHelper.h"
33 #define EXTERN_API __attribute__((visibility("default")))
36 namespace smartcard_service_api
38 ClientChannel::ClientChannel(void *context, Session *session,
39 int channelNum, ByteArray selectResponse, void *handle)
42 this->channelNum = -1;
48 SCARD_DEBUG_ERR("ClientIPC::getInstance() failed");
53 this->channelNum = channelNum;
54 this->handle = handle;
55 this->selectResponse = selectResponse;
56 this->context = context;
59 ClientChannel::~ClientChannel()
64 void ClientChannel::closeSync() throw(ErrorIO &, ErrorIllegalState &)
66 #ifdef CLIENT_IPC_THREAD
67 if (isClosed() == false)
69 if (getSession()->getReader()->isSecureElementPresent() == true)
74 /* send message to server */
75 msg.message = Message::MSG_REQUEST_CLOSE_CHANNEL;
76 msg.param1 = (unsigned long)handle;
77 msg.error = (unsigned long)context; /* using error to context */
78 msg.caller = (void *)this;
79 msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
82 if (ClientIPC::getInstance().sendMessage(&msg) == true)
84 rv = waitTimedCondition(0);
87 SCARD_DEBUG_ERR("closeSync failed [%d]", rv);
88 this->error = SCARD_ERROR_OPERATION_TIMEOUT;
93 SCARD_DEBUG_ERR("sendMessage failed");
94 this->error = SCARD_ERROR_IPC_FAILED;
100 if (this->error != SCARD_ERROR_OK)
102 ThrowError::throwError(this->error);
108 SCARD_DEBUG("unavailable channel");
114 int ClientChannel::close(closeCallback callback, void *userParam)
116 int result = SCARD_ERROR_OK;
118 if (isClosed() == false)
120 if (getSession()->getReader()->isSecureElementPresent() == true)
125 /* send message to server */
126 msg.message = Message::MSG_REQUEST_CLOSE_CHANNEL;
127 msg.param1 = (unsigned long)handle;
128 msg.error = (unsigned long)context; /* using error to context */
129 msg.caller = (void *)this;
130 msg.callback = (void *)callback;
131 msg.userParam = userParam;
133 if (ClientIPC::getInstance().sendMessage(&msg) == false)
135 result = SCARD_ERROR_IPC_FAILED;
140 SCARD_DEBUG_ERR("unavailable channel");
141 result = SCARD_ERROR_ILLEGAL_STATE;
148 int ClientChannel::transmitSync(ByteArray command, ByteArray &result)
149 throw(ErrorIO &, ErrorIllegalState &, ErrorIllegalParameter &, ErrorSecurity &)
151 int rv = SCARD_ERROR_OK;
152 if (getSession()->getReader()->isSecureElementPresent() == true)
156 #ifdef CLIENT_IPC_THREAD
157 /* send message to server */
158 msg.message = Message::MSG_REQUEST_TRANSMIT;
159 msg.param1 = (unsigned long)handle;
162 msg.error = (unsigned long)context; /* using error to context */
163 msg.caller = (void *)this;
164 msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
167 if (ClientIPC::getInstance().sendMessage(&msg) == true)
169 rv = waitTimedCondition(0);
178 SCARD_DEBUG_ERR("timeout");
180 this->error = SCARD_ERROR_OPERATION_TIMEOUT;
185 SCARD_DEBUG_ERR("sendMessage failed");
189 if (this->error != SCARD_ERROR_OK)
191 ThrowError::throwError(this->error);
197 SCARD_DEBUG_ERR("unavailable channel");
198 throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE);
204 int ClientChannel::transmit(ByteArray command, transmitCallback callback, void *userParam)
208 if (getSession()->getReader()->isSecureElementPresent() == true)
212 /* send message to server */
213 msg.message = Message::MSG_REQUEST_TRANSMIT;
214 msg.param1 = (unsigned long)handle;
217 msg.error = (unsigned long)context; /* using error to context */
218 msg.caller = (void *)this;
219 msg.callback = (void *)callback;
220 msg.userParam = userParam;
222 if (ClientIPC::getInstance().sendMessage(&msg) == true)
224 result = SCARD_ERROR_OK;
228 result = SCARD_ERROR_IPC_FAILED;
233 SCARD_DEBUG_ERR("unavailable channel");
234 result = SCARD_ERROR_ILLEGAL_STATE;
240 bool ClientChannel::dispatcherCallback(void *message)
242 Message *msg = (Message *)message;
243 ClientChannel *channel = NULL;
248 SCARD_DEBUG_ERR("message is null");
252 channel = (ClientChannel *)msg->caller;
254 switch (msg->message)
256 case Message::MSG_REQUEST_TRANSMIT :
258 /* transmit result */
259 SCARD_DEBUG("MSG_REQUEST_TRANSMIT");
261 if (msg->error == 0 &&
262 ResponseHelper::getStatus(msg->data) == 0)
264 /* store select response */
265 if (msg->data.getAt(1) == APDUCommand::INS_SELECT_FILE)
266 channel->setSelectResponse(msg->data);
269 if (msg->isSynchronousCall() == true) /* synchronized call */
275 channel->error = msg->error;
276 channel->response = msg->data;
278 channel->signalCondition();
279 channel->syncUnlock();
281 else if (msg->callback != NULL)
283 transmitCallback cb = (transmitCallback)msg->callback;
286 cb(msg->data.getBuffer(), msg->data.getLength(), msg->error, msg->userParam);
291 case Message::MSG_REQUEST_CLOSE_CHANNEL :
293 SCARD_DEBUG("MSG_REQUEST_CLOSE_CHANNEL");
295 if (msg->isSynchronousCall() == true) /* synchronized call */
300 channel->error = msg->error;
302 channel->signalCondition();
303 channel->syncUnlock();
305 else if (msg->callback != NULL)
307 closeCallback cb = (closeCallback)msg->callback;
310 cb(msg->error, msg->userParam);
316 SCARD_DEBUG("unknwon message : %s", msg->toString());
322 } /* namespace smartcard_service_api */
325 #define CHANNEL_EXTERN_BEGIN \
326 if (handle != NULL) \
328 ClientChannel *channel = (ClientChannel *)handle;
330 #define CHANNEL_EXTERN_END \
334 SCARD_DEBUG_ERR("Invalid param"); \
337 using namespace smartcard_service_api;
339 EXTERN_API int channel_close(channel_h handle, channel_close_cb callback, void *userParam)
343 CHANNEL_EXTERN_BEGIN;
344 result = channel->close((closeCallback)callback, userParam);
350 EXTERN_API int channel_transmit(channel_h handle, unsigned char *command,
351 unsigned int length, channel_transmit_cb callback, void *userParam)
355 CHANNEL_EXTERN_BEGIN;
358 temp.setBuffer(command, length);
359 result = channel->transmit(temp, (transmitCallback)callback, userParam);
365 EXTERN_API void channel_close_sync(channel_h handle)
367 #ifdef CLIENT_IPC_THREAD
368 CHANNEL_EXTERN_BEGIN;
371 channel->closeSync();
380 EXTERN_API int channel_transmit_sync(channel_h handle, unsigned char *command,
381 unsigned int cmd_len, unsigned char **response, unsigned int *resp_len)
385 #ifdef CLIENT_IPC_THREAD
386 if (command == NULL || cmd_len == 0 || response == NULL || resp_len == NULL)
389 CHANNEL_EXTERN_BEGIN;
390 ByteArray temp, resp;
392 temp.setBuffer(command, cmd_len);
396 result = channel->transmitSync(temp, resp);
397 if (resp.getLength() > 0)
399 *resp_len = resp.getLength();
400 *response = (unsigned char *)calloc(1, *resp_len);
401 memcpy(*response, resp.getBuffer(), *resp_len);
414 EXTERN_API bool channel_is_basic_channel(channel_h handle)
418 CHANNEL_EXTERN_BEGIN;
419 result = channel->isBasicChannel();
425 EXTERN_API bool channel_is_closed(channel_h handle)
429 CHANNEL_EXTERN_BEGIN;
430 result = channel->isClosed();
436 EXTERN_API unsigned int channel_get_select_response_length(channel_h handle)
438 unsigned int result = 0;
440 CHANNEL_EXTERN_BEGIN;
441 result = channel->getSelectResponse().getLength();
447 EXTERN_API bool channel_get_select_response(channel_h handle,
448 unsigned char *buffer, unsigned int length)
452 if (buffer == NULL || length == 0)
457 CHANNEL_EXTERN_BEGIN;
460 response = channel->getSelectResponse();
461 if (response.getLength() > 0)
463 memcpy(buffer, response.getBuffer(), MIN(length, response.getLength()));
471 EXTERN_API session_h channel_get_session(channel_h handle)
473 session_h session = NULL;
475 CHANNEL_EXTERN_BEGIN;
476 session = channel->getSession();
482 EXTERN_API void channel_destroy_instance(channel_h handle)