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("closeSync failed [%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);
110 _DBG("unavailable channel");
116 int ClientChannel::close(closeCallback callback, void *userParam)
118 int result = SCARD_ERROR_OK;
120 if (isClosed() == false)
122 if (getSession()->getReader()->isSecureElementPresent() == true)
127 /* send message to server */
128 msg.message = Message::MSG_REQUEST_CLOSE_CHANNEL;
129 msg.param1 = (unsigned long)handle;
130 msg.error = (unsigned long)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) == false)
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);
183 this->error = SCARD_ERROR_OPERATION_TIMEOUT;
188 _ERR("sendMessage failed");
192 if (this->error != SCARD_ERROR_OK)
194 ThrowError::throwError(this->error);
200 _ERR("unavailable channel");
201 throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE);
207 int ClientChannel::transmit(ByteArray command, transmitCallback callback, void *userParam)
211 if (getSession()->getReader()->isSecureElementPresent() == true)
215 /* send message to server */
216 msg.message = Message::MSG_REQUEST_TRANSMIT;
217 msg.param1 = (unsigned long)handle;
220 msg.error = (unsigned long)context; /* using error to context */
221 msg.caller = (void *)this;
222 msg.callback = (void *)callback;
223 msg.userParam = userParam;
225 if (ClientIPC::getInstance().sendMessage(&msg) == true)
227 result = SCARD_ERROR_OK;
231 result = SCARD_ERROR_IPC_FAILED;
236 _ERR("unavailable channel");
237 result = SCARD_ERROR_ILLEGAL_STATE;
243 bool ClientChannel::dispatcherCallback(void *message)
245 Message *msg = (Message *)message;
246 ClientChannel *channel = NULL;
251 _ERR("message is null");
255 channel = (ClientChannel *)msg->caller;
257 switch (msg->message)
259 case Message::MSG_REQUEST_TRANSMIT :
261 /* transmit result */
262 _DBG("MSG_REQUEST_TRANSMIT");
264 if (msg->error == 0 &&
265 ResponseHelper::getStatus(msg->data) == 0)
267 /* store select response */
268 if (msg->data.getAt(1) == APDUCommand::INS_SELECT_FILE)
269 channel->setSelectResponse(msg->data);
272 if (msg->isSynchronousCall() == true) /* synchronized call */
278 channel->error = msg->error;
279 channel->response = msg->data;
281 channel->signalCondition();
282 channel->syncUnlock();
284 else if (msg->callback != NULL)
286 transmitCallback cb = (transmitCallback)msg->callback;
289 cb(msg->data.getBuffer(), msg->data.getLength(), msg->error, msg->userParam);
294 case Message::MSG_REQUEST_CLOSE_CHANNEL :
296 _DBG("MSG_REQUEST_CLOSE_CHANNEL");
298 if (msg->isSynchronousCall() == true) /* synchronized call */
303 channel->error = msg->error;
305 channel->signalCondition();
306 channel->syncUnlock();
308 else if (msg->callback != NULL)
310 closeCallback cb = (closeCallback)msg->callback;
313 cb(msg->error, msg->userParam);
319 _DBG("Unknown message : %s", msg->toString());
325 } /* namespace smartcard_service_api */
328 #define CHANNEL_EXTERN_BEGIN \
329 if (handle != NULL) \
331 ClientChannel *channel = (ClientChannel *)handle;
333 #define CHANNEL_EXTERN_END \
337 _ERR("Invalid param"); \
340 using namespace smartcard_service_api;
342 EXTERN_API int channel_close(channel_h handle, channel_close_cb callback, void *userParam)
346 CHANNEL_EXTERN_BEGIN;
347 result = channel->close((closeCallback)callback, userParam);
353 EXTERN_API int channel_transmit(channel_h handle, unsigned char *command,
354 unsigned int length, channel_transmit_cb callback, void *userParam)
358 CHANNEL_EXTERN_BEGIN;
361 temp.setBuffer(command, length);
362 result = channel->transmit(temp, (transmitCallback)callback, userParam);
368 EXTERN_API void channel_close_sync(channel_h handle)
370 #ifdef CLIENT_IPC_THREAD
371 CHANNEL_EXTERN_BEGIN;
374 channel->closeSync();
383 EXTERN_API int channel_transmit_sync(channel_h handle, unsigned char *command,
384 unsigned int cmd_len, unsigned char **response, unsigned int *resp_len)
388 #ifdef CLIENT_IPC_THREAD
389 if (command == NULL || cmd_len == 0 || response == NULL || resp_len == NULL)
392 CHANNEL_EXTERN_BEGIN;
393 ByteArray temp, resp;
395 temp.setBuffer(command, cmd_len);
399 result = channel->transmitSync(temp, resp);
400 if (resp.getLength() > 0)
402 *resp_len = resp.getLength();
403 *response = (unsigned char *)calloc(1, *resp_len);
404 memcpy(*response, resp.getBuffer(), *resp_len);
417 EXTERN_API bool channel_is_basic_channel(channel_h handle)
421 CHANNEL_EXTERN_BEGIN;
422 result = channel->isBasicChannel();
428 EXTERN_API bool channel_is_closed(channel_h handle)
432 CHANNEL_EXTERN_BEGIN;
433 result = channel->isClosed();
439 EXTERN_API unsigned int channel_get_select_response_length(channel_h handle)
441 unsigned int result = 0;
443 CHANNEL_EXTERN_BEGIN;
444 result = channel->getSelectResponse().getLength();
450 EXTERN_API bool channel_get_select_response(channel_h handle,
451 unsigned char *buffer, unsigned int length)
455 if (buffer == NULL || length == 0)
460 CHANNEL_EXTERN_BEGIN;
463 response = channel->getSelectResponse();
464 if (response.getLength() > 0)
466 memcpy(buffer, response.getBuffer(), MIN(length, response.getLength()));
474 EXTERN_API session_h channel_get_session(channel_h handle)
476 session_h session = NULL;
478 CHANNEL_EXTERN_BEGIN;
479 session = channel->getSession();
485 EXTERN_API void channel_destroy_instance(channel_h handle)