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 _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()
65 throw(ExceptionBase &, ErrorIO &, ErrorSecurity &,
66 ErrorIllegalState &, ErrorIllegalParameter &)
68 #ifdef CLIENT_IPC_THREAD
69 if (isClosed() == false)
71 if (getSession()->getReader()->isSecureElementPresent() == true)
76 /* send message to server */
77 msg.message = Message::MSG_REQUEST_CLOSE_CHANNEL;
78 msg.param1 = (unsigned long)handle;
79 msg.error = (unsigned long)context; /* using error to context */
80 msg.caller = (void *)this;
81 msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
84 if (ClientIPC::getInstance().sendMessage(&msg) == true)
86 rv = waitTimedCondition(0);
89 _ERR("timeout [%d]", rv);
90 this->error = SCARD_ERROR_OPERATION_TIMEOUT;
95 _ERR("sendMessage failed");
96 this->error = SCARD_ERROR_IPC_FAILED;
102 if (this->error != SCARD_ERROR_OK)
104 ThrowError::throwError(this->error);
109 _INFO("unavailable channel");
115 int ClientChannel::close(closeCallback callback, void *userParam)
117 int result = SCARD_ERROR_OK;
119 if (isClosed() == false)
121 if (getSession()->getReader()->isSecureElementPresent() == true)
126 /* send message to server */
127 msg.message = Message::MSG_REQUEST_CLOSE_CHANNEL;
128 msg.param1 = (unsigned long)handle;
129 msg.error = (unsigned long)context; /* using error to context */
130 msg.caller = (void *)this;
131 msg.callback = (void *)callback;
132 msg.userParam = userParam;
134 if (ClientIPC::getInstance().sendMessage(&msg) == false)
136 _ERR("sendMessage failed");
137 result = SCARD_ERROR_IPC_FAILED;
142 _ERR("unavailable channel");
143 result = SCARD_ERROR_ILLEGAL_STATE;
150 int ClientChannel::transmitSync(ByteArray command, ByteArray &result)
151 throw(ExceptionBase &, ErrorIO &, ErrorIllegalState &,
152 ErrorIllegalParameter &, ErrorSecurity &)
154 int rv = SCARD_ERROR_OK;
155 if (getSession()->getReader()->isSecureElementPresent() == true)
159 #ifdef CLIENT_IPC_THREAD
160 /* send message to server */
161 msg.message = Message::MSG_REQUEST_TRANSMIT;
162 msg.param1 = (unsigned long)handle;
165 msg.error = (unsigned long)context; /* using error to context */
166 msg.caller = (void *)this;
167 msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
170 if (ClientIPC::getInstance().sendMessage(&msg) == true)
172 rv = waitTimedCondition(0);
180 _ERR("timeout [%d]", rv);
181 this->error = SCARD_ERROR_OPERATION_TIMEOUT;
186 _ERR("sendMessage failed");
190 if (this->error != SCARD_ERROR_OK)
192 ThrowError::throwError(this->error);
198 _ERR("unavailable channel");
199 throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE);
205 int ClientChannel::transmit(ByteArray command, transmitCallback callback, void *userParam)
209 if (getSession()->getReader()->isSecureElementPresent() == true)
213 /* send message to server */
214 msg.message = Message::MSG_REQUEST_TRANSMIT;
215 msg.param1 = (unsigned long)handle;
218 msg.error = (unsigned long)context; /* using error to context */
219 msg.caller = (void *)this;
220 msg.callback = (void *)callback;
221 msg.userParam = userParam;
223 if (ClientIPC::getInstance().sendMessage(&msg) == true)
225 result = SCARD_ERROR_OK;
229 _ERR("sendMessage failed");
230 result = SCARD_ERROR_IPC_FAILED;
235 _ERR("unavailable channel");
236 result = SCARD_ERROR_ILLEGAL_STATE;
242 bool ClientChannel::dispatcherCallback(void *message)
244 Message *msg = (Message *)message;
245 ClientChannel *channel = NULL;
250 _ERR("message is null");
254 channel = (ClientChannel *)msg->caller;
256 switch (msg->message)
258 case Message::MSG_REQUEST_TRANSMIT :
260 /* transmit result */
261 _INFO("MSG_REQUEST_TRANSMIT");
263 if (msg->isSynchronousCall() == true) /* synchronized call */
269 channel->error = msg->error;
270 channel->response = msg->data;
272 channel->signalCondition();
273 channel->syncUnlock();
275 else if (msg->callback != NULL)
277 transmitCallback cb = (transmitCallback)msg->callback;
280 cb(msg->data.getBuffer(), msg->data.getLength(), msg->error, msg->userParam);
285 case Message::MSG_REQUEST_CLOSE_CHANNEL :
287 _INFO("MSG_REQUEST_CLOSE_CHANNEL");
289 if (msg->isSynchronousCall() == true) /* synchronized call */
294 channel->error = msg->error;
296 channel->signalCondition();
297 channel->syncUnlock();
299 else if (msg->callback != NULL)
301 closeCallback cb = (closeCallback)msg->callback;
304 cb(msg->error, msg->userParam);
310 _DBG("Unknown message : %s", msg->toString());
318 } /* namespace smartcard_service_api */
321 #define CHANNEL_EXTERN_BEGIN \
322 if (handle != NULL) \
324 ClientChannel *channel = (ClientChannel *)handle;
326 #define CHANNEL_EXTERN_END \
330 _ERR("Invalid param"); \
333 using namespace smartcard_service_api;
335 EXTERN_API int channel_close(channel_h handle, channel_close_cb callback, void *userParam)
339 CHANNEL_EXTERN_BEGIN;
340 result = channel->close((closeCallback)callback, userParam);
346 EXTERN_API int channel_transmit(channel_h handle, unsigned char *command,
347 unsigned int length, channel_transmit_cb callback, void *userParam)
351 CHANNEL_EXTERN_BEGIN;
354 temp.setBuffer(command, length);
355 result = channel->transmit(temp, (transmitCallback)callback, userParam);
361 EXTERN_API void channel_close_sync(channel_h handle)
363 #ifdef CLIENT_IPC_THREAD
364 CHANNEL_EXTERN_BEGIN;
367 channel->closeSync();
376 EXTERN_API int channel_transmit_sync(channel_h handle, unsigned char *command,
377 unsigned int cmd_len, unsigned char **response, unsigned int *resp_len)
381 #ifdef CLIENT_IPC_THREAD
382 if (command == NULL || cmd_len == 0 || response == NULL || resp_len == NULL)
385 CHANNEL_EXTERN_BEGIN;
386 ByteArray temp, resp;
388 temp.setBuffer(command, cmd_len);
392 result = channel->transmitSync(temp, resp);
393 if (resp.getLength() > 0)
395 *resp_len = resp.getLength();
396 *response = (unsigned char *)calloc(1, *resp_len);
397 memcpy(*response, resp.getBuffer(), *resp_len);
410 EXTERN_API bool channel_is_basic_channel(channel_h handle)
414 CHANNEL_EXTERN_BEGIN;
415 result = channel->isBasicChannel();
421 EXTERN_API bool channel_is_closed(channel_h handle)
425 CHANNEL_EXTERN_BEGIN;
426 result = channel->isClosed();
432 EXTERN_API unsigned int channel_get_select_response_length(channel_h handle)
434 unsigned int result = 0;
436 CHANNEL_EXTERN_BEGIN;
437 result = channel->getSelectResponse().getLength();
443 EXTERN_API bool channel_get_select_response(channel_h handle,
444 unsigned char *buffer, unsigned int length)
448 if (buffer == NULL || length == 0)
453 CHANNEL_EXTERN_BEGIN;
456 response = channel->getSelectResponse();
457 if (response.getLength() > 0)
459 memcpy(buffer, response.getBuffer(), MIN(length, response.getLength()));
467 EXTERN_API session_h channel_get_session(channel_h handle)
469 session_h session = NULL;
471 CHANNEL_EXTERN_BEGIN;
472 session = channel->getSession();
478 EXTERN_API void channel_destroy_instance(channel_h handle)