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