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