Return error code
[platform/core/connectivity/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(ErrorIO &, ErrorIllegalState &, ErrorIllegalParameter &, ErrorSecurity &)
93         {
94                 openedSession = NULL;
95
96                 if (isSecureElementPresent() == true)
97                 {
98                         Message msg;
99                         int rv;
100
101 #ifdef CLIENT_IPC_THREAD
102                         /* request channel handle from server */
103                         msg.message = Message::MSG_REQUEST_OPEN_SESSION;
104                         msg.param1 = (unsigned long)handle;
105                         msg.error = (unsigned long)context; /* using error to context */
106                         msg.caller = (void *)this;
107                         msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */
108
109                         syncLock();
110                         if (ClientIPC::getInstance().sendMessage(&msg) == true)
111                         {
112                                 rv = waitTimedCondition(0);
113                                 if (rv != 0)
114                                 {
115                                         SCARD_DEBUG_ERR("time over");
116                                         this->error = SCARD_ERROR_OPERATION_TIMEOUT;
117                                 }
118                         }
119                         else
120                         {
121                                 SCARD_DEBUG_ERR("sendMessage failed");
122                                 this->error = SCARD_ERROR_IPC_FAILED;
123                         }
124                         syncUnlock();
125
126                         if (this->error != SCARD_ERROR_OK)
127                         {
128                                 ThrowError::throwError(this->error);
129                         }
130 #endif
131                 }
132                 else
133                 {
134                         SCARD_DEBUG_ERR("unavailable reader");
135                         throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE);
136                 }
137
138                 return (Session *)openedSession;
139         }
140
141         int Reader::openSession(openSessionCallback callback, void *userData)
142         {
143                 int result;
144
145                 SCARD_BEGIN();
146
147                 if (isSecureElementPresent() == true)
148                 {
149                         Message msg;
150
151                         /* request channel handle from server */
152                         msg.message = Message::MSG_REQUEST_OPEN_SESSION;
153                         msg.param1 = (unsigned long)handle;
154                         msg.error = (unsigned long)context; /* using error to context */
155                         msg.caller = (void *)this;
156                         msg.callback = (void *)callback;
157                         msg.userParam = userData;
158
159                         if (ClientIPC::getInstance().sendMessage(&msg) == true)
160                         {
161                                 result = SCARD_ERROR_OK;
162                         }
163                         else
164                         {
165                                 SCARD_DEBUG_ERR("sendMessage failed");
166                                 result = SCARD_ERROR_IPC_FAILED;
167                         }
168                 }
169                 else
170                 {
171                         SCARD_DEBUG_ERR("unavailable reader");
172                         result = SCARD_ERROR_ILLEGAL_STATE;
173                 }
174
175                 SCARD_END();
176
177                 return result;
178         }
179
180         bool Reader::dispatcherCallback(void *message)
181         {
182                 Message *msg = (Message *)message;
183                 Reader *reader;
184                 bool result = false;
185
186                 SCARD_BEGIN();
187
188                 if (msg == NULL)
189                 {
190                         SCARD_DEBUG_ERR("message is null");
191                         return result;
192                 }
193
194                 reader = (Reader *)msg->caller;
195
196                 switch (msg->message)
197                 {
198                 case Message::MSG_REQUEST_OPEN_SESSION :
199                         {
200                                 Session *session = NULL;
201
202                                 SCARD_DEBUG("MSG_REQUEST_OPEN_SESSION");
203
204                                 if (msg->param1 != 0)
205                                 {
206                                         /* create new instance of channel */
207                                         session = new Session(reader->context, reader, (void *)msg->param1);
208                                         if (session == NULL)
209                                         {
210                                                 SCARD_DEBUG_ERR("Session creating instance failed");
211
212                                                 return session;
213                                         }
214
215                                         reader->sessions.push_back(session);
216                                 }
217
218                                 if (msg->isSynchronousCall() == true) /* synchronized call */
219                                 {
220                                         /* sync call */
221                                         reader->syncLock();
222
223                                         /* copy result */
224                                         reader->error = msg->error;
225                                         reader->openedSession = session;
226                                         reader->signalCondition();
227
228                                         reader->syncUnlock();
229                                 }
230                                 else if (msg->callback != NULL)
231                                 {
232                                         openSessionCallback cb = (openSessionCallback)msg->callback;
233
234                                         /* async call */
235                                         cb(session, msg->error, msg->userParam);
236                                 }
237                         }
238                         break;
239
240                 default:
241                         SCARD_DEBUG("unknown [%s]", msg->toString());
242                         break;
243                 }
244
245                 SCARD_END();
246
247                 return result;
248         }
249
250 } /* namespace smartcard_service_api */
251
252 /* export C API */
253 #define READER_EXTERN_BEGIN \
254         if (handle != NULL) \
255         { \
256                 Reader *reader = (Reader *)handle;
257
258 #define READER_EXTERN_END \
259         } \
260         else \
261         { \
262                 SCARD_DEBUG_ERR("Invalid param"); \
263         }
264
265 using namespace smartcard_service_api;
266
267 EXTERN_API const char *reader_get_name(reader_h handle)
268 {
269         const char *name = NULL;
270
271         READER_EXTERN_BEGIN;
272         name = reader->getName();
273         READER_EXTERN_END;
274
275         return name;
276 }
277
278 EXTERN_API se_service_h reader_get_se_service(reader_h handle)
279 {
280         se_service_h service = NULL;
281
282         READER_EXTERN_BEGIN;
283         service = (se_service_h)reader->getSEService();
284         READER_EXTERN_END;
285
286         return service;
287 }
288
289 EXTERN_API bool reader_is_secure_element_present(reader_h handle)
290 {
291         bool result = false;
292
293         READER_EXTERN_BEGIN;
294         result = reader->isSecureElementPresent();
295         READER_EXTERN_END;
296
297         return result;
298 }
299
300 EXTERN_API int reader_open_session(reader_h handle, reader_open_session_cb callback, void *userData)
301 {
302         int result = -1;
303
304         READER_EXTERN_BEGIN;
305         result = reader->openSession((openSessionCallback)callback, userData);
306         READER_EXTERN_END;
307
308         return result;
309 }
310
311 EXTERN_API session_h reader_open_session_sync(reader_h handle)
312 {
313         session_h result = NULL;
314
315 #ifdef CLIENT_IPC_THREAD
316         READER_EXTERN_BEGIN;
317         result = (session_h)reader->openSessionSync();
318         READER_EXTERN_END;
319 #endif
320
321         return result;
322 }
323
324 EXTERN_API void reader_close_sessions(reader_h handle)
325 {
326         READER_EXTERN_BEGIN;
327         reader->closeSessions();
328         READER_EXTERN_END;
329 }
330
331 EXTERN_API void reader_destroy_instance(reader_h handle)
332 {
333 }