Initial commit
[platform/core/connectivity/smartcard-plugin-usb.git] / USBTerminal.cpp
1 /*
2  * Copyright (c) 2021 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 #include <cstdio>
18 #include <cstring>
19 #include <unistd.h>
20 #include <sys/time.h>
21 #include <sys/types.h>
22
23 #include "smartcard-types.h"
24 #include "Debug.h"
25 #include "TerminalInterface.h"
26 #include "USBTerminal.h"
27
28 #ifndef EXPORT_API
29 #define EXPORT_API __attribute__((visibility("default")))
30 #endif
31
32 typedef struct _callback_param_t
33 {
34         void *callback;
35         void *param;
36 }
37 callback_param_t;
38
39 using namespace smartcard_service_api;
40
41 static const char *se_name = "USB0";
42
43 void __attribute__ ((constructor)) lib_init()
44 {
45 }
46
47 void __attribute__ ((destructor)) lib_fini()
48 {
49 }
50
51 /* below three functions must be implemented */
52 extern "C" EXPORT_API const char *get_name()
53 {
54         return se_name;
55 }
56
57 extern "C" EXPORT_API void *create_instance()
58 {
59         return (void *)USBTerminal::getInstance();
60 }
61
62 extern "C" EXPORT_API void destroy_instance(void *instance)
63 {
64         USBTerminal *inst = (USBTerminal *)instance;
65         if (inst == USBTerminal::getInstance())
66         {
67                 inst->finalize();
68         }
69         else
70         {
71                 _ERR("instance is invalid : getInstance [%p], instance [%p]",
72                         USBTerminal::getInstance(), instance);
73         }
74 }
75
76 namespace smartcard_service_api
77 {
78         USBTerminal::USBTerminal() : Terminal()
79         {
80                 name = (char *)se_name;
81                 cardConnected = false;
82                 readerConnected = false;
83                 readerStates[0].szReader                = "\\\\?PnP?\\Notification"; // name of the card reader to monitor
84                 readerStates[0].dwCurrentState  = SCARD_STATE_UNAWARE;
85                 readerStates[0].dwEventState    = SCARD_STATE_UNKNOWN;
86
87                 initialize();
88         }
89
90         USBTerminal::~USBTerminal()
91         {
92                 finalize();
93         }
94
95         USBTerminal *USBTerminal::getInstance()
96         {
97                 static USBTerminal instance;
98
99                 return &instance;
100         }
101
102         bool USBTerminal::initialize()
103         {
104                 _BEGIN();
105
106                 if (initialized == false)
107                 {
108                         LONG rv = SCARD_S_SUCCESS;
109                         LPSTR readerName = NULL;
110                         DWORD readerLen;
111
112                         rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &mainContext);
113                         if (rv != SCARD_S_SUCCESS)
114                         {
115                                 _ERR("SCardEstablishContext failed : %s", pcsc_stringify_error(rv));
116                                 return false;
117                         }
118
119
120                         readerLen = SCARD_AUTOALLOCATE;
121                         rv = SCardListReaders(mainContext, NULL, (LPSTR)&readerName, &readerLen);
122                         if (rv == SCARD_S_SUCCESS)
123                         {
124                                 _INFO("Reader Connected : %s", readerName);
125                                 readerStates[1].szReader = readerName;
126                                 readerStates[1].dwCurrentState  = SCARD_STATE_UNAWARE;
127                                 readerStates[1].dwEventState = SCARD_STATE_UNKNOWN;
128
129                                 readerConnected = true;
130                         }
131
132                         monitorEventsThreadId = pthread_create(&monitorEventsThread, NULL, USBTerminal::monitorEvents, NULL);
133
134                         if (monitorEventsThreadId >= 0)
135                         {
136                                 initialized = true;
137                         }
138                         else
139                         {
140                                 _ERR("initialize failed");
141                         }
142                 }
143
144                 _END();
145
146                 return initialized;
147         }
148
149         void USBTerminal::finalize()
150         {
151                 _BEGIN();
152
153                 if (isInitialized())
154                 {
155                         initialized = false;
156                         SCardCancel(monitorEventsThreadContext);
157                         pthread_join(monitorEventsThread, NULL);
158
159                         if (readerStates[1].szReader != NULL)
160                                 free((void *)readerStates[1].szReader);
161                 }
162
163                 _END();
164         }
165
166         bool USBTerminal::open()
167         {
168                 _BEGIN();
169
170                 _INFO("Nothing to do for open operation");
171
172                 _END();
173
174                 return true;
175         }
176
177         void USBTerminal::close()
178         {
179                 _BEGIN();
180
181                 _INFO("Nothing to do for close operation");
182
183                 _END();
184         }
185
186         int USBTerminal::transmitSync(const ByteArray &command,
187                 ByteArray &response)
188         {
189                 int result = SCARD_ERROR_OK;
190
191                 _BEGIN();
192
193                 if (cardConnected == true)
194                 {
195                         if (command.size() > 0)
196                         {
197                                 LONG rv = SCARD_S_SUCCESS;
198                                 const uint8_t *send = command.getBuffer();
199                                 unsigned int send_len = command.size();
200                                 uint8_t resp[MAX_BUFFER_SIZE] = {0,};
201                                 uint32_t resp_len = MAX_BUFFER_SIZE;
202                                 SCARD_IO_REQUEST pioRecvPci;
203
204                                 _INFO("Sending: %s", command.toString().c_str());
205
206                                 rv = SCardTransmit(cardHandle, activeProtocol, send, send_len,
207                                         &pioRecvPci, resp, (LPDWORD)&resp_len);
208                                 if (rv == SCARD_S_SUCCESS)
209                                 {
210                                         response.assign(resp, resp_len);
211                                         _INFO("Received: %s", response.toString().c_str());
212                                 }
213                                 else
214                                 {
215                                         _ERR("SCardTransmit failed, [%s]", pcsc_stringify_error(rv));
216
217                                         result = SCARD_ERROR_IO_FAILED;
218                                 }
219                         }
220                         else
221                         {
222                                 _ERR("apdu is empty");
223
224                                 result = SCARD_ERROR_ILLEGAL_PARAM;
225                         }
226                 }
227                 else
228                 {
229                         _ERR("Card is not connected");
230
231                         result = SCARD_ERROR_SE_NOT_INITIALIZED;
232                 }
233
234                 _END();
235
236                 return result;
237         }
238
239         int USBTerminal::getATRSync(ByteArray &atr)
240         {
241                 int result = SCARD_ERROR_OK;
242
243                 _BEGIN();
244
245                 if (cardConnected == true)
246                 {
247                         atr = currentAtr;
248                 }
249                 else
250                 {
251                         _ERR("Card is not connected");
252
253                         result = SCARD_ERROR_SE_NOT_INITIALIZED;
254                 }
255
256                 _END();
257
258                 return result;
259         }
260
261         int USBTerminal::transmit(const ByteArray &command, terminalTransmitCallback callback, void *userData)
262         {
263                 _INFO("transmit Async function is not supported");
264
265                 return SCARD_ERROR_NOT_SUPPORTED;
266         }
267
268         int USBTerminal::getATR(terminalGetATRCallback callback, void *userData)
269         {
270                 _INFO("Get ATR Async function is not supported");
271
272                 return SCARD_ERROR_NOT_SUPPORTED;
273         }
274
275         bool USBTerminal::isSecureElementPresence() const
276         {
277                 _BEGIN();
278
279                 _INFO("isReaderConnected : %d", isReaderConnected());
280
281                 _END();
282
283                 return isReaderConnected();
284         }
285
286         gboolean USBTerminal::cardConnect(gpointer user_data)
287         {
288                 _BEGIN();
289
290                 LONG rv;
291                 USBTerminal *mTerminal = USBTerminal::getInstance();
292                 SCARDHANDLE hCard;
293                 char pbReader[MAX_READERNAME] = "";
294                 BYTE pbAtr[MAX_ATR_SIZE] = "";
295                 DWORD dwActiveProtocol, dwReaderLen, dwState, dwProt, dwAtrLen;
296                 pthread_mutex_t *eventMutex = (pthread_mutex_t *)user_data;
297                 const char *readerName = mTerminal->readerStates[1].szReader;
298
299                 if (eventMutex == NULL)
300                 {
301                         _INFO("eventMutex is NULL");
302                         return false;
303                 }
304
305                 pthread_mutex_lock(eventMutex);
306
307                 if (mTerminal->isReaderConnected() != true || readerName == NULL)
308                 {
309                         _INFO("Reader is not connected");
310                         pthread_mutex_unlock(eventMutex);
311                         return false;
312                 }
313
314
315                 dwActiveProtocol = -1;
316                 rv = SCardConnect(mTerminal->getMainContext(), readerName, SCARD_SHARE_SHARED,
317                         SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol);
318                 if (rv != SCARD_S_SUCCESS)
319                 {
320                         _INFO("SCardConnect failed : %s", pcsc_stringify_error(rv));
321                         pthread_mutex_unlock(eventMutex);
322                         return false;
323                 }
324
325                 _INFO("Card Inserted");
326                 mTerminal->setCardConnected(true);
327                 mTerminal->setCardHandle(hCard);
328
329                 _INFO(" Protocol: %ld\n", dwActiveProtocol);
330                 switch(dwActiveProtocol)
331                 {
332                         case SCARD_PROTOCOL_T0:
333                                 mTerminal->setActiveProtocol(SCARD_PCI_T0);
334                                 break;
335                         case SCARD_PROTOCOL_T1:
336                                 mTerminal->setActiveProtocol(SCARD_PCI_T1);
337                                 break;
338                         default:
339                                 _INFO("Unknown protocol. set default protocol");
340                                 mTerminal->setActiveProtocol(SCARD_PCI_T1);
341                 }
342
343                 dwAtrLen = sizeof(pbAtr);
344                 dwReaderLen = sizeof(pbReader);
345                 rv = SCardStatus(hCard, pbReader, &dwReaderLen, &dwState, &dwProt,
346                         pbAtr, &dwAtrLen);
347                 if (rv != SCARD_S_SUCCESS)
348                 {
349                         _INFO("SCardStatus failed : %s", pcsc_stringify_error(rv));
350                         pthread_mutex_unlock(eventMutex);
351                         return false;
352                 }
353
354                 _INFO(" Reader: %s (length %ld bytes)", pbReader, dwReaderLen);
355                 _INFO(" State: 0x%lX", dwState);
356                 _INFO(" Prot: %ld", dwProt);
357                 _INFO(" ATR (length %ld bytes):", dwAtrLen);
358
359                 ByteArray atrArray(pbAtr, dwAtrLen);
360                 _INFO("    %s", atrArray.toString().c_str());
361                 mTerminal->setCurrentAtr(atrArray);
362
363                 pthread_mutex_unlock(eventMutex);
364
365                 if (mTerminal->statusCallback != NULL)
366                         mTerminal->statusCallback(mTerminal->getName(), NOTIFY_CARD_AVAILABLE, SCARD_ERROR_OK, NULL);
367
368                 _END();
369
370                 return false;
371         }
372
373         gboolean USBTerminal::cardDisconnect(gpointer user_data)
374         {
375                 _BEGIN();
376
377                 USBTerminal *mTerminal = USBTerminal::getInstance();
378                 pthread_mutex_t *eventMutex = (pthread_mutex_t *)user_data;
379
380                 _INFO("Card Removed");
381
382                 pthread_mutex_lock(eventMutex);
383
384                 mTerminal->setCardConnected(false);
385
386                 pthread_mutex_unlock(eventMutex);
387
388                 if (mTerminal->statusCallback != NULL)
389                         mTerminal->statusCallback(mTerminal->getName(), NOTIFY_CARD_NOT_AVAILABLE, SCARD_ERROR_OK, NULL);
390
391                 _END();
392
393                 return false;
394         }
395
396         int USBTerminal::resetReaderStates(SCARDCONTEXT hContext)
397         {
398                 int readerCount = 1;
399                 LONG rv;
400                 LPSTR readerName = NULL;
401                 DWORD readerLen;
402
403                 USBTerminal *mTerminal = USBTerminal::getInstance();
404
405                 _BEGIN();
406
407                 readerLen = SCARD_AUTOALLOCATE;
408                 rv = SCardListReaders(hContext, NULL, (LPSTR)&readerName, &readerLen);
409                 if (rv == SCARD_S_SUCCESS)
410                 {
411                         _INFO("[Monitor] Reader Connected : %s", readerName);
412
413                         if (mTerminal->readerStates[1].szReader != NULL)
414                                 free((void *)mTerminal->readerStates[1].szReader);
415
416                         mTerminal->readerStates[1].szReader = readerName;
417                         mTerminal->readerStates[1].dwCurrentState       = SCARD_STATE_UNAWARE;
418                         mTerminal->readerStates[1].dwEventState = SCARD_STATE_UNKNOWN;
419
420                         mTerminal->setReaderConnected(true);
421                         readerCount = 2;
422
423                         if (mTerminal->statusCallback != NULL)
424                                 mTerminal->statusCallback(mTerminal->getName(), NOTIFY_SE_AVAILABLE, SCARD_ERROR_OK, NULL);
425                 }
426                 else
427                 {
428                         _INFO("[Monitor] Reader Removed");
429                         mTerminal->setReaderConnected(false);
430                         readerCount = 1;
431
432                         if (mTerminal->statusCallback != NULL)
433                                 mTerminal->statusCallback(mTerminal->getName(), NOTIFY_SE_NOT_AVAILABLE, SCARD_ERROR_OK, NULL);
434                 }
435
436                 _END();
437
438                 return readerCount;
439         }
440
441         void *USBTerminal::monitorEvents(void *data)
442         {
443                 LONG rv;
444                 DWORD readerCounts = 1;
445                 pthread_mutex_t eventMutex;
446
447                 SCARDCONTEXT hContext;
448                 USBTerminal *mTerminal = USBTerminal::getInstance();
449
450                 pthread_mutex_init(&eventMutex, NULL);
451
452                 _BEGIN();
453
454                 rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
455                 if (rv != SCARD_S_SUCCESS)
456                 {
457                         _ERR("[Monitor] SCardEstablishContext failed : %s", pcsc_stringify_error(rv));
458                         return NULL;
459                 }
460
461                 mTerminal->setMonitorEventsThreadContext(hContext);
462
463                 if (mTerminal->isReaderConnected())
464                         readerCounts = 2;
465
466                 while (mTerminal->isInitialized())
467                 {
468                         rv = SCardGetStatusChange(hContext, INFINITE, mTerminal->readerStates, readerCounts);
469                         if (rv != SCARD_S_SUCCESS)
470                         {
471                                 _INFO("[Monitor] SCardGetStatusChange error : %s", pcsc_stringify_error(rv));
472                                 break;
473                         }
474
475                         pthread_mutex_lock(&eventMutex);
476
477                         if (mTerminal->readerStates[0].dwEventState & SCARD_STATE_CHANGED)
478                         {
479                                 _INFO("[Monitor] reader state changed");
480                                 readerCounts = USBTerminal::resetReaderStates(hContext);
481                         }
482
483                         if (mTerminal->isReaderConnected())
484                         {
485                                 if ((mTerminal->readerStates[1].dwEventState & SCARD_STATE_EMPTY) == SCARD_STATE_EMPTY)
486                                 {
487                                         _INFO("[Monitor] Card Removed");
488                                         g_idle_add(&USBTerminal::cardDisconnect, &eventMutex);
489                                 }
490                                 else if ((mTerminal->readerStates[1].dwEventState & SCARD_STATE_PRESENT) == SCARD_STATE_PRESENT)
491                                 {
492                                         _INFO("[Monitor] Card Inserted");
493                                         g_idle_add(&USBTerminal::cardConnect, &eventMutex);
494                                 }
495
496                                 mTerminal->readerStates[1].dwCurrentState = mTerminal->readerStates[1].dwEventState;
497                         }
498
499                         pthread_mutex_unlock(&eventMutex);
500                 }
501
502                 rv = SCardReleaseContext(hContext);
503                 if (rv != SCARD_S_SUCCESS)
504                         _ERR("[Monitor] SCardReleaseContext failed : %s", pcsc_stringify_error(rv));
505
506                 _END();
507
508                 return NULL;
509         }
510 } /* namespace smartcard_service_api */