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