pcsc-lite 2.5.2
readerfactory.c
Go to the documentation of this file.
1/*
2 * MUSCLE SmartCard Development ( https://pcsclite.apdu.fr/ )
3 *
4 * Copyright (C) 1999-2004
5 * David Corcoran <corcoran@musclecard.com>
6 * Copyright (C) 2003-2004
7 * Damien Sauveron <damien.sauveron@labri.fr>
8 * Copyright (C) 2002-2024
9 * Ludovic Rousseau <ludovic.rousseau@free.fr>
10 * Copyright (C) 2009
11 * Jean-Luc Giraud <jlgiraud@googlemail.com>
12 *
13Redistribution and use in source and binary forms, with or without
14modification, are permitted provided that the following conditions
15are met:
16
171. Redistributions of source code must retain the above copyright
18 notice, this list of conditions and the following disclaimer.
192. Redistributions in binary form must reproduce the above copyright
20 notice, this list of conditions and the following disclaimer in the
21 documentation and/or other materials provided with the distribution.
223. The name of the author may not be used to endorse or promote products
23 derived from this software without specific prior written permission.
24
25THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 */
36
41
42#include "config.h"
43#include <stdio.h>
44#include <stdlib.h>
45#include <string.h>
46#include <unistd.h>
47#include <sys/types.h>
48#include <sys/stat.h>
49#include <errno.h>
50#include <fcntl.h>
51#include <pthread.h>
52#include <stdatomic.h>
53#include <stdbool.h>
54
55#include "misc.h"
56#include "pcscd.h"
57#include "debuglog.h"
58#include "readerfactory.h"
59#include "dyn_generic.h"
60#include "sys_generic.h"
61#include "eventhandler.h"
62#include "readers.h"
63#include "ifdwrapper.h"
64#include "hotplug.h"
65#include "configfile.h"
66#include "utils.h"
67
68#define INITIAL_MAX_READERS_CONTEXTS 2
69
70int pcsclite_max_reader_context = -1;
71READER_CONTEXT ** sReadersContexts;
72static int maxReaderHandles = PCSC_MAX_READER_HANDLES;
73#ifdef USE_SERIAL
74static char *ConfigFile = NULL;
75static int ConfigFileCRC = 0;
76#endif
77static pthread_mutex_t LockMutex = PTHREAD_MUTEX_INITIALIZER;
78int16_t ReaderEvents = 1;
79
80static LONG removeReader(READER_CONTEXT * sReader);
81
82static int RDR_CLIHANDLES_seeker(const void *el, const void *key)
83{
84 const RDR_CLIHANDLES *rdrCliHandles = el;
85
86 if ((el == NULL) || (key == NULL))
87 {
88 Log3(PCSC_LOG_CRITICAL,
89 "RDR_CLIHANDLES_seeker called with NULL pointer: el=%p, key=%p",
90 el, key);
91 return 0;
92 }
93
94 if (rdrCliHandles->hCard == *(SCARDHANDLE *)key)
95 return 1;
96
97 return 0;
98}
99
100
101LONG _RefReader(READER_CONTEXT * sReader)
102{
103 if (0 == sReader->reference)
105
106 sReader->reference += 1;
107
108 return SCARD_S_SUCCESS;
109}
110
111LONG _UnrefReader(READER_CONTEXT * sReader)
112{
113 if (0 == sReader->reference)
115
116 sReader->reference -= 1;
117
118 if (0 == sReader->reference)
119 removeReader(sReader);
120
121 return SCARD_S_SUCCESS;
122}
123
124LONG RFAllocateReaderSpace(unsigned int customMaxReaderHandles)
125{
126 int i; /* Counter */
127
128 if (customMaxReaderHandles != 0)
129 maxReaderHandles = customMaxReaderHandles;
130
131 pcsclite_max_reader_context = INITIAL_MAX_READERS_CONTEXTS;
132 sReadersContexts = calloc(pcsclite_max_reader_context, sizeof(sReadersContexts[0]));
133 if (NULL == sReadersContexts)
135
136 /* Allocate each reader structure */
137 for (i = 0; i < pcsclite_max_reader_context; i++)
138 {
139 sReadersContexts[i] = calloc(1, sizeof(READER_CONTEXT));
140 sReadersContexts[i]->vHandle = NULL;
141 atomic_init(&sReadersContexts[i]->hLockId, 0);
142 atomic_init(&sReadersContexts[i]->contexts, 0);
143 atomic_init(&sReadersContexts[i]->reference, 0);
144
145 /* Initialize the readerState struct */
146 sReadersContexts[i]->readerState.cardAtrLength = READER_NOT_INITIALIZED;
147 sReadersContexts[i]->readerState.cardProtocol = SCARD_PROTOCOL_UNDEFINED;
148 }
149
150 /* Create public event structures */
151 return EHInitializeEventStructures();
152}
153
154static LONG RFReAllocateReaderSpace(void)
155{
156 int new_size = pcsclite_max_reader_context + INITIAL_MAX_READERS_CONTEXTS;
157
158 Log3(PCSC_LOG_INFO, "from %d to %d", pcsclite_max_reader_context, new_size);
159
160 sReadersContexts = realloc(sReadersContexts, new_size * sizeof(sReadersContexts[0]));
161
162 /* Allocate each new reader structure */
163 for (int i = pcsclite_max_reader_context; i < new_size; i++)
164 {
165 sReadersContexts[i] = malloc(sizeof(READER_CONTEXT));
166 sReadersContexts[i]->vHandle = NULL;
167 atomic_init(&sReadersContexts[i]->hLockId, 0);
168 atomic_init(&sReadersContexts[i]->contexts, 0);
169 atomic_init(&sReadersContexts[i]->reference, 0);
170
171 /* Zero out each value in the struct */
172 memset(sReadersContexts[i]->readerState.readerName, 0, MAX_READERNAME);
173 memset(sReadersContexts[i]->readerState.cardAtr, 0, MAX_ATR_SIZE);
174 sReadersContexts[i]->readerState.eventCounter = 0;
175 sReadersContexts[i]->readerState.readerState = 0;
176 sReadersContexts[i]->readerState.readerSharing = 0;
177 sReadersContexts[i]->readerState.cardAtrLength = READER_NOT_INITIALIZED;
178 sReadersContexts[i]->readerState.cardProtocol = SCARD_PROTOCOL_UNDEFINED;
179 }
180
181 pcsclite_max_reader_context = new_size;
182
183 return SCARD_S_SUCCESS;
184}
185
186LONG RFAddReader(const char *readerNameLong, int port, const char *library,
187 const char *device)
188{
189 DWORD dwContext = 0, dwGetSize;
190 UCHAR ucGetData[1], ucThread[1];
191 LONG rv, parentNode;
192 int i, j;
193 int lrv = 0;
194 char *readerName = NULL;
195
196 if ((readerNameLong == NULL) || (library == NULL) || (device == NULL))
198
199#ifdef FILTER_NAMES
200 const char *ro_filter = SYS_GetEnv("PCSCLITE_FILTER_IGNORE_READER_NAMES");
201 if (ro_filter)
202 {
203 char *filter, *next;
204
205 /* get a RW copy of the env string */
206 filter = alloca(strlen(ro_filter)+1);
207 strcpy(filter, ro_filter);
208
209 while (filter)
210 {
211 /* ':' is the separator */
212 next = strchr(filter, ':');
213 if (next)
214 {
215 /* NUL terminate the current pattern */
216 *next = '\0';
217 }
218
219 /* if filter is non empty and found in the reader name */
220 if (*filter && strstr(readerNameLong, filter))
221 {
222 Log3(PCSC_LOG_ERROR,
223 "Reader name \"%s\" contains \"%s\": ignored",
224 readerNameLong, filter);
226 }
227
228 if (next)
229 /* next pattern */
230 filter = next+1;
231 else
232 /* end */
233 filter = NULL;
234 }
235 }
236#endif
237
238 /* allocate memory that is automatically freed */
239 readerName = alloca(strlen(readerNameLong)+1);
240 strcpy(readerName, readerNameLong);
241
242 /* Reader name too long? also count " 00 00"*/
243 if (strlen(readerName) > MAX_READERNAME - sizeof(" 00 00"))
244 {
245 Log3(PCSC_LOG_ERROR,
246 "Reader name too long: %zd chars instead of max %zd. Truncating!",
247 strlen(readerName), MAX_READERNAME - sizeof(" 00 00"));
248 readerName[MAX_READERNAME - sizeof(" 00 00")] = '\0';
249 }
250
251 /* Same name, same port, same device - duplicate reader cannot be used */
252 for (i = 0; i < pcsclite_max_reader_context; i++)
253 {
254 if (sReadersContexts[i]->vHandle != 0)
255 {
256 char lpcStripReader[MAX_READERNAME];
257 int tmplen;
258
259 /* get the reader name without the reader and slot numbers */
260 strncpy(lpcStripReader,
261 sReadersContexts[i]->readerState.readerName,
262 sizeof(lpcStripReader));
263 tmplen = strlen(lpcStripReader);
264 lpcStripReader[tmplen - 6] = 0;
265
266 if ((strcmp(readerName, lpcStripReader) == 0)
267 && (port == sReadersContexts[i]->port)
268 && (strcmp(device, sReadersContexts[i]->device) == 0))
269 {
270 Log1(PCSC_LOG_ERROR, "Duplicate reader found.");
272 }
273 }
274 }
275
276 /* We must find an empty slot to put the reader structure */
277 for (i = 0; i < pcsclite_max_reader_context; i++)
278 {
279 if (sReadersContexts[i]->vHandle == 0)
280 {
281 dwContext = i;
282 break;
283 }
284 }
285
286 if (i == pcsclite_max_reader_context)
287 {
288 /* No more spots left return */
289 RFReAllocateReaderSpace();
290 dwContext = i;
291 }
292
293 /* Check and set the readername to see if it must be enumerated */
294 parentNode = RFSetReaderName(sReadersContexts[dwContext], readerName,
295 library, port);
296 if (parentNode < -1)
297 return SCARD_E_NO_MEMORY;
298
299 sReadersContexts[dwContext]->library = strdup(library);
300 sReadersContexts[dwContext]->device = strdup(device);
301 sReadersContexts[dwContext]->version = 0;
302 sReadersContexts[dwContext]->port = port;
303 sReadersContexts[dwContext]->mMutex = NULL;
304 sReadersContexts[dwContext]->contexts = 0;
305 sReadersContexts[dwContext]->pthThread = 0;
306 sReadersContexts[dwContext]->hLockId = 0;
307 sReadersContexts[dwContext]->LockCount = 0;
308 sReadersContexts[dwContext]->vHandle = NULL;
309 sReadersContexts[dwContext]->pFeeds = NULL;
310 sReadersContexts[dwContext]->pMutex = NULL;
311 sReadersContexts[dwContext]->pthCardEvent = NULL;
312
313 lrv = list_init(&sReadersContexts[dwContext]->handlesList);
314 if (lrv < 0)
315 {
316 Log2(PCSC_LOG_CRITICAL, "list_init failed with return value: %d", lrv);
317 return SCARD_E_NO_MEMORY;
318 }
319
320 lrv = list_attributes_seeker(&sReadersContexts[dwContext]->handlesList,
321 RDR_CLIHANDLES_seeker);
322 if (lrv < 0)
323 {
324 Log2(PCSC_LOG_CRITICAL,
325 "list_attributes_seeker failed with return value: %d", lrv);
326 return SCARD_E_NO_MEMORY;
327 }
328
329 (void)pthread_mutex_init(&sReadersContexts[dwContext]->handlesList_lock,
330 NULL);
331
332 (void)pthread_mutex_init(&sReadersContexts[dwContext]->powerState_lock,
333 NULL);
334 sReadersContexts[dwContext]->powerState = POWER_STATE_UNPOWERED;
335
336 /* reference count */
337 sReadersContexts[dwContext]->reference = 1;
338
339 /* If a clone to this reader exists take some values from that clone */
340 if (parentNode >= 0 && parentNode < pcsclite_max_reader_context)
341 {
342 sReadersContexts[dwContext]->pFeeds =
343 sReadersContexts[parentNode]->pFeeds;
344 *(sReadersContexts[dwContext])->pFeeds += 1;
345 sReadersContexts[dwContext]->vHandle =
346 sReadersContexts[parentNode]->vHandle;
347 sReadersContexts[dwContext]->mMutex =
348 sReadersContexts[parentNode]->mMutex;
349 sReadersContexts[dwContext]->pMutex =
350 sReadersContexts[parentNode]->pMutex;
351
352 /* Call on the parent driver to see if it is thread safe */
353 dwGetSize = sizeof(ucThread);
354 rv = IFDGetCapabilities(sReadersContexts[parentNode],
355 TAG_IFD_THREAD_SAFE, &dwGetSize, ucThread);
356
357 if (rv == IFD_SUCCESS && dwGetSize == 1 && ucThread[0] == 1)
358 {
359 Log1(PCSC_LOG_INFO, "Driver is thread safe");
360 sReadersContexts[dwContext]->mMutex = NULL;
361 sReadersContexts[dwContext]->pMutex = NULL;
362 }
363 else
364 *(sReadersContexts[dwContext])->pMutex += 1;
365 }
366
367 if (sReadersContexts[dwContext]->pFeeds == NULL)
368 {
369 sReadersContexts[dwContext]->pFeeds = malloc(sizeof(int));
370
371 /* Initialize pFeeds to 1, otherwise multiple
372 cloned readers will cause pcscd to crash when
373 RFUnloadReader unloads the driver library
374 and there are still devices attached using it --mikeg*/
375 *(sReadersContexts[dwContext])->pFeeds = 1;
376 }
377
378 if (sReadersContexts[dwContext]->mMutex == 0)
379 {
380 sReadersContexts[dwContext]->mMutex =
381 malloc(sizeof(pthread_mutex_t));
382 (void)pthread_mutex_init(sReadersContexts[dwContext]->mMutex, NULL);
383 }
384
385 if (sReadersContexts[dwContext]->pMutex == NULL)
386 {
387 sReadersContexts[dwContext]->pMutex = malloc(sizeof(int));
388 *(sReadersContexts[dwContext])->pMutex = 1;
389 }
390
391 rv = RFInitializeReader(sReadersContexts[dwContext]);
392 if (rv != SCARD_S_SUCCESS)
393 {
394 int log_level = PCSC_LOG_ERROR;
395 if (SCARD_E_UNKNOWN_READER == rv)
396 log_level = PCSC_LOG_INFO;
397
398 /* Cannot connect to reader. Exit gracefully */
399 Log2(log_level, "%s init failed.", readerName);
400 (void)RFRemoveReader(readerName, port, REMOVE_READER_NO_FLAG);
401 return rv;
402 }
403
404 /* asynchronous card movement? */
405 {
406 RESPONSECODE (*fct)(DWORD, int) = NULL;
407
408 dwGetSize = sizeof(fct);
409
410 rv = IFDGetCapabilities(sReadersContexts[dwContext],
411 TAG_IFD_POLLING_THREAD_WITH_TIMEOUT, &dwGetSize, (PUCHAR)&fct);
412 if ((rv != SCARD_S_SUCCESS) || (dwGetSize != sizeof(fct)))
413 {
414 Log1(PCSC_LOG_INFO, "Using the pcscd polling thread");
415 }
416 else
417 {
418 sReadersContexts[dwContext]->pthCardEvent = fct;
419 Log1(PCSC_LOG_INFO, "Using the reader polling thread");
420 }
421
422 rv = EHSpawnEventHandler(sReadersContexts[dwContext]);
423 if (rv != SCARD_S_SUCCESS)
424 {
425 Log2(PCSC_LOG_ERROR, "%s init failed.", readerName);
426 (void)RFRemoveReader(readerName, port, REMOVE_READER_NO_FLAG);
427 return rv;
428 }
429 }
430
431 /* we have one more reader */
432 ReaderEvents++;
433 /* wrap? */
434 if (ReaderEvents < 0)
435 ReaderEvents = 1;
436
437 /* Call on the driver to see if there are multiple slots */
438 dwGetSize = sizeof(ucGetData);
439 rv = IFDGetCapabilities((sReadersContexts[dwContext]),
440 TAG_IFD_SLOTS_NUMBER, &dwGetSize, ucGetData);
441
442 int nbSlots = ucGetData[0];
443 if (rv != IFD_SUCCESS || dwGetSize != 1 || nbSlots == 0)
444 /* Reader does not have this defined. Must be a single slot
445 * reader so we can just return SCARD_S_SUCCESS. */
446 return SCARD_S_SUCCESS;
447
448 if (1 == nbSlots)
449 /* Reader has only one slot */
450 return SCARD_S_SUCCESS;
451
452 /*
453 * Check the number of slots and create a different
454 * structure for each one accordingly
455 */
456
457 /* Initialize the rest of the slots */
458 for (j = 1; j < nbSlots; j++)
459 {
460 char *tmpReader = NULL;
461 DWORD dwContextB = 0;
462 RESPONSECODE (*fct)(DWORD, int) = NULL;
463
464 /* We must find an empty spot to put the reader structure */
465 for (i = 0; i < pcsclite_max_reader_context; i++)
466 {
467 if (sReadersContexts[i]->vHandle == 0)
468 {
469 dwContextB = i;
470 break;
471 }
472 }
473
474 if (i == pcsclite_max_reader_context)
475 {
476 /* No more slot left */
477 RFReAllocateReaderSpace();
478 dwContextB = i;
479 }
480
481 /* Copy the previous reader name and increment the slot number */
482 tmpReader = sReadersContexts[dwContextB]->readerState.readerName;
483 memcpy(tmpReader,
484 sReadersContexts[dwContext]->readerState.readerName,
485 sizeof(sReadersContexts[dwContextB]->readerState.readerName));
486 snprintf(tmpReader + strlen(tmpReader) - 2, 3, "%02X", j);
487
488 sReadersContexts[dwContextB]->library =
489 sReadersContexts[dwContext]->library;
490 sReadersContexts[dwContextB]->device =
491 sReadersContexts[dwContext]->device;
492 sReadersContexts[dwContextB]->version =
493 sReadersContexts[dwContext]->version;
494 sReadersContexts[dwContextB]->port =
495 sReadersContexts[dwContext]->port;
496 sReadersContexts[dwContextB]->vHandle =
497 sReadersContexts[dwContext]->vHandle;
498 sReadersContexts[dwContextB]->mMutex =
499 sReadersContexts[dwContext]->mMutex;
500 sReadersContexts[dwContextB]->pMutex =
501 sReadersContexts[dwContext]->pMutex;
502 sReadersContexts[dwContextB]->slot =
503 sReadersContexts[dwContext]->slot + j;
504 sReadersContexts[dwContextB]->pthCardEvent = NULL;
505
506 /*
507 * Added by Dave - slots did not have a pFeeds
508 * parameter so it was by luck they were working
509 */
510 sReadersContexts[dwContextB]->pFeeds =
511 sReadersContexts[dwContext]->pFeeds;
512
513 /* Added by Dave for multiple slots */
514 *(sReadersContexts[dwContextB])->pFeeds += 1;
515
516 sReadersContexts[dwContextB]->contexts = 0;
517 sReadersContexts[dwContextB]->hLockId = 0;
518 sReadersContexts[dwContextB]->LockCount = 0;
519
520 lrv = list_init(&sReadersContexts[dwContextB]->handlesList);
521 if (lrv < 0)
522 {
523 Log2(PCSC_LOG_CRITICAL, "list_init failed with return value: %d", lrv);
524 return SCARD_E_NO_MEMORY;
525 }
526
527 lrv = list_attributes_seeker(&sReadersContexts[dwContextB]->handlesList,
528 RDR_CLIHANDLES_seeker);
529 if (lrv < 0)
530 {
531 Log2(PCSC_LOG_CRITICAL,
532 "list_attributes_seeker failed with return value: %d", lrv);
533 return SCARD_E_NO_MEMORY;
534 }
535
536 (void)pthread_mutex_init(&sReadersContexts[dwContextB]->handlesList_lock, NULL);
537 (void)pthread_mutex_init(&sReadersContexts[dwContextB]->powerState_lock,
538 NULL);
539 sReadersContexts[dwContextB]->powerState = POWER_STATE_UNPOWERED;
540
541 /* reference count */
542 sReadersContexts[dwContextB]->reference = 1;
543
544 /* Call on the parent driver to see if the slots are thread safe */
545 dwGetSize = sizeof(ucThread);
546 rv = IFDGetCapabilities((sReadersContexts[dwContext]),
547 TAG_IFD_SLOT_THREAD_SAFE, &dwGetSize, ucThread);
548
549 if (rv == IFD_SUCCESS && dwGetSize == 1 && ucThread[0] == 1)
550 {
551 Log1(PCSC_LOG_INFO, "Driver is slot thread safe");
552
553 sReadersContexts[dwContextB]->library =
554 strdup(sReadersContexts[dwContext]->library);
555 sReadersContexts[dwContextB]->device =
556 strdup(sReadersContexts[dwContext]->device);
557 sReadersContexts[dwContextB]->mMutex =
558 malloc(sizeof(pthread_mutex_t));
559 (void)pthread_mutex_init(sReadersContexts[dwContextB]->mMutex,
560 NULL);
561
562 sReadersContexts[dwContextB]->pMutex = malloc(sizeof(int));
563 *(sReadersContexts[dwContextB])->pMutex = 1;
564 }
565 else
566 *(sReadersContexts[dwContextB])->pMutex += 1;
567
568 rv = RFInitializeReader(sReadersContexts[dwContextB]);
569 if (rv != SCARD_S_SUCCESS)
570 {
571 /* Cannot connect to slot. Exit gracefully */
572 (void)RFRemoveReader(readerName, port, REMOVE_READER_NO_FLAG);
573 return rv;
574 }
575
576 /* asynchronous card movement? */
577 dwGetSize = sizeof(fct);
578
579 rv = IFDGetCapabilities((sReadersContexts[dwContextB]),
580 TAG_IFD_POLLING_THREAD_WITH_TIMEOUT, &dwGetSize, (PUCHAR)&fct);
581 if ((rv != SCARD_S_SUCCESS) || (dwGetSize != sizeof(fct)))
582 {
583 Log1(PCSC_LOG_INFO, "Using the pcscd polling thread");
584 }
585 else
586 {
587 sReadersContexts[dwContextB]->pthCardEvent = fct;
588 Log1(PCSC_LOG_INFO, "Using the reader polling thread");
589 }
590
591 rv = EHSpawnEventHandler(sReadersContexts[dwContextB]);
592 if (rv != SCARD_S_SUCCESS)
593 {
594 Log2(PCSC_LOG_ERROR, "%s init failed.", readerName);
595 (void)RFRemoveReader(readerName, port, REMOVE_READER_NO_FLAG);
596 return rv;
597 }
598 }
599
600 return SCARD_S_SUCCESS;
601}
602
603LONG RFRemoveReader(const char *readerName, int port, int flags)
604{
605 char lpcStripReader[MAX_READERNAME];
606 int i;
607#ifdef FILTER_NAMES
608 const char *extend;
609#endif
610 int extend_size = 0;
611
612 if (readerName == NULL)
614
615#ifdef FILTER_NAMES
616 extend = SYS_GetEnv("PCSCLITE_FILTER_EXTEND_READER_NAMES");
617 if (extend)
618 extend_size = strlen(extend);
619#endif
620
621 for (i = 0; i < pcsclite_max_reader_context; i++)
622 {
623 if (sReadersContexts[i] && (sReadersContexts[i]->vHandle != 0))
624 {
625 strncpy(lpcStripReader,
626 sReadersContexts[i]->readerState.readerName,
627 sizeof(lpcStripReader));
628 lpcStripReader[strlen(lpcStripReader) - 6 - extend_size] = 0;
629
630 /* Compare only the significant part of the reader name */
631 if ((strncmp(readerName, lpcStripReader, MAX_READERNAME - sizeof(" 00 00")) == 0)
632 && (port == sReadersContexts[i]->port))
633 {
634 if (flags & REMOVE_READER_FLAG_REMOVED)
635 {
636 UCHAR tagValue[1];
637 DWORD valueLength;
638 LONG ret;
639
640 /* signal to the driver that the reader has been removed */
641 valueLength = sizeof(tagValue);
642 ret = IFDGetCapabilities(sReadersContexts[i],
643 TAG_IFD_DEVICE_REMOVED, &valueLength, tagValue);
644 if ((IFD_SUCCESS) == ret && (1 == tagValue[0]))
645 {
646 tagValue[0] = 1;
647 IFDSetCapabilities(sReadersContexts[i],
648 TAG_IFD_DEVICE_REMOVED, sizeof tagValue, tagValue);
649 }
650 }
651
652 /* remove the reader */
653 UNREF_READER(sReadersContexts[i])
654 }
655 }
656 }
657
658 /* we have one less reader */
659 ReaderEvents++;
660 /* wrap? */
661 if (ReaderEvents < 0)
662 ReaderEvents = 1;
663
664 return SCARD_S_SUCCESS;
665}
666
667LONG removeReader(READER_CONTEXT * sContext)
668{
669 /* Try to destroy the thread */
670 if (sContext -> pthThread)
671 EHDestroyEventHandler(sContext);
672
673 if ((NULL == sContext->pMutex) || (NULL == sContext->pFeeds))
674 {
675 Log1(PCSC_LOG_ERROR,
676 "Trying to remove an already removed driver");
678 }
679
680 RFUnInitializeReader(sContext);
681
682 *sContext->pMutex -= 1;
683
684 /* free shared resources when the last slot is closed */
685 if (0 == *sContext->pMutex)
686 {
687 (void)pthread_mutex_destroy(sContext->mMutex);
688 free(sContext->mMutex);
689 sContext->mMutex = NULL;
690 free(sContext->library);
691 free(sContext->device);
692 free(sContext->pMutex);
693 sContext->pMutex = NULL;
694 }
695
696 *sContext->pFeeds -= 1;
697
698 /* Added by Dave to free the pFeeds variable */
699 if (*sContext->pFeeds == 0)
700 {
701 free(sContext->pFeeds);
702 sContext->pFeeds = NULL;
703 }
704
705 (void)pthread_mutex_destroy(&sContext->powerState_lock);
706 sContext->version = 0;
707 sContext->port = 0;
708 sContext->contexts = 0;
709 sContext->slot = 0;
710 sContext->hLockId = 0;
711 sContext->LockCount = 0;
712 sContext->vHandle = NULL;
713
714 (void)pthread_mutex_lock(&sContext->handlesList_lock);
715 while (list_size(&sContext->handlesList) != 0)
716 {
717 int lrv;
718 RDR_CLIHANDLES *currentHandle;
719
720 currentHandle = list_get_at(&sContext->handlesList, 0);
721 lrv = list_delete_at(&sContext->handlesList, 0);
722 if (lrv < 0)
723 Log2(PCSC_LOG_CRITICAL,
724 "list_delete_at failed with return value: %d", lrv);
725
726 free(currentHandle);
727 }
728 (void)pthread_mutex_unlock(&sContext->handlesList_lock);
729 (void)pthread_mutex_destroy(&sContext->handlesList_lock);
730 list_destroy(&sContext->handlesList);
731
732 /* signal an event to clients */
734
735 return SCARD_S_SUCCESS;
736}
737
738LONG RFSetReaderName(READER_CONTEXT * rContext, const char *readerName,
739 const char *libraryName, int port)
740{
741 LONG parent = -1; /* reader number of the parent of the clone */
742 DWORD valueLength;
743 int currentDigit = -1;
744 int supportedChannels = 0;
745 bool usedDigits[pcsclite_max_reader_context];
746 int i;
747 const char *extend = NULL;
748
749 /* Clear the list */
750 for (i = 0; i < pcsclite_max_reader_context; i++)
751 usedDigits[i] = false;
752
753 for (i = 0; i < pcsclite_max_reader_context; i++)
754 {
755 if (sReadersContexts[i]->vHandle != 0)
756 {
757 if (strcmp(sReadersContexts[i]->library, libraryName) == 0)
758 {
759 UCHAR tagValue[1];
760 LONG ret;
761
762 /* Ask the driver if it supports multiple channels */
763 valueLength = sizeof(tagValue);
764 ret = IFDGetCapabilities(sReadersContexts[i],
766 &valueLength, tagValue);
767
768 if ((ret == IFD_SUCCESS) && (valueLength == 1) &&
769 (tagValue[0] > 1))
770 {
771 supportedChannels = tagValue[0];
772 Log2(PCSC_LOG_INFO,
773 "Support %d simultaneous readers", tagValue[0]);
774 }
775 else
776 supportedChannels = 1;
777
778 /* Check to see if it is a hotplug reader and different */
779 if ((((sReadersContexts[i]->port & 0xFFFF0000) ==
780 PCSCLITE_HP_BASE_PORT)
781 && (sReadersContexts[i]->port != port))
782 || (supportedChannels > 1))
783 {
784 const char *reader = sReadersContexts[i]->readerState.readerName;
785
786 /*
787 * tells the caller who the parent of this
788 * clone is so it can use its shared
789 * resources like mutex/etc.
790 */
791 parent = i;
792
793 /*
794 * If the same reader already exists and it is
795 * hotplug then we must look for others and
796 * enumerate the readername
797 */
798 currentDigit = strtol(reader + strlen(reader) - 5, NULL, 16);
799
800 /* This spot is taken */
801 usedDigits[currentDigit] = true;
802 }
803 }
804 }
805 }
806
807 /* default value */
808 i = 0;
809
810 /* Other identical readers exist on the same bus */
811 if (currentDigit != -1)
812 {
813 for (i = 0; i < pcsclite_max_reader_context; i++)
814 {
815 /* get the first free digit */
816 if (usedDigits[i] == false)
817 break;
818 }
819
820 if (i == pcsclite_max_reader_context)
821 {
822 Log2(PCSC_LOG_ERROR, "Max number of readers reached: %d", pcsclite_max_reader_context);
823 return -2;
824 }
825
826 if (i >= supportedChannels)
827 {
828 Log3(PCSC_LOG_ERROR, "Driver %s does not support more than "
829 "%d reader(s). Maybe the driver should support "
830 "TAG_IFD_SIMULTANEOUS_ACCESS", libraryName, supportedChannels);
831 return -2;
832 }
833 }
834
835#ifdef FILTER_NAMES
836 extend = SYS_GetEnv("PCSCLITE_FILTER_EXTEND_READER_NAMES");
837 if (NULL == extend)
838 extend = "";
839#else
840 extend = "";
841#endif
842
843 snprintf(rContext->readerState.readerName,
844 sizeof(rContext->readerState.readerName), "%s%s %02X 00",
845 readerName, extend, i);
846
847 /* Set the slot in 0xDDDDCCCC */
848 rContext->slot = i << 16;
849
850 return parent;
851}
852
853LONG RFReaderInfo(const char *readerName, READER_CONTEXT ** sReader)
854{
855 int i;
856
857 if (readerName == NULL)
859
860 for (i = 0; i < pcsclite_max_reader_context; i++)
861 {
862 if (sReadersContexts[i]->vHandle != 0)
863 {
864 if (strcmp(readerName,
865 sReadersContexts[i]->readerState.readerName) == 0)
866 {
867 /* Increase reference count */
868 REF_READER(sReadersContexts[i])
869
870 *sReader = sReadersContexts[i];
871 return SCARD_S_SUCCESS;
872 }
873 }
874 }
875
877}
878
879LONG RFReaderInfoById(SCARDHANDLE hCard, READER_CONTEXT * * sReader)
880{
881 int i;
882
883 for (i = 0; i < pcsclite_max_reader_context; i++)
884 {
885 if (sReadersContexts[i]->vHandle != 0)
886 {
887 RDR_CLIHANDLES * currentHandle;
888 (void)pthread_mutex_lock(&sReadersContexts[i]->handlesList_lock);
889 currentHandle = list_seek(&sReadersContexts[i]->handlesList,
890 &hCard);
891 (void)pthread_mutex_unlock(&sReadersContexts[i]->handlesList_lock);
892 if (currentHandle != NULL)
893 {
894 /* Increase reference count */
895 REF_READER(sReadersContexts[i])
896
897 *sReader = sReadersContexts[i];
898 return SCARD_S_SUCCESS;
899 }
900 }
901 }
902
904}
905
906LONG RFLoadReader(READER_CONTEXT * rContext)
907{
908 LONG ret = SCARD_S_SUCCESS;
909 if (rContext->vHandle != 0)
910 {
911 Log2(PCSC_LOG_INFO, "Reusing already loaded driver for %s",
912 rContext->library);
913 /* Another reader exists with this library loaded */
914 return SCARD_S_SUCCESS;
915 }
916
917 rContext->vHandle = DYN_LoadLibrary(rContext->library);
918 if (NULL == rContext->vHandle)
920 return ret;
921}
922
923LONG RFBindFunctions(READER_CONTEXT * rContext)
924{
925 int rv;
926 void *f;
927
928 rv = DYN_GetAddress(rContext->vHandle, &f, "IFDHCreateChannelByName", true);
929 if (SCARD_S_SUCCESS == rv)
930 {
931 /* Ifd Handler 3.0 found */
932 rContext->version = IFD_HVERSION_3_0;
933 }
934 else
935 {
936 rv = DYN_GetAddress(rContext->vHandle, &f, "IFDHCreateChannel", false);
937 if (SCARD_S_SUCCESS == rv)
938 {
939 /* Ifd Handler 2.0 found */
940 rContext->version = IFD_HVERSION_2_0;
941 }
942 else
943 {
944 /* Neither version of the IFD Handler was found - exit */
945 Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing");
947 }
948 }
949
950 if (rContext->version == IFD_HVERSION_2_0)
951 {
952 /* The following binds version 2.0 of the IFD Handler specs */
953#define GET_ADDRESS_OPTIONALv2(s, code) \
954{ \
955 void *f1 = NULL; \
956 int rvl = DYN_GetAddress(rContext->vHandle, &f1, "IFDH" #s, false); \
957 if (SCARD_S_SUCCESS != rvl) \
958 { \
959 code \
960 } \
961 rContext->psFunctions.psFunctions_v2.pvf ## s = f1; \
962}
963
964#define GET_ADDRESSv2(s) \
965 GET_ADDRESS_OPTIONALv2(s, \
966 Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing: " #s ); \
967 return(rv); )
968
969 Log1(PCSC_LOG_INFO, "Loading IFD Handler 2.0");
970
971 GET_ADDRESSv2(CreateChannel)
972 GET_ADDRESSv2(CloseChannel)
973 GET_ADDRESSv2(GetCapabilities)
974 GET_ADDRESSv2(SetCapabilities)
975 GET_ADDRESSv2(PowerICC)
976 GET_ADDRESSv2(TransmitToICC)
977 GET_ADDRESSv2(ICCPresence)
978 GET_ADDRESS_OPTIONALv2(SetProtocolParameters, )
979
980 GET_ADDRESSv2(Control)
981 }
982 else if (rContext->version == IFD_HVERSION_3_0)
983 {
984 /* The following binds version 3.0 of the IFD Handler specs */
985#define GET_ADDRESS_OPTIONALv3(s, code) \
986{ \
987 void *f1 = NULL; \
988 int rvl = DYN_GetAddress(rContext->vHandle, &f1, "IFDH" #s, false); \
989 if (SCARD_S_SUCCESS != rvl) \
990 { \
991 code \
992 } \
993 rContext->psFunctions.psFunctions_v3.pvf ## s = f1; \
994}
995
996#define GET_ADDRESSv3(s) \
997 GET_ADDRESS_OPTIONALv3(s, \
998 Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing: " #s ); \
999 return(rv); )
1000
1001 Log1(PCSC_LOG_INFO, "Loading IFD Handler 3.0");
1002
1003 GET_ADDRESSv2(CreateChannel)
1004 GET_ADDRESSv2(CloseChannel)
1005 GET_ADDRESSv2(GetCapabilities)
1006 GET_ADDRESSv2(SetCapabilities)
1007 GET_ADDRESSv2(PowerICC)
1008 GET_ADDRESSv2(TransmitToICC)
1009 GET_ADDRESSv2(ICCPresence)
1010 GET_ADDRESS_OPTIONALv2(SetProtocolParameters, )
1011
1012 GET_ADDRESSv3(CreateChannelByName)
1013 GET_ADDRESSv3(Control)
1014 }
1015 else
1016 {
1017 /* Who knows what could have happened for it to get here. */
1018 Log1(PCSC_LOG_CRITICAL, "IFD Handler not 1.0/2.0 or 3.0");
1019 return SCARD_F_UNKNOWN_ERROR;
1020 }
1021
1022 return SCARD_S_SUCCESS;
1023}
1024
1025LONG RFUnBindFunctions(READER_CONTEXT * rContext)
1026{
1027 /* Zero out everything */
1028 memset(&rContext->psFunctions, 0, sizeof(rContext->psFunctions));
1029
1030 return SCARD_S_SUCCESS;
1031}
1032
1033LONG RFUnloadReader(READER_CONTEXT * rContext)
1034{
1035 /* Make sure no one else is using this library */
1036 if (*rContext->pFeeds == 1)
1037 {
1038 Log1(PCSC_LOG_INFO, "Unloading reader driver.");
1039 (void)DYN_CloseLibrary(rContext->vHandle);
1040 rContext->vHandle = NULL;
1041 }
1042
1043 rContext->vHandle = NULL;
1044
1045 return SCARD_S_SUCCESS;
1046}
1047
1048LONG RFCheckSharing(SCARDHANDLE hCard, READER_CONTEXT * rContext)
1049{
1050 if (rContext->hLockId == 0 || rContext->hLockId == hCard)
1051 return SCARD_S_SUCCESS;
1052 else
1054}
1055
1056LONG RFLockSharing(SCARDHANDLE hCard, READER_CONTEXT * rContext)
1057{
1058 LONG rv;
1059
1060 (void)pthread_mutex_lock(&LockMutex);
1061 rv = RFCheckSharing(hCard, rContext);
1062 if (SCARD_S_SUCCESS == rv)
1063 {
1064 rContext->LockCount += 1;
1065 rContext->hLockId = hCard;
1066 }
1067 (void)pthread_mutex_unlock(&LockMutex);
1068
1069 return rv;
1070}
1071
1072LONG RFUnlockSharing(SCARDHANDLE hCard, READER_CONTEXT * rContext)
1073{
1074 LONG rv;
1075
1076 (void)pthread_mutex_lock(&LockMutex);
1077 rv = RFCheckSharing(hCard, rContext);
1078 if (SCARD_S_SUCCESS == rv)
1079 {
1081 {
1082 if (rContext->LockCount > 1)
1083 rContext->LockCount -= 1;
1084 else
1086 }
1087 else
1088 {
1089 if (rContext->LockCount > 0)
1090 {
1091 rContext->LockCount -= 1;
1092 if (0 == rContext->LockCount)
1093 rContext->hLockId = 0;
1094 }
1095 else
1096 /* rContext->LockCount == 0 */
1098 }
1099 }
1100 (void)pthread_mutex_unlock(&LockMutex);
1101
1102 return rv;
1103}
1104
1105LONG RFUnlockAllSharing(SCARDHANDLE hCard, READER_CONTEXT * rContext)
1106{
1107 LONG rv;
1108
1109 (void)pthread_mutex_lock(&LockMutex);
1110 rv = RFCheckSharing(hCard, rContext);
1111 if (SCARD_S_SUCCESS == rv)
1112 {
1113 rContext->LockCount = 0;
1114 rContext->hLockId = 0;
1115 }
1116 (void)pthread_mutex_unlock(&LockMutex);
1117
1118 return rv;
1119}
1120
1121LONG RFInitializeReader(READER_CONTEXT * rContext)
1122{
1123 LONG rv = SCARD_S_SUCCESS;
1124 RESPONSECODE rvd;
1125
1126 /* Spawn the event handler thread */
1127 Log4(PCSC_LOG_INFO, "Attempting startup of %s using %s on port 0x%X",
1128 rContext->readerState.readerName, rContext->library, rContext->port);
1129
1130#ifndef PCSCLITE_STATIC_DRIVER
1131 /* loads the library */
1132 rv = RFLoadReader(rContext);
1133 if (rv != SCARD_S_SUCCESS)
1134 {
1135 Log2(PCSC_LOG_ERROR, "RFLoadReader failed: 0x%lX", rv);
1136 return rv;
1137 }
1138
1139 /* binds the functions */
1140 rv = RFBindFunctions(rContext);
1141
1142 if (rv != SCARD_S_SUCCESS)
1143 {
1144 Log2(PCSC_LOG_ERROR, "RFBindFunctions failed: 0x%lX", rv);
1145 (void)RFUnloadReader(rContext);
1146 return rv;
1147 }
1148#else
1149 /* define a fake vHandle. Can be any value except NULL */
1150 rContext->vHandle = RFInitializeReader;
1151#endif
1152
1153 /* tries to open the port */
1154 rvd = IFDOpenIFD(rContext);
1155
1156 if (rvd != IFD_SUCCESS)
1157 {
1158 int log_level = PCSC_LOG_CRITICAL;
1160
1161 if (IFD_NO_SUCH_DEVICE == rvd)
1162 {
1163 /* wrong interface on a composite device? */
1164 log_level = PCSC_LOG_INFO;
1166 }
1167
1168 Log3(log_level, "Open Port 0x%X Failed (%s)",
1169 rContext->port, rContext->device);
1170
1171 /* IFDOpenIFD() failed */
1172 /* the reader was not started correctly */
1173 rContext->slot = -1;
1174 }
1175
1176 return rv;
1177}
1178
1179void RFUnInitializeReader(READER_CONTEXT * rContext)
1180{
1181 Log2(PCSC_LOG_INFO, "Attempting shutdown of %s.",
1182 rContext->readerState.readerName);
1183
1184 /* Do not close a reader if IFDOpenIFD() failed in RFInitializeReader() */
1185 if (rContext->slot != -1)
1186 (void)IFDCloseIFD(rContext);
1187
1188 (void)RFUnBindFunctions(rContext);
1189 (void)RFUnloadReader(rContext);
1190
1191 /*
1192 * Zero out the public status struct to allow it to be recycled and
1193 * used again
1194 */
1195 memset(rContext->readerState.readerName, 0,
1196 sizeof(rContext->readerState.readerName));
1197 memset(rContext->readerState.cardAtr, 0,
1198 sizeof(rContext->readerState.cardAtr));
1199 rContext->readerState.readerState = 0;
1200 rContext->readerState.eventCounter = 0;
1201 rContext->readerState.readerSharing = 0;
1204
1205 return;
1206}
1207
1208SCARDHANDLE RFCreateReaderHandle(READER_CONTEXT * rContext)
1209{
1210 SCARDHANDLE randHandle;
1211 LONG ret;
1212
1213 (void)rContext;
1214
1215 do
1216 {
1217 READER_CONTEXT *dummy_reader;
1218
1219 /* Create a random handle with 32 bits check to see if it already is
1220 * used. */
1221 /* FIXME: THIS IS NOT STRONG ENOUGH: A 128-bit token should be
1222 * generated. The client and server would associate token and hCard
1223 * for authentication. */
1224 randHandle = SYS_RandomInt();
1225
1226 /* do we already use this hCard somewhere? */
1227 ret = RFReaderInfoById(randHandle, &dummy_reader);
1228 if (SCARD_S_SUCCESS == ret)
1229 UNREF_READER(dummy_reader)
1230 }
1231 while (SCARD_S_SUCCESS == ret);
1232
1233 /* Once the for loop is completed w/o restart a good handle was
1234 * found and the loop can be exited. */
1235 return randHandle;
1236}
1237
1238LONG RFAddReaderHandle(READER_CONTEXT * rContext, SCARDHANDLE hCard)
1239{
1240 int listLength, lrv;
1241 RDR_CLIHANDLES *newHandle;
1242 LONG rv = SCARD_S_SUCCESS;
1243
1244 (void)pthread_mutex_lock(&rContext->handlesList_lock);
1245 listLength = list_size(&rContext->handlesList);
1246
1247 /* Throttle the number of possible handles */
1248 if (listLength >= maxReaderHandles)
1249 {
1250 Log2(PCSC_LOG_CRITICAL,
1251 "Too many handles opened, exceeding configured max (%d)",
1252 maxReaderHandles);
1253 rv = SCARD_E_NO_MEMORY;
1254 goto end;
1255 }
1256
1257 newHandle = malloc(sizeof(RDR_CLIHANDLES));
1258 if (NULL == newHandle)
1259 {
1260 Log1(PCSC_LOG_CRITICAL, "malloc failed");
1261 rv = SCARD_E_NO_MEMORY;
1262 goto end;
1263 }
1264
1265 newHandle->hCard = hCard;
1266 atomic_init(&newHandle->dwEventStatus, 0);
1267
1268 lrv = list_append(&rContext->handlesList, newHandle);
1269 if (lrv < 0)
1270 {
1271 free(newHandle);
1272 Log2(PCSC_LOG_CRITICAL, "list_append failed with return value: %d",
1273 lrv);
1274 rv = SCARD_E_NO_MEMORY;
1275 }
1276end:
1277 (void)pthread_mutex_unlock(&rContext->handlesList_lock);
1278 return rv;
1279}
1280
1281LONG RFRemoveReaderHandle(READER_CONTEXT * rContext, SCARDHANDLE hCard)
1282{
1283 RDR_CLIHANDLES *currentHandle;
1284 int lrv;
1285 LONG rv = SCARD_S_SUCCESS;
1286
1287 (void)pthread_mutex_lock(&rContext->handlesList_lock);
1288 currentHandle = list_seek(&rContext->handlesList, &hCard);
1289 if (NULL == currentHandle)
1290 {
1291 Log2(PCSC_LOG_CRITICAL, "list_seek failed to locate hCard=%lX", hCard);
1293 goto end;
1294 }
1295
1296 lrv = list_delete(&rContext->handlesList, currentHandle);
1297 if (lrv < 0)
1298 Log2(PCSC_LOG_CRITICAL,
1299 "list_delete failed with return value: %d", lrv);
1300
1301 free(currentHandle);
1302
1303end:
1304 (void)pthread_mutex_unlock(&rContext->handlesList_lock);
1305
1306 /* Not Found */
1307 return rv;
1308}
1309
1310void RFSetReaderEventState(READER_CONTEXT * rContext, DWORD dwEvent)
1311{
1312 /* Set all the handles for that reader to the event */
1313 int list_index, listSize;
1314 RDR_CLIHANDLES *currentHandle;
1315
1316 (void)pthread_mutex_lock(&rContext->handlesList_lock);
1317 listSize = list_size(&rContext->handlesList);
1318
1319 for (list_index = 0; list_index < listSize; list_index++)
1320 {
1321 currentHandle = list_get_at(&rContext->handlesList, list_index);
1322 if (NULL == currentHandle)
1323 {
1324 Log2(PCSC_LOG_CRITICAL, "list_get_at failed at index %d",
1325 list_index);
1326 continue;
1327 }
1328
1329 currentHandle->dwEventStatus = dwEvent;
1330 }
1331 (void)pthread_mutex_unlock(&rContext->handlesList_lock);
1332
1333 if (SCARD_REMOVED == dwEvent)
1334 {
1335 /* unlock the card */
1336 rContext->hLockId = 0;
1337 rContext->LockCount = 0;
1338 }
1339
1340 return;
1341}
1342
1343LONG RFCheckReaderEventState(READER_CONTEXT * rContext, SCARDHANDLE hCard)
1344{
1345 LONG rv;
1346 RDR_CLIHANDLES *currentHandle;
1347 DWORD dwEventStatus;
1348
1349 (void)pthread_mutex_lock(&rContext->handlesList_lock);
1350 currentHandle = list_seek(&rContext->handlesList, &hCard);
1351 (void)pthread_mutex_unlock(&rContext->handlesList_lock);
1352 if (NULL == currentHandle)
1353 {
1354 /* Not Found */
1355 Log2(PCSC_LOG_CRITICAL, "list_seek failed for hCard 0x%lX", hCard);
1357 }
1358
1359 dwEventStatus = currentHandle->dwEventStatus;
1360 switch(dwEventStatus)
1361 {
1362 case 0:
1363 rv = SCARD_S_SUCCESS;
1364 break;
1365
1366 case SCARD_REMOVED:
1368 break;
1369
1370 case SCARD_RESET:
1371 rv = SCARD_W_RESET_CARD;
1372 break;
1373
1374 default:
1376 }
1377
1378 return rv;
1379}
1380
1381LONG RFClearReaderEventState(READER_CONTEXT * rContext, SCARDHANDLE hCard)
1382{
1383 RDR_CLIHANDLES *currentHandle;
1384
1385 (void)pthread_mutex_lock(&rContext->handlesList_lock);
1386 currentHandle = list_seek(&rContext->handlesList, &hCard);
1387 (void)pthread_mutex_unlock(&rContext->handlesList_lock);
1388 if (NULL == currentHandle)
1389 /* Not Found */
1391
1392 currentHandle->dwEventStatus = 0;
1393
1394 /* hCards should be unique so we
1395 * should be able to return
1396 * as soon as we have a hit */
1397 return SCARD_S_SUCCESS;
1398}
1399
1400LONG RFCheckReaderStatus(READER_CONTEXT * rContext)
1401{
1402 if (rContext->readerState.readerState & SCARD_UNKNOWN)
1404 else
1405 return SCARD_S_SUCCESS;
1406}
1407
1408void RFCleanupReaders(void)
1409{
1410 int i;
1411
1412 Log1(PCSC_LOG_INFO, "entering cleaning function");
1413 for (i = 0; i < pcsclite_max_reader_context; i++)
1414 {
1415 if (sReadersContexts[i]->vHandle != 0)
1416 {
1417 LONG rv;
1418 char lpcStripReader[MAX_READERNAME];
1419
1420 Log2(PCSC_LOG_INFO, "Stopping reader: %s",
1421 sReadersContexts[i]->readerState.readerName);
1422
1423 strncpy(lpcStripReader,
1424 sReadersContexts[i]->readerState.readerName,
1425 sizeof(lpcStripReader));
1426 /* strip the 6 last char ' 00 00' */
1427 lpcStripReader[strlen(lpcStripReader) - 6] = '\0';
1428
1429 rv = RFRemoveReader(lpcStripReader, sReadersContexts[i]->port,
1430 REMOVE_READER_NO_FLAG);
1431
1432 if (rv != SCARD_S_SUCCESS)
1433 Log2(PCSC_LOG_ERROR, "RFRemoveReader error: %s", rv2text(rv));
1434 }
1435
1436 free(sReadersContexts[i]);
1437 sReadersContexts[i] = NULL;
1438 }
1439
1440#ifdef USE_SERIAL
1441 if (ConfigFile)
1442 {
1443 free(ConfigFile);
1444 ConfigFile = NULL;
1445 }
1446#endif
1447}
1448
1453#ifdef USE_USB
1454void RFWaitForReaderInit(void)
1455{
1456 bool need_to_wait;
1457
1458 do
1459 {
1460 need_to_wait = false;
1461 for (int i = 0; i < pcsclite_max_reader_context; i++)
1462 {
1463 /* reader is present */
1464 if (sReadersContexts[i] && sReadersContexts[i]->vHandle != NULL)
1465 {
1466 /* but card state is not yet available */
1468 == sReadersContexts[i]->readerState.cardAtrLength)
1469 {
1470 Log2(PCSC_LOG_DEBUG, "Waiting init for reader: %s",
1471 sReadersContexts[i]->readerState.readerName);
1472 need_to_wait = true;
1473 }
1474 }
1475 }
1476
1477 if (need_to_wait)
1478 SYS_USleep(10*1000); /* 10 ms */
1479 } while (need_to_wait);
1480}
1481#endif
1482
1483#ifdef USE_SERIAL
1484int RFStartSerialReaders(const char *readerconf)
1485{
1486 SerialReader *reader_list = NULL;
1487 int i, rv;
1488
1489 /* remember the configuration filename for RFReCheckReaderConf() */
1490 ConfigFile = strdup(readerconf);
1491
1492 rv = DBGetReaderListDir(readerconf, &reader_list);
1493
1494 /* the list is empty */
1495 if (NULL == reader_list)
1496 return rv;
1497
1498 for (i=0; reader_list[i].pcFriendlyname; i++)
1499 {
1500 int j;
1501
1502 (void)RFAddReader(reader_list[i].pcFriendlyname,
1503 reader_list[i].channelId,
1504 reader_list[i].pcLibpath, reader_list[i].pcDevicename);
1505
1506 /* update the ConfigFileCRC (this false "CRC" is very weak) */
1507 for (j=0; j<reader_list[i].pcFriendlyname[j]; j++)
1508 ConfigFileCRC += reader_list[i].pcFriendlyname[j];
1509 for (j=0; j<reader_list[i].pcLibpath[j]; j++)
1510 ConfigFileCRC += reader_list[i].pcLibpath[j];
1511 for (j=0; j<reader_list[i].pcDevicename[j]; j++)
1512 ConfigFileCRC += reader_list[i].pcDevicename[j];
1513
1514 /* free strings allocated by DBGetReaderListDir() */
1515 free(reader_list[i].pcFriendlyname);
1516 free(reader_list[i].pcLibpath);
1517 free(reader_list[i].pcDevicename);
1518 }
1519 free(reader_list);
1520
1521 return rv;
1522}
1523
1524void RFReCheckReaderConf(void)
1525{
1526 SerialReader *reader_list = NULL;
1527 int i, crc;
1528
1529 (void)DBGetReaderListDir(ConfigFile, &reader_list);
1530
1531 /* the list is empty */
1532 if (NULL == reader_list)
1533 return;
1534
1535 crc = 0;
1536 for (i=0; reader_list[i].pcFriendlyname; i++)
1537 {
1538 int j;
1539
1540 /* calculate a local crc */
1541 for (j=0; j<reader_list[i].pcFriendlyname[j]; j++)
1542 crc += reader_list[i].pcFriendlyname[j];
1543 for (j=0; j<reader_list[i].pcLibpath[j]; j++)
1544 crc += reader_list[i].pcLibpath[j];
1545 for (j=0; j<reader_list[i].pcDevicename[j]; j++)
1546 crc += reader_list[i].pcDevicename[j];
1547 }
1548
1549 /* cancel if the configuration file has been modified */
1550 if (crc != ConfigFileCRC)
1551 {
1552 Log2(PCSC_LOG_CRITICAL,
1553 "configuration file: %s has been modified. Recheck canceled",
1554 ConfigFile);
1555 return;
1556 }
1557
1558 for (i=0; reader_list[i].pcFriendlyname; i++)
1559 {
1560 int r;
1561 char present = false;
1562
1563 Log2(PCSC_LOG_DEBUG, "refresh reader: %s",
1564 reader_list[i].pcFriendlyname);
1565
1566 /* is the reader already present? */
1567 for (r = 0; r < pcsclite_max_reader_context; r++)
1568 {
1569 if (sReadersContexts[r]->vHandle != 0)
1570 {
1571 char lpcStripReader[MAX_READERNAME];
1572 int tmplen;
1573
1574 /* get the reader name without the reader and slot numbers */
1575 strncpy(lpcStripReader,
1576 sReadersContexts[r]->readerState.readerName,
1577 sizeof(lpcStripReader));
1578 tmplen = strlen(lpcStripReader);
1579 lpcStripReader[tmplen - 6] = 0;
1580
1581 if ((strcmp(reader_list[i].pcFriendlyname, lpcStripReader) == 0)
1582 && (reader_list[i].channelId == sReadersContexts[r]->port))
1583 {
1584 DWORD dwStatus = 0;
1585
1586 /* the reader was already started */
1587 present = true;
1588
1589 /* verify the reader is still connected */
1590 if (IFDStatusICC(sReadersContexts[r], &dwStatus, false)
1591 != SCARD_S_SUCCESS)
1592 {
1593 Log2(PCSC_LOG_INFO, "Reader %s disappeared",
1594 reader_list[i].pcFriendlyname);
1595 (void)RFRemoveReader(reader_list[i].pcFriendlyname,
1596 reader_list[i].channelId, REMOVE_READER_NO_FLAG);
1597 }
1598 }
1599 }
1600 }
1601
1602 /* the reader was not present */
1603 if (!present)
1604 /* we try to add it */
1605 (void)RFAddReader(reader_list[i].pcFriendlyname,
1606 reader_list[i].channelId, reader_list[i].pcLibpath,
1607 reader_list[i].pcDevicename);
1608
1609 /* free strings allocated by DBGetReaderListDir() */
1610 free(reader_list[i].pcFriendlyname);
1611 free(reader_list[i].pcLibpath);
1612 free(reader_list[i].pcDevicename);
1613 }
1614 free(reader_list);
1615}
1616#endif
1617
1618int RFGetPowerState(READER_CONTEXT * rContext)
1619{
1620 (void)pthread_mutex_lock(&rContext->powerState_lock);
1621 int result = rContext->powerState;
1622 (void)pthread_mutex_unlock(&rContext->powerState_lock);
1623 return result;
1624}
1625
1626void RFSetPowerState(READER_CONTEXT * rContext, int value)
1627{
1628 (void)pthread_mutex_lock(&rContext->powerState_lock);
1629 rContext->powerState = value;
1630 (void)pthread_mutex_unlock(&rContext->powerState_lock);
1631}
1632
This handles debugging.
This abstracts dynamic library loading functions.
void EHSignalEventToClients(void)
Sends an asynchronous event to any waiting client.
This handles card insertion/removal events, updates ATR, protocol, and status information.
#define PCSCLITE_SHARING_EXCLUSIVE_CONTEXT
Reader used in exclusive mode.
#define READER_NOT_INITIALIZED
Special value to indicate that power up has not yet happen This is used to auto start mode to wait un...
#define SCARD_E_INVALID_HANDLE
The supplied handle was invalid.
Definition pcsclite.h:113
#define SCARD_E_UNKNOWN_READER
The specified reader name is not recognized.
Definition pcsclite.h:125
#define SCARD_W_RESET_CARD
The smart card has been reset, so any shared state information is invalid.
Definition pcsclite.h:217
#define SCARD_F_UNKNOWN_ERROR
An internal error has been detected, but the source is unknown.
Definition pcsclite.h:147
#define SCARD_E_INVALID_TARGET
Registry startup information is missing or invalid.
Definition pcsclite.h:117
#define SCARD_S_SUCCESS
No error was encountered.
Definition pcsclite.h:107
#define SCARD_E_NO_MEMORY
Not enough memory available to complete this command.
Definition pcsclite.h:119
#define SCARD_E_SHARING_VIOLATION
The smart card cannot be accessed because of other connections outstanding.
Definition pcsclite.h:129
#define SCARD_E_DUPLICATE_READER
The reader driver did not produce a unique reader name.
Definition pcsclite.h:161
#define SCARD_E_INVALID_VALUE
One or more of the supplied parameters values could not be properly interpreted.
Definition pcsclite.h:141
#define SCARD_W_REMOVED_CARD
The smart card has been removed, so further communication is not possible.
Definition pcsclite.h:219
#define SCARD_E_INSUFFICIENT_BUFFER
The data buffer to receive returned data is too small for the returned data.
Definition pcsclite.h:123
#define SCARD_E_NOT_TRANSACTED
An attempt was made to end a non-existent transaction.
Definition pcsclite.h:151
#define SCARD_E_READER_UNAVAILABLE
The specified reader is not currently available for use.
Definition pcsclite.h:153
This provides a search API for hot pluggble devices.
#define IFD_NO_SUCH_DEVICE
The IFD_NO_SUCH_DEVICE error must be returned by the driver when it detects the reader is no more pre...
Definition ifdhandler.h:372
#define TAG_IFD_SIMULTANEOUS_ACCESS
number of reader the driver can manage
Definition ifdhandler.h:326
#define TAG_IFD_THREAD_SAFE
driver is thread safe
Definition ifdhandler.h:324
#define TAG_IFD_SLOTS_NUMBER
number of slots of the reader
Definition ifdhandler.h:325
#define TAG_IFD_POLLING_THREAD_WITH_TIMEOUT
driver uses a polling thread with a timeout parameter
Definition ifdhandler.h:330
#define TAG_IFD_SLOT_THREAD_SAFE
support access to different slots of the reader
Definition ifdhandler.h:323
#define IFD_SUCCESS
no error
Definition ifdhandler.h:351
#define TAG_IFD_DEVICE_REMOVED
signals the reader has been removed
Definition ifdhandler.h:331
RESPONSECODE IFDCloseIFD(READER_CONTEXT *rContext)
Close a communication channel to the IFD.
Definition ifdwrapper.c:161
LONG IFDStatusICC(READER_CONTEXT *rContext, PDWORD pdwStatus, bool hotplug)
Provide statistical information about the IFD and ICC including insertions, atr, powering status/etc.
Definition ifdwrapper.c:346
RESPONSECODE IFDOpenIFD(READER_CONTEXT *rContext)
Open a communication channel to the IFD.
Definition ifdwrapper.c:105
RESPONSECODE IFDGetCapabilities(READER_CONTEXT *rContext, DWORD dwTag, PDWORD pdwLength, PUCHAR pucValue)
Gets capabilities in the reader.
Definition ifdwrapper.c:238
RESPONSECODE IFDSetCapabilities(READER_CONTEXT *rContext, DWORD dwTag, DWORD dwLength, PUCHAR pucValue)
Set capabilities in the reader.
Definition ifdwrapper.c:207
This wraps the dynamic ifdhandler functions.
#define SCARD_PROTOCOL_UNDEFINED
protocol not set
Definition pcsclite.h:240
#define MAX_ATR_SIZE
Maximum ATR size.
Definition pcsclite.h:59
#define SCARD_UNKNOWN
Unknown state.
Definition pcsclite.h:258
LONG SCARDHANDLE
hCard returned by SCardConnect()
Definition pcsclite.h:55
int RFGetPowerState(READER_CONTEXT *rContext)
Wait until all connected readers have a chance to power up a possibly inserted card.
This keeps track of a list of currently available reader structures.
define structures to represent a reader
SCARDHANDLE hCard
hCard for this connection
_Atomic DWORD dwEventStatus
Recent event that must be sent.
READER_STATE readerState
reader state
Definition readers.h:133
pthread_mutex_t * mMutex
Mutex for this connection.
Definition readers.h:110
union ReaderContext::@326266165201103155124353152063316062370301160101 psFunctions
driver functions
pthread_mutex_t powerState_lock
powerState mutex
Definition readers.h:130
int port
Port ID.
Definition readers.h:122
_Atomic int32_t contexts
Number of open contexts.
Definition readers.h:126
int slot
Current Reader Slot.
Definition readers.h:123
int * pFeeds
Number of shared client to lib.
Definition readers.h:127
_Atomic SCARDHANDLE hLockId
Lock Id.
Definition readers.h:124
int * pMutex
Number of client to mutex.
Definition readers.h:128
int version
IFD Handler version number.
Definition readers.h:121
pthread_mutex_t handlesList_lock
lock for the above list
Definition readers.h:112
_Atomic int LockCount
number of recursive locks
Definition readers.h:125
char * library
Library Path.
Definition readers.h:106
_Atomic int reference
number of users of the structure
Definition readers.h:131
int powerState
auto power off state
Definition readers.h:129
char * device
Device Name.
Definition readers.h:107
_Atomic LPVOID vHandle
Dlopen handle.
Definition readers.h:120
char * pcFriendlyname
FRIENDLYNAME.
char * pcLibpath
LIBPATH.
char * pcDevicename
DEVICENAME.
_Atomic int32_t readerSharing
PCSCLITE_SHARING_* sharing status.
Definition readers.h:54
char readerName[MAX_READERNAME]
reader name
Definition readers.h:51
uint32_t cardProtocol
SCARD_PROTOCOL_* value.
Definition readers.h:58
UCHAR cardAtr[MAX_ATR_SIZE]
ATR.
Definition readers.h:56
uint32_t eventCounter
number of card events
Definition readers.h:52
_Atomic uint32_t cardAtrLength
ATR length.
Definition readers.h:57
uint32_t readerState
SCARD_* bit field.
Definition readers.h:53
This handles abstract system level calls.
const char * SYS_GetEnv(const char *name)
(More) secure version of getenv(3)
Definition sys_unix.c:168
int SYS_RandomInt(void)
Generate a pseudo random number.
Definition sys_unix.c:108
int SYS_USleep(int)
Makes the current process sleep for some microseconds.
Definition sys_unix.c:80