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"
32 #define EXTERN_API __attribute__((visibility("default")))
35 namespace smartcard_service_api
37 ClientChannel::ClientChannel(void *context, Session *session,
38 int channelNum, ByteArray selectResponse, void *handle)
41 this->channelNum = -1;
47 SCARD_DEBUG_ERR("ClientIPC::getInstance() failed");
52 this->channelNum = channelNum;
53 this->handle = handle;
54 this->selectResponse = selectResponse;
55 this->context = context;
58 ClientChannel::~ClientChannel()
63 void ClientChannel::closeSync() throw(ErrorIO &, ErrorIllegalState &)
65 #ifdef CLIENT_IPC_THREAD
66 if (isClosed() == false)
68 if (getSession()->getReader()->isSecureElementPresent() == true)
73 /* send message to server */
74 msg.message = Message::MSG_REQUEST_CLOSE_CHANNEL;
75 msg.param1 = (int)handle;
76 msg.error = (unsigned int)context; /* using error to context */
77 msg.caller = (void *)this;
78 msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
83 if (ClientIPC::getInstance().sendMessage(&msg) == true)
85 rv = waitTimedCondition(0);
88 SCARD_DEBUG_ERR("closeSync failed [%d]", rv);
93 SCARD_DEBUG_ERR("sendMessage failed");
94 throw ErrorIO(SCARD_ERROR_IPC_FAILED);
98 catch (ExceptionBase &e)
109 SCARD_DEBUG_ERR("unavailable channel");
115 int ClientChannel::close(closeCallback callback, void *userParam)
119 if (isClosed() == false)
121 if (getSession()->getReader()->isSecureElementPresent() == true)
127 /* send message to server */
128 msg.message = Message::MSG_REQUEST_CLOSE_CHANNEL;
129 msg.param1 = (int)handle;
130 msg.error = (unsigned int)context; /* using error to context */
131 msg.caller = (void *)this;
132 msg.callback = (void *)callback;
133 msg.userParam = userParam;
135 if (ClientIPC::getInstance().sendMessage(&msg) == true)
146 SCARD_DEBUG_ERR("unavailable channel");
154 int ClientChannel::transmitSync(ByteArray command, ByteArray &result)
155 throw(ErrorIO &, ErrorIllegalState &, ErrorIllegalParameter &, ErrorSecurity &)
159 if (getSession()->getReader()->isSecureElementPresent() == true)
163 #ifdef CLIENT_IPC_THREAD
164 /* send message to server */
165 msg.message = Message::MSG_REQUEST_TRANSMIT;
166 msg.param1 = (int)handle;
169 msg.error = (unsigned int)context; /* using error to context */
170 msg.caller = (void *)this;
171 msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
174 if (ClientIPC::getInstance().sendMessage(&msg) == true)
176 rv = waitTimedCondition(0);
185 SCARD_DEBUG_ERR("timeout");
192 SCARD_DEBUG_ERR("sendMessage failed");
199 SCARD_DEBUG_ERR("unavailable channel");
200 throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE);
206 int ClientChannel::transmit(ByteArray command, transmitCallback callback, void *userParam)
210 if (getSession()->getReader()->isSecureElementPresent() == true)
214 /* send message to server */
215 msg.message = Message::MSG_REQUEST_TRANSMIT;
216 msg.param1 = (int)handle;
219 msg.error = (unsigned int)context; /* using error to context */
220 msg.caller = (void *)this;
221 msg.callback = (void *)callback;
222 msg.userParam = userParam;
224 if (ClientIPC::getInstance().sendMessage(&msg) == true)
235 SCARD_DEBUG_ERR("unavailable channel");
241 bool ClientChannel::dispatcherCallback(void *message)
243 Message *msg = (Message *)message;
244 ClientChannel *channel = NULL;
249 SCARD_DEBUG_ERR("message is null");
253 channel = (ClientChannel *)msg->caller;
255 switch (msg->message)
257 case Message::MSG_REQUEST_TRANSMIT :
259 /* transmit result */
260 SCARD_DEBUG("MSG_REQUEST_TRANSMIT");
262 if (msg->isSynchronousCall() == true) /* synchronized call */
268 channel->error = msg->error;
269 channel->response = msg->data;
271 channel->signalCondition();
272 channel->syncUnlock();
274 else if (msg->callback != NULL)
276 transmitCallback cb = (transmitCallback)msg->callback;
279 cb(msg->data.getBuffer(), msg->data.getLength(), msg->error, msg->userParam);
284 case Message::MSG_REQUEST_CLOSE_CHANNEL :
286 SCARD_DEBUG("MSG_REQUEST_CLOSE_CHANNEL");
288 if (msg->isSynchronousCall() == true) /* synchronized call */
293 channel->error = msg->error;
295 channel->signalCondition();
296 channel->syncUnlock();
298 else if (msg->callback != NULL)
300 closeCallback cb = (closeCallback)msg->callback;
303 cb(msg->error, msg->userParam);
309 SCARD_DEBUG("unknwon message : %s", msg->toString());
315 } /* namespace smartcard_service_api */
318 #define CHANNEL_EXTERN_BEGIN \
319 if (handle != NULL) \
321 ClientChannel *channel = (ClientChannel *)handle;
323 #define CHANNEL_EXTERN_END \
327 SCARD_DEBUG_ERR("Invalid param"); \
330 using namespace smartcard_service_api;
332 EXTERN_API int channel_close(channel_h handle, channel_close_cb callback, void *userParam)
336 CHANNEL_EXTERN_BEGIN;
337 result = channel->close((closeCallback)callback, userParam);
343 EXTERN_API int channel_transmit(channel_h handle, unsigned char *command,
344 unsigned int length, channel_transmit_cb callback, void *userParam)
348 CHANNEL_EXTERN_BEGIN;
351 temp.setBuffer(command, length);
352 result = channel->transmit(temp, (transmitCallback)callback, userParam);
358 EXTERN_API void channel_close_sync(channel_h handle)
360 #ifdef CLIENT_IPC_THREAD
361 CHANNEL_EXTERN_BEGIN;
364 channel->closeSync();
373 EXTERN_API int channel_transmit_sync(channel_h handle, unsigned char *command,
374 unsigned int cmd_len, unsigned char **response, unsigned int *resp_len)
378 #ifdef CLIENT_IPC_THREAD
379 if (command == NULL || cmd_len == 0 || response == NULL || resp_len == NULL)
382 CHANNEL_EXTERN_BEGIN;
383 ByteArray temp, resp;
385 temp.setBuffer(command, cmd_len);
389 result = channel->transmitSync(temp, resp);
390 if (resp.getLength() > 0)
392 *resp_len = resp.getLength();
393 *response = (unsigned char *)calloc(1, *resp_len);
394 memcpy(*response, resp.getBuffer(), *resp_len);
407 EXTERN_API bool channel_is_basic_channel(channel_h handle)
411 CHANNEL_EXTERN_BEGIN;
412 result = channel->isBasicChannel();
418 EXTERN_API bool channel_is_closed(channel_h handle)
422 CHANNEL_EXTERN_BEGIN;
423 result = channel->isClosed();
429 EXTERN_API unsigned int channel_get_select_response_length(channel_h handle)
431 unsigned int result = 0;
433 CHANNEL_EXTERN_BEGIN;
434 result = channel->getSelectResponse().getLength();
440 EXTERN_API bool channel_get_select_response(channel_h handle,
441 unsigned char *buffer, unsigned int length)
445 if (buffer == NULL || length == 0)
450 CHANNEL_EXTERN_BEGIN;
453 response = channel->getSelectResponse();
454 if (response.getLength() > 0)
456 memcpy(buffer, response.getBuffer(), MIN(length, response.getLength()));
464 EXTERN_API session_h channel_get_session(channel_h handle)
466 session_h session = NULL;
468 CHANNEL_EXTERN_BEGIN;
469 session = channel->getSession();
475 EXTERN_API void channel_destroy_instance(channel_h handle)