Modify for NFC operation
[platform/core/connectivity/smartcard-plugin-nfc.git] / NFCTerminal.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 <cstdio>
19 #include <cstring>
20 #include <unistd.h>
21 #include <sys/time.h>
22 #include <glib.h>
23
24 /* local header */
25 #include "smartcard-types.h"
26 #include "Debug.h"
27 #include "TerminalInterface.h"
28 #include "NFCTerminal.h"
29
30 #ifndef EXPORT_API
31 #define EXPORT_API __attribute__((visibility("default")))
32 #endif
33
34 #define ASYNC
35
36 using namespace smartcard_service_api;
37
38 static const char *se_name = "eSE";
39
40 /* below functions will be called when dlopen or dlclose is called */
41 void __attribute__ ((constructor)) lib_init()
42 {
43 }
44
45 void __attribute__ ((destructor)) lib_fini()
46 {
47 }
48
49 /* below three functions must be implemented */
50 extern "C"
51 {
52 EXPORT_API const char *get_name()
53 {
54         return se_name;
55 }
56
57 EXPORT_API void *create_instance()
58 {
59         int value;
60
61         if (vconf_get_bool(VCONFKEY_NFC_ESE_DISABLE, &value) < 0)
62                 return NULL;
63
64         return value ? NULL : (void *)NFCTerminal::getInstance();
65 }
66
67 EXPORT_API void destroy_instance(void *instance)
68 {
69         NFCTerminal *inst = (NFCTerminal *)instance;
70
71         if (inst == NFCTerminal::getInstance())
72         {
73                 inst->finalize();
74         }
75         else
76         {
77                 _ERR("instance is invalid : getInstance [%p], instance [%p]",
78                                 NFCTerminal::getInstance(), instance);
79         }
80 }
81 }
82
83 namespace smartcard_service_api
84 {
85         NFCTerminal::NFCTerminal() : Terminal(), seHandle(NULL),
86                 present(false), referred(0)
87         {
88                 name = (char *)se_name;
89
90                 initialize();
91         }
92
93         NFCTerminal *NFCTerminal::getInstance()
94         {
95                 static NFCTerminal instance;
96
97                 return &instance;
98         }
99
100         NFCTerminal::~NFCTerminal()
101         {
102                 finalize();
103         }
104
105         void NFCTerminal::onActivationChanged(bool activated, void *userData)
106         {
107                 NFCTerminal *instance = (NFCTerminal *)userData;
108
109                 _ERR("nfc state changed [%s]", activated ? "activated" : "deactivated");
110
111                 if (activated == true) {
112                         if (instance->present == false) {
113                                 if (instance->open() == true) {
114                                         instance->present = true;
115                                         instance->close();
116
117                                         if (instance->statusCallback != NULL) {
118                                                 instance->statusCallback(
119                                                         instance->getName(),
120                                                         NOTIFY_SE_AVAILABLE,
121                                                         SCARD_ERROR_OK,
122                                                         NULL);
123                                         }
124                                 } else {
125                                         _ERR("ese open failed");
126                                 }
127                         } else {
128                                 /* okay */
129                         }
130                 } else {
131                         if (instance->present == true) {
132                                 instance->present = false;
133
134                                 if (instance->isClosed() == false) {
135                                         int ret;
136
137                                         /* close now */
138                                         ret = nfc_se_close_secure_element_internal(
139                                                 instance->seHandle);
140                                         if (ret != NFC_ERROR_NONE) {
141                                                 _ERR("nfc_se_close_secure_element failed [%d]", ret);
142                                         }
143
144                                         instance->seHandle = NULL;
145                                         instance->closed = true;
146                                         instance->referred = 0;
147                                 }
148
149                                 if (instance->statusCallback != NULL) {
150                                         instance->statusCallback(
151                                                 instance->getName(),
152                                                 NOTIFY_SE_NOT_AVAILABLE,
153                                                 SCARD_ERROR_OK,
154                                                 NULL);
155                                 }
156                         } else {
157                                 /* okay */
158                         }
159                 }
160         }
161
162         bool NFCTerminal::initialize()
163         {
164                 int ret;
165
166                 if (initialized == true)
167                         return initialized;
168
169                 ret = nfc_manager_initialize();
170                 if (ret == NFC_ERROR_NONE)
171                 {
172                         initialized = true;
173
174                         ret = nfc_manager_set_activation_changed_cb(
175                                 &NFCTerminal::onActivationChanged, this);
176                         if (ret != NFC_ERROR_NONE) {
177                                 _ERR("nfc_manager_set_activation_changed_cb failed, [%d]", ret);
178                         }
179
180                         if (nfc_manager_is_activated() == true) {
181                                 if (open() == true) {
182                                         present = true;
183                                         close();
184                                 } else {
185                                         _ERR("ese open failed");
186                                 }
187                         } else {
188                                 _ERR("nfc is not activated.");
189                         }
190                 }
191                 else
192                 {
193                         _ERR("net_nfc_initialize failed [%d]", ret);
194                 }
195
196                 return initialized;
197         }
198
199         void NFCTerminal::finalize()
200         {
201                 int ret;
202
203                 if (isClosed() == false) {
204                         /* close now */
205                         ret = nfc_se_close_secure_element_internal(seHandle);
206                         if (ret != NFC_ERROR_NONE) {
207                                 _ERR("nfc_se_close_secure_element failed [%d]", ret);
208                         }
209
210                         seHandle = NULL;
211                         closed = true;
212                         referred = 0;
213                 }
214
215                 present = false;
216
217                 nfc_manager_unset_activation_changed_cb();
218
219                 ret = nfc_manager_deinitialize();
220                 if (ret == NFC_ERROR_NONE) {
221                         initialized = false;
222                 } else {
223                         _ERR("nfc_manager_deinitialize failed [%d]", ret);
224                 }
225         }
226
227         bool NFCTerminal::open()
228         {
229                 int ret;
230
231                 _BEGIN();
232
233                 if (isInitialized()) {
234                         if (referred == 0) {
235                                 ret = nfc_se_open_secure_element_internal(NFC_SE_TYPE_ESE,
236                                         &seHandle);
237                                 if (ret == NFC_ERROR_NONE) {
238                                         closed = false;
239                                         referred++;
240                                 } else {
241                                         _ERR("nfc_se_open_secure_element_internal failed [%d]", ret);
242                                 }
243                         } else {
244                                 referred++;
245                         }
246
247                         _DBG("reference count [%d]", referred);
248                 }
249
250                 _END();
251
252                 return (isClosed() == false);
253         }
254
255         void NFCTerminal::close()
256         {
257                 int ret;
258
259                 _BEGIN();
260
261                 if (isInitialized())
262                 {
263                         if (referred <= 1) {
264                                 g_usleep(1000000);
265
266                                 ret = nfc_se_close_secure_element_internal(seHandle);
267                                 if (ret == NFC_ERROR_NONE) {
268                                         seHandle = NULL;
269                                         closed = true;
270                                         referred = 0;
271                                 } else {
272                                         _ERR("nfc_se_close_secure_element_internal failed [%d]", ret);
273                                 }
274                         } else {
275                                 referred--;
276                         }
277
278                         _DBG("reference count [%d]", referred);
279                 }
280
281                 _END();
282         }
283
284         int NFCTerminal::transmitSync(const ByteArray &command, ByteArray &response)
285         {
286                 int rv = SCARD_ERROR_NOT_INITIALIZED;
287
288                 _BEGIN();
289
290                 if (isClosed() == false)
291                 {
292                         if (command.size() > 0)
293                         {
294                                 uint8_t *resp = NULL;
295                                 uint32_t resp_len;
296
297                                 rv = nfc_se_send_apdu_internal(seHandle,
298                                         (uint8_t *)command.getBuffer(),
299                                         command.size(),
300                                         &resp,
301                                         &resp_len);
302                                 if (rv == NFC_ERROR_NONE &&
303                                         resp != NULL)
304                                 {
305                                         response.assign(resp, resp_len);
306
307                                         g_free(resp);
308                                 }
309                                 else
310                                 {
311                                         _ERR("nfc_se_send_apdu_internal failed, [%d]", rv);
312                                 }
313                         }
314                         else
315                         {
316                                 _ERR("invalid command");
317                         }
318                 }
319                 else
320                 {
321                         _ERR("closed...");
322                 }
323
324                 _END();
325
326                 return rv;
327         }
328
329         int NFCTerminal::getATRSync(ByteArray &atr)
330         {
331                 int rv = -1;
332
333                 _BEGIN();
334
335                 if (isClosed() == false)
336                 {
337                         uint8_t *temp = NULL;
338                         uint32_t temp_len;
339
340                         rv = nfc_se_get_atr_internal(seHandle, &temp, &temp_len);
341                         if (rv == NFC_ERROR_NONE && temp != NULL)
342                         {
343                                 atr.assign(temp, temp_len);
344                                 g_free(temp);
345                         }
346                         else
347                         {
348                                 _ERR("nfc_se_get_atr_internal failed");
349                         }
350                 }
351                 else
352                 {
353                         _ERR("closed...");
354                 }
355
356                 _END();
357
358                 return rv;
359         }
360 } /* namespace smartcard_service_api */