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