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