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