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