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