8acb9a7c8a2d8744f83d50af7381d5a628084bd8
[framework/system/smartcard-service.git] / client / Reader.cpp
1 /*
2  * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 /* standard library header */
18 #include <stdio.h>
19 #include <string.h>
20 #include <unistd.h>
21
22 /* SLP library header */
23
24 /* local header */
25 #include "Debug.h"
26 #include "Message.h"
27 #include "ClientIPC.h"
28 #include "Reader.h"
29 #include "Session.h"
30
31 #ifndef EXTERN_API
32 #define EXTERN_API __attribute__((visibility("default")))
33 #endif
34
35 namespace smartcard_service_api
36 {
37         Reader::Reader(void *context, const char *name, void *handle)
38                 : ReaderHelper()
39         {
40                 unsigned int length = 0;
41
42                 SCARD_BEGIN();
43
44                 this->context = NULL;
45                 this->handle = NULL;
46
47                 if (context == NULL || name == NULL || strlen(name) == 0 || handle == NULL)
48                 {
49                         SCARD_DEBUG_ERR("invalid param");
50
51                         return;
52                 }
53
54                 this->handle = handle;
55                 this->context = context;
56
57                 length = strlen(name);
58                 length = (length < sizeof(this->name)) ? length : sizeof(this->name);
59                 memcpy(this->name, name, length);
60
61                 present = true;
62
63                 SCARD_END();
64         }
65
66         Reader::~Reader()
67         {
68                 size_t i;
69
70                 closeSessions();
71
72                 for (i = 0; i < sessions.size(); i++)
73                 {
74                         delete (Session *)sessions[i];
75                 }
76
77                 sessions.clear();
78         }
79
80         void Reader::closeSessions()
81                 throw(ErrorIO &, ErrorIllegalState &)
82         {
83                 size_t i;
84
85                 for (i = 0; i < sessions.size(); i++)
86                 {
87                         sessions[i]->closeSync();
88                 }
89         }
90
91         SessionHelper *Reader::openSessionSync()
92                 throw(ExceptionBase &, ErrorIO &, ErrorIllegalState &,
93                         ErrorIllegalParameter &, ErrorSecurity &)
94         {
95                 openedSession = NULL;
96
97                 if (isSecureElementPresent() == true)
98                 {
99                         Message msg;
100                         int rv;
101
102 #ifdef CLIENT_IPC_THREAD
103                         /* request channel handle from server */
104                         msg.message = Message::MSG_REQUEST_OPEN_SESSION;
105                         msg.param1 = (unsigned long)handle;
106                         msg.error = (unsigned long)context; /* using error to context */
107                         msg.caller = (void *)this;
108                         msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
109
110                         syncLock();
111                         if (ClientIPC::getInstance().sendMessage(&msg) == true)
112                         {
113                                 rv = waitTimedCondition(0);
114                                 if (rv != 0)
115                                 {
116                                         SCARD_DEBUG_ERR("time over");
117                                         this->error = SCARD_ERROR_OPERATION_TIMEOUT;
118                                 }
119                         }
120                         else
121                         {
122                                 SCARD_DEBUG_ERR("sendMessage failed");
123                                 this->error = SCARD_ERROR_IPC_FAILED;
124                         }
125                         syncUnlock();
126
127                         if (this->error != SCARD_ERROR_OK)
128                         {
129                                 ThrowError::throwError(this->error);
130                         }
131 #endif
132                 }
133                 else
134                 {
135                         SCARD_DEBUG_ERR("unavailable reader");
136                         throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE);
137                 }
138
139                 return (Session *)openedSession;
140         }
141
142         int Reader::openSession(openSessionCallback callback, void *userData)
143         {
144                 int result;
145
146                 SCARD_BEGIN();
147
148                 if (isSecureElementPresent() == true)
149                 {
150                         Message msg;
151
152                         /* request channel handle from server */
153                         msg.message = Message::MSG_REQUEST_OPEN_SESSION;
154                         msg.param1 = (unsigned long)handle;
155                         msg.error = (unsigned long)context; /* using error to context */
156                         msg.caller = (void *)this;
157                         msg.callback = (void *)callback;
158                         msg.userParam = userData;
159
160                         if (ClientIPC::getInstance().sendMessage(&msg) == true)
161                         {
162                                 result = SCARD_ERROR_OK;
163                         }
164                         else
165                         {
166                                 SCARD_DEBUG_ERR("sendMessage failed");
167                                 result = SCARD_ERROR_IPC_FAILED;
168                         }
169                 }
170                 else
171                 {
172                         SCARD_DEBUG_ERR("unavailable reader");
173                         result = SCARD_ERROR_ILLEGAL_STATE;
174                 }
175
176                 SCARD_END();
177
178                 return result;
179         }
180
181         bool Reader::dispatcherCallback(void *message)
182         {
183                 Message *msg = (Message *)message;
184                 Reader *reader;
185                 bool result = false;
186
187                 SCARD_BEGIN();
188
189                 if (msg == NULL)
190                 {
191                         SCARD_DEBUG_ERR("message is null");
192                         return result;
193                 }
194
195                 reader = (Reader *)msg->caller;
196
197                 switch (msg->message)
198                 {
199                 case Message::MSG_REQUEST_OPEN_SESSION :
200                         {
201                                 Session *session = NULL;
202
203                                 SCARD_DEBUG("MSG_REQUEST_OPEN_SESSION");
204
205                                 if (msg->param1 != 0)
206                                 {
207                                         /* create new instance of channel */
208                                         session = new Session(reader->context, reader, (void *)msg->param1);
209                                         if (session == NULL)
210                                         {
211                                                 SCARD_DEBUG_ERR("Session creating instance failed");
212
213                                                 return session;
214                                         }
215
216                                         reader->sessions.push_back(session);
217                                 }
218
219                                 if (msg->isSynchronousCall() == true) /* synchronized call */
220                                 {
221                                         /* sync call */
222                                         reader->syncLock();
223
224                                         /* copy result */
225                                         reader->error = msg->error;
226                                         reader->openedSession = session;
227                                         reader->signalCondition();
228
229                                         reader->syncUnlock();
230                                 }
231                                 else if (msg->callback != NULL)
232                                 {
233                                         openSessionCallback cb = (openSessionCallback)msg->callback;
234
235                                         /* async call */
236                                         cb(session, msg->error, msg->userParam);
237                                 }
238                         }
239                         break;
240
241                 default:
242                         SCARD_DEBUG("unknown [%s]", msg->toString());
243                         break;
244                 }
245
246                 SCARD_END();
247
248                 return result;
249         }
250
251 } /* namespace smartcard_service_api */
252
253 /* export C API */
254 #define READER_EXTERN_BEGIN \
255         if (handle != NULL) \
256         { \
257                 Reader *reader = (Reader *)handle;
258
259 #define READER_EXTERN_END \
260         } \
261         else \
262         { \
263                 SCARD_DEBUG_ERR("Invalid param"); \
264         }
265
266 using namespace smartcard_service_api;
267
268 EXTERN_API const char *reader_get_name(reader_h handle)
269 {
270         const char *name = NULL;
271
272         READER_EXTERN_BEGIN;
273         name = reader->getName();
274         READER_EXTERN_END;
275
276         return name;
277 }
278
279 EXTERN_API se_service_h reader_get_se_service(reader_h handle)
280 {
281         se_service_h service = NULL;
282
283         READER_EXTERN_BEGIN;
284         service = (se_service_h)reader->getSEService();
285         READER_EXTERN_END;
286
287         return service;
288 }
289
290 EXTERN_API bool reader_is_secure_element_present(reader_h handle)
291 {
292         bool result = false;
293
294         READER_EXTERN_BEGIN;
295         result = reader->isSecureElementPresent();
296         READER_EXTERN_END;
297
298         return result;
299 }
300
301 EXTERN_API int reader_open_session(reader_h handle, reader_open_session_cb callback, void *userData)
302 {
303         int result = -1;
304
305         READER_EXTERN_BEGIN;
306         result = reader->openSession((openSessionCallback)callback, userData);
307         READER_EXTERN_END;
308
309         return result;
310 }
311
312 EXTERN_API session_h reader_open_session_sync(reader_h handle)
313 {
314         session_h result = NULL;
315
316 #ifdef CLIENT_IPC_THREAD
317         READER_EXTERN_BEGIN;
318         result = (session_h)reader->openSessionSync();
319         READER_EXTERN_END;
320 #endif
321
322         return result;
323 }
324
325 EXTERN_API void reader_close_sessions(reader_h handle)
326 {
327         READER_EXTERN_BEGIN;
328         reader->closeSessions();
329         READER_EXTERN_END;
330 }
331
332 EXTERN_API void reader_destroy_instance(reader_h handle)
333 {
334 }