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