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