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