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