pcsc-lite  1.8.10
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 6748 2013-09-10 18:28:44Z 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  Log1(PCSC_LOG_INFO, "Driver is slot thread safe");
460 
461  sReadersContexts[dwContextB]->library =
462  strdup(sReadersContexts[dwContext]->library);
463  sReadersContexts[dwContextB]->device =
464  strdup(sReadersContexts[dwContext]->device);
465  sReadersContexts[dwContextB]->mMutex =
466  malloc(sizeof(pthread_mutex_t));
467  (void)pthread_mutex_init(sReadersContexts[dwContextB]->mMutex,
468  NULL);
469 
470  sReadersContexts[dwContextB]->pMutex = malloc(sizeof(int));
471  *(sReadersContexts[dwContextB])->pMutex = 1;
472  }
473  else
474  *(sReadersContexts[dwContextB])->pMutex += 1;
475 
476  dwNumReadersContexts += 1;
477 
478  rv = RFInitializeReader(sReadersContexts[dwContextB]);
479  if (rv != SCARD_S_SUCCESS)
480  {
481  /* Cannot connect to slot. Exit gracefully */
482  (void)RFRemoveReader(readerName, port);
483  return rv;
484  }
485 
486  /* asynchronous card movement? */
487  dwGetSize = sizeof(fct);
488 
489  rv = IFDGetCapabilities((sReadersContexts[dwContextB]),
490  TAG_IFD_POLLING_THREAD_WITH_TIMEOUT, &dwGetSize, (PUCHAR)&fct);
491  if ((rv != SCARD_S_SUCCESS) || (dwGetSize != sizeof(fct)))
492  {
493  Log1(PCSC_LOG_INFO, "Using the pcscd polling thread");
494  }
495  else
496  {
497  sReadersContexts[dwContextB]->pthCardEvent = fct;
498  Log1(PCSC_LOG_INFO, "Using the reader polling thread");
499  }
500 
501  rv = EHSpawnEventHandler(sReadersContexts[dwContextB]);
502  if (rv != SCARD_S_SUCCESS)
503  {
504  Log2(PCSC_LOG_ERROR, "%s init failed.", readerName);
505  (void)RFRemoveReader(readerName, port);
506  return rv;
507  }
508  }
509 
510  return SCARD_S_SUCCESS;
511 }
512 
513 LONG RFRemoveReader(const char *readerName, int port)
514 {
515  char lpcStripReader[MAX_READERNAME];
516  int i;
517 
518  if (readerName == NULL)
519  return SCARD_E_INVALID_VALUE;
520 
521  for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
522  {
523  if (sReadersContexts[i]->vHandle != 0)
524  {
525  strncpy(lpcStripReader,
526  sReadersContexts[i]->readerState->readerName,
527  sizeof(lpcStripReader));
528  lpcStripReader[strlen(lpcStripReader) - 6] = 0;
529 
530  /* Compare only the significant part of the reader name */
531  if ((strncmp(readerName, lpcStripReader, MAX_READERNAME - sizeof(" 00 00")) == 0)
532  && (port == sReadersContexts[i]->port))
533  {
534  /* remove the reader */
535  UNREF_READER(sReadersContexts[i])
536  }
537  }
538  }
539 
540  return SCARD_S_SUCCESS;
541 }
542 
543 LONG removeReader(READER_CONTEXT * sContext)
544 {
545  LONG rv;
546 
547  {
548  /* Try to destroy the thread */
549  if (sContext -> pthThread)
550  (void)EHDestroyEventHandler(sContext);
551 
552  if ((NULL == sContext->pMutex) || (NULL == sContext->pFeeds))
553  {
554  Log1(PCSC_LOG_ERROR,
555  "Trying to remove an already removed driver");
556  return SCARD_E_INVALID_VALUE;
557  }
558 
559  rv = RFUnInitializeReader(sContext);
560  if (rv != SCARD_S_SUCCESS)
561  return rv;
562 
563  *sContext->pMutex -= 1;
564 
565  /* free shared resources when the last slot is closed */
566  if (0 == *sContext->pMutex)
567  {
568  (void)pthread_mutex_destroy(sContext->mMutex);
569  free(sContext->mMutex);
570  sContext->mMutex = NULL;
571  free(sContext->library);
572  free(sContext->device);
573  free(sContext->pMutex);
574  sContext->pMutex = NULL;
575  }
576 
577  *sContext->pFeeds -= 1;
578 
579  /* Added by Dave to free the pFeeds variable */
580  if (*sContext->pFeeds == 0)
581  {
582  free(sContext->pFeeds);
583  sContext->pFeeds = NULL;
584  }
585 
586  (void)pthread_mutex_destroy(&sContext->powerState_lock);
587  sContext->version = 0;
588  sContext->port = 0;
589  sContext->contexts = 0;
590  sContext->slot = 0;
591  sContext->hLockId = 0;
592  sContext->LockCount = 0;
593  sContext->vHandle = NULL;
594 
595  (void)pthread_mutex_lock(&sContext->handlesList_lock);
596  while (list_size(&sContext->handlesList) != 0)
597  {
598  int lrv;
599  RDR_CLIHANDLES *currentHandle;
600 
601  currentHandle = list_get_at(&sContext->handlesList, 0);
602  lrv = list_delete_at(&sContext->handlesList, 0);
603  if (lrv < 0)
604  Log2(PCSC_LOG_CRITICAL,
605  "list_delete_at failed with return value: %d", lrv);
606 
607  free(currentHandle);
608  }
609  (void)pthread_mutex_unlock(&sContext->handlesList_lock);
610  (void)pthread_mutex_destroy(&sContext->handlesList_lock);
611  list_destroy(&sContext->handlesList);
612  dwNumReadersContexts -= 1;
613 
614  /* signal an event to clients */
615  (void)EHSignalEventToClients();
616  }
617 
618  return SCARD_S_SUCCESS;
619 }
620 
621 LONG RFSetReaderName(READER_CONTEXT * rContext, const char *readerName,
622  const char *libraryName, int port)
623 {
624  LONG parent = -1; /* reader number of the parent of the clone */
625  DWORD valueLength;
626  int currentDigit = -1;
627  int supportedChannels = 0;
628  int usedDigits[PCSCLITE_MAX_READERS_CONTEXTS];
629  int i;
630 
631  /* Clear the list */
632  for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
633  usedDigits[i] = FALSE;
634 
635  if (dwNumReadersContexts != 0)
636  {
637  for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
638  {
639  if (sReadersContexts[i]->vHandle != 0)
640  {
641  if (strcmp(sReadersContexts[i]->library, libraryName) == 0)
642  {
643  UCHAR tagValue[1];
644  LONG ret;
645 
646  /* Ask the driver if it supports multiple channels */
647  valueLength = sizeof(tagValue);
648  ret = IFDGetCapabilities(sReadersContexts[i],
650  &valueLength, tagValue);
651 
652  if ((ret == IFD_SUCCESS) && (valueLength == 1) &&
653  (tagValue[0] > 1))
654  {
655  supportedChannels = tagValue[0];
656  Log2(PCSC_LOG_INFO,
657  "Support %d simultaneous readers", tagValue[0]);
658  }
659  else
660  supportedChannels = 1;
661 
662  /* Check to see if it is a hotplug reader and different */
663  if ((((sReadersContexts[i]->port & 0xFFFF0000) ==
664  PCSCLITE_HP_BASE_PORT)
665  && (sReadersContexts[i]->port != port))
666  || (supportedChannels > 1))
667  {
668  const char *reader = sReadersContexts[i]->readerState->readerName;
669 
670  /*
671  * tells the caller who the parent of this
672  * clone is so it can use it's shared
673  * resources like mutex/etc.
674  */
675  parent = i;
676 
677  /*
678  * If the same reader already exists and it is
679  * hotplug then we must look for others and
680  * enumerate the readername
681  */
682  currentDigit = strtol(reader + strlen(reader) - 5, NULL, 16);
683 
684  /* This spot is taken */
685  usedDigits[currentDigit] = TRUE;
686  }
687  }
688  }
689  }
690  }
691 
692  /* default value */
693  i = 0;
694 
695  /* Other identical readers exist on the same bus */
696  if (currentDigit != -1)
697  {
698  for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
699  {
700  /* get the first free digit */
701  if (usedDigits[i] == FALSE)
702  break;
703  }
704 
705  if (i == PCSCLITE_MAX_READERS_CONTEXTS)
706  {
707  Log2(PCSC_LOG_ERROR, "Max number of readers reached: %d", PCSCLITE_MAX_READERS_CONTEXTS);
708  return -2;
709  }
710 
711  if (i >= supportedChannels)
712  {
713  Log3(PCSC_LOG_ERROR, "Driver %s does not support more than "
714  "%d reader(s). Maybe the driver should support "
715  "TAG_IFD_SIMULTANEOUS_ACCESS", libraryName, supportedChannels);
716  return -2;
717  }
718  }
719 
720  snprintf(rContext->readerState->readerName,
721  sizeof(rContext->readerState->readerName), "%s %02X 00",
722  readerName, i);
723 
724  /* Set the slot in 0xDDDDCCCC */
725  rContext->slot = i << 16;
726 
727  return parent;
728 }
729 
730 LONG RFReaderInfo(const char *readerName, READER_CONTEXT ** sReader)
731 {
732  int i;
733 
734  if (readerName == NULL)
735  return SCARD_E_UNKNOWN_READER;
736 
737  for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
738  {
739  if (sReadersContexts[i]->vHandle != 0)
740  {
741  if (strcmp(readerName,
742  sReadersContexts[i]->readerState->readerName) == 0)
743  {
744  /* Increase reference count */
745  REF_READER(sReadersContexts[i])
746 
747  *sReader = sReadersContexts[i];
748  return SCARD_S_SUCCESS;
749  }
750  }
751  }
752 
753  return SCARD_E_UNKNOWN_READER;
754 }
755 
756 LONG RFReaderInfoById(SCARDHANDLE hCard, READER_CONTEXT * * sReader)
757 {
758  int i;
759 
760  for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
761  {
762  if (sReadersContexts[i]->vHandle != 0)
763  {
764  RDR_CLIHANDLES * currentHandle;
765  (void)pthread_mutex_lock(&sReadersContexts[i]->handlesList_lock);
766  currentHandle = list_seek(&sReadersContexts[i]->handlesList,
767  &hCard);
768  (void)pthread_mutex_unlock(&sReadersContexts[i]->handlesList_lock);
769  if (currentHandle != NULL)
770  {
771  /* Increase reference count */
772  REF_READER(sReadersContexts[i])
773 
774  *sReader = sReadersContexts[i];
775  return SCARD_S_SUCCESS;
776  }
777  }
778  }
779 
780  return SCARD_E_INVALID_VALUE;
781 }
782 
783 LONG RFLoadReader(READER_CONTEXT * rContext)
784 {
785  if (rContext->vHandle != 0)
786  {
787  Log2(PCSC_LOG_INFO, "Reusing already loaded driver for %s",
788  rContext->library);
789  /* Another reader exists with this library loaded */
790  return SCARD_S_SUCCESS;
791  }
792 
793  return DYN_LoadLibrary(&rContext->vHandle, rContext->library);
794 }
795 
796 LONG RFBindFunctions(READER_CONTEXT * rContext)
797 {
798  int rv;
799  void *f;
800 
801  rv = DYN_GetAddress(rContext->vHandle, &f, "IFDHCreateChannelByName");
802  if (SCARD_S_SUCCESS == rv)
803  {
804  /* Ifd Handler 3.0 found */
805  rContext->version = IFD_HVERSION_3_0;
806  }
807  else
808  {
809  rv = DYN_GetAddress(rContext->vHandle, &f, "IFDHCreateChannel");
810  if (SCARD_S_SUCCESS == rv)
811  {
812  /* Ifd Handler 2.0 found */
813  rContext->version = IFD_HVERSION_2_0;
814  }
815  else
816  {
817  /* Neither version of the IFD Handler was found - exit */
818  Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing");
819  return SCARD_F_UNKNOWN_ERROR;
820  }
821  }
822 
823  if (rContext->version == IFD_HVERSION_2_0)
824  {
825  /* The following binds version 2.0 of the IFD Handler specs */
826 #define GET_ADDRESS_OPTIONALv2(s, code) \
827 { \
828  void *f1 = NULL; \
829  int rvl = DYN_GetAddress(rContext->vHandle, &f1, "IFDH" #s); \
830  if (SCARD_S_SUCCESS != rvl) \
831  { \
832  code \
833  } \
834  rContext->psFunctions.psFunctions_v2.pvf ## s = f1; \
835 }
836 
837 #define GET_ADDRESSv2(s) \
838  GET_ADDRESS_OPTIONALv2(s, \
839  Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing: " #s ); \
840  return(rv); )
841 
842  Log1(PCSC_LOG_INFO, "Loading IFD Handler 2.0");
843 
844  GET_ADDRESSv2(CreateChannel)
845  GET_ADDRESSv2(CloseChannel)
846  GET_ADDRESSv2(GetCapabilities)
847  GET_ADDRESSv2(SetCapabilities)
848  GET_ADDRESSv2(PowerICC)
849  GET_ADDRESSv2(TransmitToICC)
850  GET_ADDRESSv2(ICCPresence)
851  GET_ADDRESS_OPTIONALv2(SetProtocolParameters, )
852 
853  GET_ADDRESSv2(Control)
854  }
855  else if (rContext->version == IFD_HVERSION_3_0)
856  {
857  /* The following binds version 3.0 of the IFD Handler specs */
858 #define GET_ADDRESS_OPTIONALv3(s, code) \
859 { \
860  void *f1 = NULL; \
861  int rvl = DYN_GetAddress(rContext->vHandle, &f1, "IFDH" #s); \
862  if (SCARD_S_SUCCESS != rvl) \
863  { \
864  code \
865  } \
866  rContext->psFunctions.psFunctions_v3.pvf ## s = f1; \
867 }
868 
869 #define GET_ADDRESSv3(s) \
870  GET_ADDRESS_OPTIONALv3(s, \
871  Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing: " #s ); \
872  return(rv); )
873 
874  Log1(PCSC_LOG_INFO, "Loading IFD Handler 3.0");
875 
876  GET_ADDRESSv2(CreateChannel)
877  GET_ADDRESSv2(CloseChannel)
878  GET_ADDRESSv2(GetCapabilities)
879  GET_ADDRESSv2(SetCapabilities)
880  GET_ADDRESSv2(PowerICC)
881  GET_ADDRESSv2(TransmitToICC)
882  GET_ADDRESSv2(ICCPresence)
883  GET_ADDRESS_OPTIONALv2(SetProtocolParameters, )
884 
885  GET_ADDRESSv3(CreateChannelByName)
886  GET_ADDRESSv3(Control)
887  }
888  else
889  {
890  /* Who knows what could have happenned for it to get here. */
891  Log1(PCSC_LOG_CRITICAL, "IFD Handler not 1.0/2.0 or 3.0");
892  return SCARD_F_UNKNOWN_ERROR;
893  }
894 
895  return SCARD_S_SUCCESS;
896 }
897 
898 LONG RFUnBindFunctions(READER_CONTEXT * rContext)
899 {
900  /* Zero out everything */
901  memset(&rContext->psFunctions, 0, sizeof(rContext->psFunctions));
902 
903  return SCARD_S_SUCCESS;
904 }
905 
906 LONG RFUnloadReader(READER_CONTEXT * rContext)
907 {
908  /* Make sure no one else is using this library */
909  if (*rContext->pFeeds == 1)
910  {
911  Log1(PCSC_LOG_INFO, "Unloading reader driver.");
912  (void)DYN_CloseLibrary(&rContext->vHandle);
913  }
914 
915  rContext->vHandle = NULL;
916 
917  return SCARD_S_SUCCESS;
918 }
919 
920 LONG RFCheckSharing(SCARDHANDLE hCard, READER_CONTEXT * rContext)
921 {
922  if (rContext->hLockId == 0 || rContext->hLockId == hCard)
923  return SCARD_S_SUCCESS;
924  else
926 }
927 
928 LONG RFLockSharing(SCARDHANDLE hCard, READER_CONTEXT * rContext)
929 {
930  LONG rv;
931 
932  (void)pthread_mutex_lock(&LockMutex);
933  rv = RFCheckSharing(hCard, rContext);
934  if (SCARD_S_SUCCESS == rv)
935  {
936  rContext->LockCount += 1;
937  rContext->hLockId = hCard;
938  }
939  (void)pthread_mutex_unlock(&LockMutex);
940 
941  return rv;
942 }
943 
944 LONG RFUnlockSharing(SCARDHANDLE hCard, READER_CONTEXT * rContext)
945 {
946  LONG rv;
947 
948  (void)pthread_mutex_lock(&LockMutex);
949  rv = RFCheckSharing(hCard, rContext);
950  if (SCARD_S_SUCCESS == rv)
951  {
952  if (rContext->LockCount > 0)
953  {
954  rContext->LockCount -= 1;
955  if (0 == rContext->LockCount)
956  rContext->hLockId = 0;
957  }
958  else
959  /* rContext->LockCount == 0 */
961  }
962  (void)pthread_mutex_unlock(&LockMutex);
963 
964  return rv;
965 }
966 
967 LONG RFUnlockAllSharing(SCARDHANDLE hCard, READER_CONTEXT * rContext)
968 {
969  LONG rv;
970 
971  (void)pthread_mutex_lock(&LockMutex);
972  rv = RFCheckSharing(hCard, rContext);
973  if (SCARD_S_SUCCESS == rv)
974  {
975  rContext->LockCount = 0;
976  rContext->hLockId = 0;
977  }
978  (void)pthread_mutex_unlock(&LockMutex);
979 
980  return rv;
981 }
982 
983 LONG RFInitializeReader(READER_CONTEXT * rContext)
984 {
985  LONG rv;
986 
987  /* Spawn the event handler thread */
988  Log3(PCSC_LOG_INFO, "Attempting startup of %s using %s",
989  rContext->readerState->readerName, rContext->library);
990 
991 #ifndef PCSCLITE_STATIC_DRIVER
992  /* loads the library */
993  rv = RFLoadReader(rContext);
994  if (rv != SCARD_S_SUCCESS)
995  {
996  Log2(PCSC_LOG_ERROR, "RFLoadReader failed: 0x%lX", rv);
997  return rv;
998  }
999 
1000  /* binds the functions */
1001  rv = RFBindFunctions(rContext);
1002 
1003  if (rv != SCARD_S_SUCCESS)
1004  {
1005  Log2(PCSC_LOG_ERROR, "RFBindFunctions failed: 0x%lX", rv);
1006  (void)RFUnloadReader(rContext);
1007  return rv;
1008  }
1009 #else
1010  /* define a fake vHandle. Can be any value except NULL */
1011  rContext->vHandle = RFInitializeReader;
1012 #endif
1013 
1014  /* tries to open the port */
1015  rv = IFDOpenIFD(rContext);
1016 
1017  if (rv != IFD_SUCCESS)
1018  {
1019  Log3(PCSC_LOG_CRITICAL, "Open Port 0x%X Failed (%s)",
1020  rContext->port, rContext->device);
1021 
1022  /* the reader was not started correctly */
1023  rContext->slot = -1;
1024 
1025  /* IFDOpenIFD() failed */
1026  rContext->slot = -1;
1027 
1028  if (IFD_NO_SUCH_DEVICE == rv)
1029  return SCARD_E_UNKNOWN_READER;
1030  else
1031  return SCARD_E_INVALID_TARGET;
1032  }
1033 
1034  return SCARD_S_SUCCESS;
1035 }
1036 
1037 LONG RFUnInitializeReader(READER_CONTEXT * rContext)
1038 {
1039  Log2(PCSC_LOG_INFO, "Attempting shutdown of %s.",
1040  rContext->readerState->readerName);
1041 
1042  /* Do not close a reader if IFDOpenIFD() failed in RFInitializeReader() */
1043  if (rContext->slot != -1)
1044  (void)IFDCloseIFD(rContext);
1045 
1046  (void)RFUnBindFunctions(rContext);
1047  (void)RFUnloadReader(rContext);
1048 
1049  /*
1050  * Zero out the public status struct to allow it to be recycled and
1051  * used again
1052  */
1053  memset(rContext->readerState->readerName, 0,
1054  sizeof(rContext->readerState->readerName));
1055  memset(rContext->readerState->cardAtr, 0,
1056  sizeof(rContext->readerState->cardAtr));
1057  rContext->readerState->readerState = 0;
1058  rContext->readerState->readerSharing = 0;
1061 
1062  return SCARD_S_SUCCESS;
1063 }
1064 
1065 SCARDHANDLE RFCreateReaderHandle(READER_CONTEXT * rContext)
1066 {
1067  SCARDHANDLE randHandle;
1068  LONG ret;
1069 
1070  (void)rContext;
1071 
1072  do
1073  {
1074  READER_CONTEXT *dummy_reader;
1075 
1076  /* Create a random handle with 32 bits check to see if it already is
1077  * used. */
1078  /* FIXME: THIS IS NOT STRONG ENOUGH: A 128-bit token should be
1079  * generated. The client and server would associate token and hCard
1080  * for authentication. */
1081  randHandle = SYS_RandomInt(0, -1);
1082 
1083  /* do we already use this hCard somewhere? */
1084  ret = RFReaderInfoById(randHandle, &dummy_reader);
1085  if (SCARD_S_SUCCESS == ret)
1086  UNREF_READER(dummy_reader)
1087  }
1088  while (SCARD_S_SUCCESS == ret);
1089 
1090  /* Once the for loop is completed w/o restart a good handle was
1091  * found and the loop can be exited. */
1092  return randHandle;
1093 }
1094 
1095 LONG RFDestroyReaderHandle(/*@unused@*/ SCARDHANDLE hCard)
1096 {
1097  (void)hCard;
1098  return SCARD_S_SUCCESS;
1099 }
1100 
1101 LONG RFAddReaderHandle(READER_CONTEXT * rContext, SCARDHANDLE hCard)
1102 {
1103  int listLength, lrv;
1104  RDR_CLIHANDLES *newHandle;
1105  LONG rv = SCARD_S_SUCCESS;
1106 
1107  (void)pthread_mutex_lock(&rContext->handlesList_lock);
1108  listLength = list_size(&rContext->handlesList);
1109 
1110  /* Throttle the number of possible handles */
1111  if (listLength >= maxReaderHandles)
1112  {
1113  Log2(PCSC_LOG_CRITICAL,
1114  "Too many handles opened, exceeding configured max (%d)",
1115  maxReaderHandles);
1116  rv = SCARD_E_NO_MEMORY;
1117  goto end;
1118  }
1119 
1120  newHandle = malloc(sizeof(RDR_CLIHANDLES));
1121  if (NULL == newHandle)
1122  {
1123  Log1(PCSC_LOG_CRITICAL, "malloc failed");
1124  rv = SCARD_E_NO_MEMORY;
1125  goto end;
1126  }
1127 
1128  newHandle->hCard = hCard;
1129  newHandle->dwEventStatus = 0;
1130 
1131  lrv = list_append(&rContext->handlesList, newHandle);
1132  if (lrv < 0)
1133  {
1134  free(newHandle);
1135  Log2(PCSC_LOG_CRITICAL, "list_append failed with return value: %d",
1136  lrv);
1137  rv = SCARD_E_NO_MEMORY;
1138  }
1139 end:
1140  (void)pthread_mutex_unlock(&rContext->handlesList_lock);
1141  return rv;
1142 }
1143 
1144 LONG RFRemoveReaderHandle(READER_CONTEXT * rContext, SCARDHANDLE hCard)
1145 {
1146  RDR_CLIHANDLES *currentHandle;
1147  int lrv;
1148  LONG rv = SCARD_S_SUCCESS;
1149 
1150  (void)pthread_mutex_lock(&rContext->handlesList_lock);
1151  currentHandle = list_seek(&rContext->handlesList, &hCard);
1152  if (NULL == currentHandle)
1153  {
1154  Log2(PCSC_LOG_CRITICAL, "list_seek failed to locate hCard=%lX", hCard);
1156  goto end;
1157  }
1158 
1159  lrv = list_delete(&rContext->handlesList, currentHandle);
1160  if (lrv < 0)
1161  Log2(PCSC_LOG_CRITICAL,
1162  "list_delete failed with return value: %d", lrv);
1163 
1164  free(currentHandle);
1165 
1166 end:
1167  (void)pthread_mutex_unlock(&rContext->handlesList_lock);
1168 
1169  /* Not Found */
1170  return rv;
1171 }
1172 
1173 LONG RFSetReaderEventState(READER_CONTEXT * rContext, DWORD dwEvent)
1174 {
1175  /* Set all the handles for that reader to the event */
1176  int list_index, listSize;
1177  RDR_CLIHANDLES *currentHandle;
1178 
1179  (void)pthread_mutex_lock(&rContext->handlesList_lock);
1180  listSize = list_size(&rContext->handlesList);
1181 
1182  for (list_index = 0; list_index < listSize; list_index++)
1183  {
1184  currentHandle = list_get_at(&rContext->handlesList, list_index);
1185  if (NULL == currentHandle)
1186  {
1187  Log2(PCSC_LOG_CRITICAL, "list_get_at failed at index %d",
1188  list_index);
1189  continue;
1190  }
1191 
1192  currentHandle->dwEventStatus = dwEvent;
1193  }
1194  (void)pthread_mutex_unlock(&rContext->handlesList_lock);
1195 
1196  if (SCARD_REMOVED == dwEvent)
1197  {
1198  /* unlock the card */
1199  rContext->hLockId = 0;
1200  rContext->LockCount = 0;
1201  }
1202 
1203  return SCARD_S_SUCCESS;
1204 }
1205 
1206 LONG RFCheckReaderEventState(READER_CONTEXT * rContext, SCARDHANDLE hCard)
1207 {
1208  LONG rv;
1209  RDR_CLIHANDLES *currentHandle;
1210 
1211  (void)pthread_mutex_lock(&rContext->handlesList_lock);
1212  currentHandle = list_seek(&rContext->handlesList, &hCard);
1213  (void)pthread_mutex_unlock(&rContext->handlesList_lock);
1214  if (NULL == currentHandle)
1215  {
1216  /* Not Found */
1217  Log2(PCSC_LOG_CRITICAL, "list_seek failed for hCard 0x%lX", hCard);
1218  return SCARD_E_INVALID_HANDLE;
1219  }
1220 
1221  switch(currentHandle->dwEventStatus)
1222  {
1223  case 0:
1224  rv = SCARD_S_SUCCESS;
1225  break;
1226 
1227  case SCARD_REMOVED:
1228  rv = SCARD_W_REMOVED_CARD;
1229  break;
1230 
1231  case SCARD_RESET:
1232  rv = SCARD_W_RESET_CARD;
1233  break;
1234 
1235  default:
1236  rv = SCARD_E_INVALID_VALUE;
1237  }
1238 
1239  return rv;
1240 }
1241 
1242 LONG RFClearReaderEventState(READER_CONTEXT * rContext, SCARDHANDLE hCard)
1243 {
1244  RDR_CLIHANDLES *currentHandle;
1245 
1246  (void)pthread_mutex_lock(&rContext->handlesList_lock);
1247  currentHandle = list_seek(&rContext->handlesList, &hCard);
1248  (void)pthread_mutex_unlock(&rContext->handlesList_lock);
1249  if (NULL == currentHandle)
1250  /* Not Found */
1251  return SCARD_E_INVALID_HANDLE;
1252 
1253  currentHandle->dwEventStatus = 0;
1254 
1255  /* hCards should be unique so we
1256  * should be able to return
1257  * as soon as we have a hit */
1258  return SCARD_S_SUCCESS;
1259 }
1260 
1261 LONG RFCheckReaderStatus(READER_CONTEXT * rContext)
1262 {
1263  if (rContext->readerState->readerState & SCARD_UNKNOWN)
1265  else
1266  return SCARD_S_SUCCESS;
1267 }
1268 
1269 void RFCleanupReaders(void)
1270 {
1271  int i;
1272 
1273  Log1(PCSC_LOG_INFO, "entering cleaning function");
1274  for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
1275  {
1276  if (sReadersContexts[i]->vHandle != 0)
1277  {
1278  LONG rv;
1279  char lpcStripReader[MAX_READERNAME];
1280 
1281  Log2(PCSC_LOG_INFO, "Stopping reader: %s",
1282  sReadersContexts[i]->readerState->readerName);
1283 
1284  strncpy(lpcStripReader,
1285  sReadersContexts[i]->readerState->readerName,
1286  sizeof(lpcStripReader));
1287  /* strip the 6 last char ' 00 00' */
1288  lpcStripReader[strlen(lpcStripReader) - 6] = '\0';
1289 
1290  rv = RFRemoveReader(lpcStripReader, sReadersContexts[i]->port);
1291 
1292  if (rv != SCARD_S_SUCCESS)
1293  Log2(PCSC_LOG_ERROR, "RFRemoveReader error: 0x%08lX", rv);
1294 
1295  free(sReadersContexts[i]);
1296  }
1297  }
1298 
1299 #ifdef USE_SERIAL
1300  if (ConfigFile)
1301  {
1302  free(ConfigFile);
1303  ConfigFile = NULL;
1304  }
1305 #endif
1306 }
1307 
1312 #ifdef USE_USB
1313 void RFWaitForReaderInit(void)
1314 {
1315  int i, need_to_wait;
1316 
1317  do
1318  {
1319  need_to_wait = FALSE;
1320  for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
1321  {
1322  /* reader is present */
1323  if (sReadersContexts[i]->vHandle != NULL)
1324  {
1325  /* but card state is not yet available */
1327  == sReadersContexts[i]->readerState->cardAtrLength)
1328  {
1329  Log2(PCSC_LOG_DEBUG, "Waiting init for reader: %s",
1330  sReadersContexts[i]->readerState->readerName);
1331  need_to_wait = TRUE;
1332  }
1333  }
1334  }
1335 
1336  if (need_to_wait)
1337  SYS_USleep(10*1000); /* 10 ms */
1338  } while (need_to_wait);
1339 }
1340 #endif
1341 
1342 #ifdef USE_SERIAL
1343 int RFStartSerialReaders(const char *readerconf)
1344 {
1345  SerialReader *reader_list = NULL;
1346  int i, rv;
1347 
1348  /* remember the configuration filename for RFReCheckReaderConf() */
1349  ConfigFile = strdup(readerconf);
1350 
1351  rv = DBGetReaderListDir(readerconf, &reader_list);
1352 
1353  /* the list is empty */
1354  if (NULL == reader_list)
1355  return rv;
1356 
1357  for (i=0; reader_list[i].pcFriendlyname; i++)
1358  {
1359  int j;
1360 
1361  (void)RFAddReader(reader_list[i].pcFriendlyname,
1362  reader_list[i].channelId,
1363  reader_list[i].pcLibpath, reader_list[i].pcDevicename);
1364 
1365  /* update the ConfigFileCRC (this false "CRC" is very weak) */
1366  for (j=0; j<reader_list[i].pcFriendlyname[j]; j++)
1367  ConfigFileCRC += reader_list[i].pcFriendlyname[j];
1368  for (j=0; j<reader_list[i].pcLibpath[j]; j++)
1369  ConfigFileCRC += reader_list[i].pcLibpath[j];
1370  for (j=0; j<reader_list[i].pcDevicename[j]; j++)
1371  ConfigFileCRC += reader_list[i].pcDevicename[j];
1372 
1373  /* free strings allocated by DBGetReaderListDir() */
1374  free(reader_list[i].pcFriendlyname);
1375  free(reader_list[i].pcLibpath);
1376  free(reader_list[i].pcDevicename);
1377  }
1378  free(reader_list);
1379 
1380  return rv;
1381 }
1382 
1383 void RFReCheckReaderConf(void)
1384 {
1385  SerialReader *reader_list = NULL;
1386  int i, crc;
1387 
1388  (void)DBGetReaderListDir(ConfigFile, &reader_list);
1389 
1390  /* the list is empty */
1391  if (NULL == reader_list)
1392  return;
1393 
1394  crc = 0;
1395  for (i=0; reader_list[i].pcFriendlyname; i++)
1396  {
1397  int j;
1398 
1399  /* calculate a local crc */
1400  for (j=0; j<reader_list[i].pcFriendlyname[j]; j++)
1401  crc += reader_list[i].pcFriendlyname[j];
1402  for (j=0; j<reader_list[i].pcLibpath[j]; j++)
1403  crc += reader_list[i].pcLibpath[j];
1404  for (j=0; j<reader_list[i].pcDevicename[j]; j++)
1405  crc += reader_list[i].pcDevicename[j];
1406  }
1407 
1408  /* cancel if the configuration file has been modified */
1409  if (crc != ConfigFileCRC)
1410  {
1411  Log2(PCSC_LOG_CRITICAL,
1412  "configuration file: %s has been modified. Recheck canceled",
1413  ConfigFile);
1414  return;
1415  }
1416 
1417  for (i=0; reader_list[i].pcFriendlyname; i++)
1418  {
1419  int r;
1420  char present = FALSE;
1421 
1422  Log2(PCSC_LOG_DEBUG, "refresh reader: %s",
1423  reader_list[i].pcFriendlyname);
1424 
1425  /* is the reader already present? */
1426  for (r = 0; r < PCSCLITE_MAX_READERS_CONTEXTS; r++)
1427  {
1428  if (sReadersContexts[r]->vHandle != 0)
1429  {
1430  char lpcStripReader[MAX_READERNAME];
1431  int tmplen;
1432 
1433  /* get the reader name without the reader and slot numbers */
1434  strncpy(lpcStripReader,
1435  sReadersContexts[i]->readerState->readerName,
1436  sizeof(lpcStripReader));
1437  tmplen = strlen(lpcStripReader);
1438  lpcStripReader[tmplen - 6] = 0;
1439 
1440  if ((strcmp(reader_list[i].pcFriendlyname, lpcStripReader) == 0)
1441  && (reader_list[r].channelId == sReadersContexts[i]->port))
1442  {
1443  DWORD dwStatus = 0;
1444 
1445  /* the reader was already started */
1446  present = TRUE;
1447 
1448  /* verify the reader is still connected */
1449  if (IFDStatusICC(sReadersContexts[r], &dwStatus)
1450  != SCARD_S_SUCCESS)
1451  {
1452  Log2(PCSC_LOG_INFO, "Reader %s disappeared",
1453  reader_list[i].pcFriendlyname);
1454  (void)RFRemoveReader(reader_list[i].pcFriendlyname,
1455  reader_list[r].channelId);
1456  }
1457  }
1458  }
1459  }
1460 
1461  /* the reader was not present */
1462  if (!present)
1463  /* we try to add it */
1464  (void)RFAddReader(reader_list[i].pcFriendlyname,
1465  reader_list[i].channelId, reader_list[i].pcLibpath,
1466  reader_list[i].pcDevicename);
1467 
1468  /* free strings allocated by DBGetReaderListDir() */
1469  free(reader_list[i].pcFriendlyname);
1470  free(reader_list[i].pcLibpath);
1471  free(reader_list[i].pcDevicename);
1472  }
1473  free(reader_list);
1474 }
1475 #endif
1476 
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'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
#define SCARD_E_NOT_TRANSACTED
An attempt was made to end a non-existent transaction.
Definition: pcsclite.h:102
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:59