pcsc-lite  1.9.1
readerfactory.c
Go to the documentation of this file.
1 /*
2  * MUSCLE SmartCard Development ( https://pcsclite.apdu.fr/ )
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;
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, same device - 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  && (strcmp(device, sReadersContexts[i]->device) == 0))
246  {
247  Log1(PCSC_LOG_ERROR, "Duplicate reader found.");
249  }
250  }
251  }
252  }
253 
254  /* We must find an empty slot to put the reader structure */
255  for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
256  {
257  if (sReadersContexts[i]->vHandle == 0)
258  {
259  dwContext = i;
260  break;
261  }
262  }
263 
265  {
266  /* No more spots left return */
267  return SCARD_E_NO_MEMORY;
268  }
269 
270  /* Check and set the readername to see if it must be enumerated */
271  parentNode = RFSetReaderName(sReadersContexts[dwContext], readerName,
272  library, port);
273  if (parentNode < -1)
274  return SCARD_E_NO_MEMORY;
275 
276  sReadersContexts[dwContext]->library = strdup(library);
277  sReadersContexts[dwContext]->device = strdup(device);
278  sReadersContexts[dwContext]->version = 0;
279  sReadersContexts[dwContext]->port = port;
280  sReadersContexts[dwContext]->mMutex = NULL;
281  sReadersContexts[dwContext]->contexts = 0;
282  sReadersContexts[dwContext]->pthThread = 0;
283  sReadersContexts[dwContext]->hLockId = 0;
284  sReadersContexts[dwContext]->LockCount = 0;
285  sReadersContexts[dwContext]->vHandle = NULL;
286  sReadersContexts[dwContext]->pFeeds = NULL;
287  sReadersContexts[dwContext]->pMutex = NULL;
288  sReadersContexts[dwContext]->pthCardEvent = NULL;
289 
290  lrv = list_init(&sReadersContexts[dwContext]->handlesList);
291  if (lrv < 0)
292  {
293  Log2(PCSC_LOG_CRITICAL, "list_init failed with return value: %d", lrv);
294  return SCARD_E_NO_MEMORY;
295  }
296 
297  lrv = list_attributes_seeker(&sReadersContexts[dwContext]->handlesList,
298  RDR_CLIHANDLES_seeker);
299  if (lrv < 0)
300  {
301  Log2(PCSC_LOG_CRITICAL,
302  "list_attributes_seeker failed with return value: %d", lrv);
303  return SCARD_E_NO_MEMORY;
304  }
305 
306  (void)pthread_mutex_init(&sReadersContexts[dwContext]->handlesList_lock,
307  NULL);
308 
309  (void)pthread_mutex_init(&sReadersContexts[dwContext]->powerState_lock,
310  NULL);
311  sReadersContexts[dwContext]->powerState = POWER_STATE_UNPOWERED;
312 
313  /* reference count */
314  (void)pthread_mutex_init(&sReadersContexts[dwContext]->reference_lock,
315  NULL);
316  sReadersContexts[dwContext]->reference = 1;
317 
318  /* If a clone to this reader exists take some values from that clone */
319  if (parentNode >= 0 && parentNode < PCSCLITE_MAX_READERS_CONTEXTS)
320  {
321  sReadersContexts[dwContext]->pFeeds =
322  sReadersContexts[parentNode]->pFeeds;
323  *(sReadersContexts[dwContext])->pFeeds += 1;
324  sReadersContexts[dwContext]->vHandle =
325  sReadersContexts[parentNode]->vHandle;
326  sReadersContexts[dwContext]->mMutex =
327  sReadersContexts[parentNode]->mMutex;
328  sReadersContexts[dwContext]->pMutex =
329  sReadersContexts[parentNode]->pMutex;
330 
331  /* Call on the parent driver to see if it is thread safe */
332  dwGetSize = sizeof(ucThread);
333  rv = IFDGetCapabilities(sReadersContexts[parentNode],
334  TAG_IFD_THREAD_SAFE, &dwGetSize, ucThread);
335 
336  if (rv == IFD_SUCCESS && dwGetSize == 1 && ucThread[0] == 1)
337  {
338  Log1(PCSC_LOG_INFO, "Driver is thread safe");
339  sReadersContexts[dwContext]->mMutex = NULL;
340  sReadersContexts[dwContext]->pMutex = NULL;
341  }
342  else
343  *(sReadersContexts[dwContext])->pMutex += 1;
344  }
345 
346  if (sReadersContexts[dwContext]->pFeeds == NULL)
347  {
348  sReadersContexts[dwContext]->pFeeds = malloc(sizeof(int));
349 
350  /* Initialize pFeeds to 1, otherwise multiple
351  cloned readers will cause pcscd to crash when
352  RFUnloadReader unloads the driver library
353  and there are still devices attached using it --mikeg*/
354  *(sReadersContexts[dwContext])->pFeeds = 1;
355  }
356 
357  if (sReadersContexts[dwContext]->mMutex == 0)
358  {
359  sReadersContexts[dwContext]->mMutex =
360  malloc(sizeof(pthread_mutex_t));
361  (void)pthread_mutex_init(sReadersContexts[dwContext]->mMutex, NULL);
362  }
363 
364  if (sReadersContexts[dwContext]->pMutex == NULL)
365  {
366  sReadersContexts[dwContext]->pMutex = malloc(sizeof(int));
367  *(sReadersContexts[dwContext])->pMutex = 1;
368  }
369 
370  dwNumReadersContexts += 1;
371 
372  rv = RFInitializeReader(sReadersContexts[dwContext]);
373  if (rv != SCARD_S_SUCCESS)
374  {
375  int log_level = PCSC_LOG_ERROR;
376  if (SCARD_E_UNKNOWN_READER == rv)
377  log_level = PCSC_LOG_INFO;
378 
379  /* Cannot connect to reader. Exit gracefully */
380  Log2(log_level, "%s init failed.", readerName);
381  (void)RFRemoveReader(readerName, port);
382  return rv;
383  }
384 
385  /* asynchronous card movement? */
386  {
387  RESPONSECODE (*fct)(DWORD, int) = NULL;
388 
389  dwGetSize = sizeof(fct);
390 
391  rv = IFDGetCapabilities(sReadersContexts[dwContext],
392  TAG_IFD_POLLING_THREAD_WITH_TIMEOUT, &dwGetSize, (PUCHAR)&fct);
393  if ((rv != SCARD_S_SUCCESS) || (dwGetSize != sizeof(fct)))
394  {
395  Log1(PCSC_LOG_INFO, "Using the pcscd polling thread");
396  }
397  else
398  {
399  sReadersContexts[dwContext]->pthCardEvent = fct;
400  Log1(PCSC_LOG_INFO, "Using the reader polling thread");
401  }
402 
403  rv = EHSpawnEventHandler(sReadersContexts[dwContext]);
404  if (rv != SCARD_S_SUCCESS)
405  {
406  Log2(PCSC_LOG_ERROR, "%s init failed.", readerName);
407  (void)RFRemoveReader(readerName, port);
408  return rv;
409  }
410  }
411 
412  /* Call on the driver to see if there are multiple slots */
413  dwGetSize = sizeof(ucGetData);
414  rv = IFDGetCapabilities((sReadersContexts[dwContext]),
415  TAG_IFD_SLOTS_NUMBER, &dwGetSize, ucGetData);
416 
417  int nbSlots = ucGetData[0];
418  if (rv != IFD_SUCCESS || dwGetSize != 1 || nbSlots == 0)
419  /* Reader does not have this defined. Must be a single slot
420  * reader so we can just return SCARD_S_SUCCESS. */
421  return SCARD_S_SUCCESS;
422 
423  if (1 == nbSlots)
424  /* Reader has only one slot */
425  return SCARD_S_SUCCESS;
426 
427  /*
428  * Check the number of slots and create a different
429  * structure for each one accordingly
430  */
431 
432  /* Initialize the rest of the slots */
433  for (j = 1; j < nbSlots; j++)
434  {
435  char *tmpReader = NULL;
436  DWORD dwContextB = 0;
437  RESPONSECODE (*fct)(DWORD, int) = NULL;
438 
439  /* We must find an empty spot to put the reader structure */
440  for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
441  {
442  if (sReadersContexts[i]->vHandle == 0)
443  {
444  dwContextB = i;
445  break;
446  }
447  }
448 
450  {
451  /* No more slot left return */
452  RFRemoveReader(readerName, port);
453  return SCARD_E_NO_MEMORY;
454  }
455 
456  /* Copy the previous reader name and increment the slot number */
457  tmpReader = sReadersContexts[dwContextB]->readerState->readerName;
458  memcpy(tmpReader,
459  sReadersContexts[dwContext]->readerState->readerName,
460  sizeof(sReadersContexts[dwContextB]->readerState->readerName));
461  snprintf(tmpReader + strlen(tmpReader) - 2, 3, "%02X", j);
462 
463  sReadersContexts[dwContextB]->library =
464  sReadersContexts[dwContext]->library;
465  sReadersContexts[dwContextB]->device =
466  sReadersContexts[dwContext]->device;
467  sReadersContexts[dwContextB]->version =
468  sReadersContexts[dwContext]->version;
469  sReadersContexts[dwContextB]->port =
470  sReadersContexts[dwContext]->port;
471  sReadersContexts[dwContextB]->vHandle =
472  sReadersContexts[dwContext]->vHandle;
473  sReadersContexts[dwContextB]->mMutex =
474  sReadersContexts[dwContext]->mMutex;
475  sReadersContexts[dwContextB]->pMutex =
476  sReadersContexts[dwContext]->pMutex;
477  sReadersContexts[dwContextB]->slot =
478  sReadersContexts[dwContext]->slot + j;
479  sReadersContexts[dwContextB]->pthCardEvent = NULL;
480 
481  /*
482  * Added by Dave - slots did not have a pFeeds
483  * parameter so it was by luck they were working
484  */
485  sReadersContexts[dwContextB]->pFeeds =
486  sReadersContexts[dwContext]->pFeeds;
487 
488  /* Added by Dave for multiple slots */
489  *(sReadersContexts[dwContextB])->pFeeds += 1;
490 
491  sReadersContexts[dwContextB]->contexts = 0;
492  sReadersContexts[dwContextB]->hLockId = 0;
493  sReadersContexts[dwContextB]->LockCount = 0;
494 
495  lrv = list_init(&sReadersContexts[dwContextB]->handlesList);
496  if (lrv < 0)
497  {
498  Log2(PCSC_LOG_CRITICAL, "list_init failed with return value: %d", lrv);
499  return SCARD_E_NO_MEMORY;
500  }
501 
502  lrv = list_attributes_seeker(&sReadersContexts[dwContextB]->handlesList,
503  RDR_CLIHANDLES_seeker);
504  if (lrv < 0)
505  {
506  Log2(PCSC_LOG_CRITICAL,
507  "list_attributes_seeker failed with return value: %d", lrv);
508  return SCARD_E_NO_MEMORY;
509  }
510 
511  (void)pthread_mutex_init(&sReadersContexts[dwContextB]->handlesList_lock, NULL);
512  (void)pthread_mutex_init(&sReadersContexts[dwContextB]->powerState_lock,
513  NULL);
514  sReadersContexts[dwContextB]->powerState = POWER_STATE_UNPOWERED;
515 
516  /* reference count */
517  (void)pthread_mutex_init(&sReadersContexts[dwContextB]->reference_lock,
518  NULL);
519  sReadersContexts[dwContextB]->reference = 1;
520 
521  /* Call on the parent driver to see if the slots are thread safe */
522  dwGetSize = sizeof(ucThread);
523  rv = IFDGetCapabilities((sReadersContexts[dwContext]),
524  TAG_IFD_SLOT_THREAD_SAFE, &dwGetSize, ucThread);
525 
526  if (rv == IFD_SUCCESS && dwGetSize == 1 && ucThread[0] == 1)
527  {
528  Log1(PCSC_LOG_INFO, "Driver is slot thread safe");
529 
530  sReadersContexts[dwContextB]->library =
531  strdup(sReadersContexts[dwContext]->library);
532  sReadersContexts[dwContextB]->device =
533  strdup(sReadersContexts[dwContext]->device);
534  sReadersContexts[dwContextB]->mMutex =
535  malloc(sizeof(pthread_mutex_t));
536  (void)pthread_mutex_init(sReadersContexts[dwContextB]->mMutex,
537  NULL);
538 
539  sReadersContexts[dwContextB]->pMutex = malloc(sizeof(int));
540  *(sReadersContexts[dwContextB])->pMutex = 1;
541  }
542  else
543  *(sReadersContexts[dwContextB])->pMutex += 1;
544 
545  dwNumReadersContexts += 1;
546 
547  rv = RFInitializeReader(sReadersContexts[dwContextB]);
548  if (rv != SCARD_S_SUCCESS)
549  {
550  /* Cannot connect to slot. Exit gracefully */
551  (void)RFRemoveReader(readerName, port);
552  return rv;
553  }
554 
555  /* asynchronous card movement? */
556  dwGetSize = sizeof(fct);
557 
558  rv = IFDGetCapabilities((sReadersContexts[dwContextB]),
559  TAG_IFD_POLLING_THREAD_WITH_TIMEOUT, &dwGetSize, (PUCHAR)&fct);
560  if ((rv != SCARD_S_SUCCESS) || (dwGetSize != sizeof(fct)))
561  {
562  Log1(PCSC_LOG_INFO, "Using the pcscd polling thread");
563  }
564  else
565  {
566  sReadersContexts[dwContextB]->pthCardEvent = fct;
567  Log1(PCSC_LOG_INFO, "Using the reader polling thread");
568  }
569 
570  rv = EHSpawnEventHandler(sReadersContexts[dwContextB]);
571  if (rv != SCARD_S_SUCCESS)
572  {
573  Log2(PCSC_LOG_ERROR, "%s init failed.", readerName);
574  (void)RFRemoveReader(readerName, port);
575  return rv;
576  }
577  }
578 
579  return SCARD_S_SUCCESS;
580 }
581 
582 LONG RFRemoveReader(const char *readerName, int port)
583 {
584  char lpcStripReader[MAX_READERNAME];
585  int i;
586 #ifdef FILTER_NAMES
587  const char *extend;
588 #endif
589  int extend_size = 0;
590 
591  if (readerName == NULL)
592  return SCARD_E_INVALID_VALUE;
593 
594 #ifdef FILTER_NAMES
595  extend = getenv("PCSCLITE_FILTER_EXTEND_READER_NAMES");
596  if (extend)
597  extend_size = strlen(extend);
598 #endif
599 
600  for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
601  {
602  if (sReadersContexts[i] && (sReadersContexts[i]->vHandle != 0))
603  {
604  strncpy(lpcStripReader,
605  sReadersContexts[i]->readerState->readerName,
606  sizeof(lpcStripReader));
607  lpcStripReader[strlen(lpcStripReader) - 6 - extend_size] = 0;
608 
609  /* Compare only the significant part of the reader name */
610  if ((strncmp(readerName, lpcStripReader, MAX_READERNAME - sizeof(" 00 00")) == 0)
611  && (port == sReadersContexts[i]->port))
612  {
613  /* remove the reader */
614  UNREF_READER(sReadersContexts[i])
615  }
616  }
617  }
618 
619  return SCARD_S_SUCCESS;
620 }
621 
622 LONG removeReader(READER_CONTEXT * sContext)
623 {
624  /* Try to destroy the thread */
625  if (sContext -> pthThread)
626  EHDestroyEventHandler(sContext);
627 
628  if ((NULL == sContext->pMutex) || (NULL == sContext->pFeeds))
629  {
630  Log1(PCSC_LOG_ERROR,
631  "Trying to remove an already removed driver");
632  return SCARD_E_INVALID_VALUE;
633  }
634 
635  RFUnInitializeReader(sContext);
636 
637  *sContext->pMutex -= 1;
638 
639  /* free shared resources when the last slot is closed */
640  if (0 == *sContext->pMutex)
641  {
642  (void)pthread_mutex_destroy(sContext->mMutex);
643  free(sContext->mMutex);
644  sContext->mMutex = NULL;
645  free(sContext->library);
646  free(sContext->device);
647  free(sContext->pMutex);
648  sContext->pMutex = NULL;
649  }
650 
651  *sContext->pFeeds -= 1;
652 
653  /* Added by Dave to free the pFeeds variable */
654  if (*sContext->pFeeds == 0)
655  {
656  free(sContext->pFeeds);
657  sContext->pFeeds = NULL;
658  }
659 
660  (void)pthread_mutex_destroy(&sContext->powerState_lock);
661  sContext->version = 0;
662  sContext->port = 0;
663  sContext->contexts = 0;
664  sContext->slot = 0;
665  sContext->hLockId = 0;
666  sContext->LockCount = 0;
667  sContext->vHandle = NULL;
668 
669  (void)pthread_mutex_lock(&sContext->handlesList_lock);
670  while (list_size(&sContext->handlesList) != 0)
671  {
672  int lrv;
673  RDR_CLIHANDLES *currentHandle;
674 
675  currentHandle = list_get_at(&sContext->handlesList, 0);
676  lrv = list_delete_at(&sContext->handlesList, 0);
677  if (lrv < 0)
678  Log2(PCSC_LOG_CRITICAL,
679  "list_delete_at failed with return value: %d", lrv);
680 
681  free(currentHandle);
682  }
683  (void)pthread_mutex_unlock(&sContext->handlesList_lock);
684  (void)pthread_mutex_destroy(&sContext->handlesList_lock);
685  list_destroy(&sContext->handlesList);
686  dwNumReadersContexts -= 1;
687 
688  /* signal an event to clients */
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 
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 = SCARD_S_SUCCESS;
1076  RESPONSECODE rvd;
1077 
1078  /* Spawn the event handler thread */
1079  Log3(PCSC_LOG_INFO, "Attempting startup of %s using %s",
1080  rContext->readerState->readerName, rContext->library);
1081 
1082 #ifndef PCSCLITE_STATIC_DRIVER
1083  /* loads the library */
1084  rv = RFLoadReader(rContext);
1085  if (rv != SCARD_S_SUCCESS)
1086  {
1087  Log2(PCSC_LOG_ERROR, "RFLoadReader failed: 0x%lX", rv);
1088  return rv;
1089  }
1090 
1091  /* binds the functions */
1092  rv = RFBindFunctions(rContext);
1093 
1094  if (rv != SCARD_S_SUCCESS)
1095  {
1096  Log2(PCSC_LOG_ERROR, "RFBindFunctions failed: 0x%lX", rv);
1097  (void)RFUnloadReader(rContext);
1098  return rv;
1099  }
1100 #else
1101  /* define a fake vHandle. Can be any value except NULL */
1102  rContext->vHandle = RFInitializeReader;
1103 #endif
1104 
1105  /* tries to open the port */
1106  rvd = IFDOpenIFD(rContext);
1107 
1108  if (rvd != IFD_SUCCESS)
1109  {
1110  int log_level = PCSC_LOG_CRITICAL;
1112 
1113  if (IFD_NO_SUCH_DEVICE == rvd)
1114  {
1115  /* wrong interface on a composite device? */
1116  log_level = PCSC_LOG_INFO;
1118  }
1119 
1120  Log3(log_level, "Open Port 0x%X Failed (%s)",
1121  rContext->port, rContext->device);
1122 
1123  /* IFDOpenIFD() failed */
1124  /* the reader was not started correctly */
1125  rContext->slot = -1;
1126  }
1127 
1128  return rv;
1129 }
1130 
1131 void RFUnInitializeReader(READER_CONTEXT * rContext)
1132 {
1133  Log2(PCSC_LOG_INFO, "Attempting shutdown of %s.",
1134  rContext->readerState->readerName);
1135 
1136  /* Do not close a reader if IFDOpenIFD() failed in RFInitializeReader() */
1137  if (rContext->slot != -1)
1138  (void)IFDCloseIFD(rContext);
1139 
1140  (void)RFUnBindFunctions(rContext);
1141  (void)RFUnloadReader(rContext);
1142 
1143  /*
1144  * Zero out the public status struct to allow it to be recycled and
1145  * used again
1146  */
1147  memset(rContext->readerState->readerName, 0,
1148  sizeof(rContext->readerState->readerName));
1149  memset(rContext->readerState->cardAtr, 0,
1150  sizeof(rContext->readerState->cardAtr));
1151  rContext->readerState->readerState = 0;
1152  rContext->readerState->readerSharing = 0;
1155 
1156  return;
1157 }
1158 
1159 SCARDHANDLE RFCreateReaderHandle(READER_CONTEXT * rContext)
1160 {
1161  SCARDHANDLE randHandle;
1162  LONG ret;
1163 
1164  (void)rContext;
1165 
1166  do
1167  {
1168  READER_CONTEXT *dummy_reader;
1169 
1170  /* Create a random handle with 32 bits check to see if it already is
1171  * used. */
1172  /* FIXME: THIS IS NOT STRONG ENOUGH: A 128-bit token should be
1173  * generated. The client and server would associate token and hCard
1174  * for authentication. */
1175  randHandle = SYS_RandomInt(0, -1);
1176 
1177  /* do we already use this hCard somewhere? */
1178  ret = RFReaderInfoById(randHandle, &dummy_reader);
1179  if (SCARD_S_SUCCESS == ret)
1180  UNREF_READER(dummy_reader)
1181  }
1182  while (SCARD_S_SUCCESS == ret);
1183 
1184  /* Once the for loop is completed w/o restart a good handle was
1185  * found and the loop can be exited. */
1186  return randHandle;
1187 }
1188 
1189 LONG RFAddReaderHandle(READER_CONTEXT * rContext, SCARDHANDLE hCard)
1190 {
1191  int listLength, lrv;
1192  RDR_CLIHANDLES *newHandle;
1193  LONG rv = SCARD_S_SUCCESS;
1194 
1195  (void)pthread_mutex_lock(&rContext->handlesList_lock);
1196  listLength = list_size(&rContext->handlesList);
1197 
1198  /* Throttle the number of possible handles */
1199  if (listLength >= maxReaderHandles)
1200  {
1201  Log2(PCSC_LOG_CRITICAL,
1202  "Too many handles opened, exceeding configured max (%d)",
1203  maxReaderHandles);
1204  rv = SCARD_E_NO_MEMORY;
1205  goto end;
1206  }
1207 
1208  newHandle = malloc(sizeof(RDR_CLIHANDLES));
1209  if (NULL == newHandle)
1210  {
1211  Log1(PCSC_LOG_CRITICAL, "malloc failed");
1212  rv = SCARD_E_NO_MEMORY;
1213  goto end;
1214  }
1215 
1216  newHandle->hCard = hCard;
1217  newHandle->dwEventStatus = 0;
1218 
1219  lrv = list_append(&rContext->handlesList, newHandle);
1220  if (lrv < 0)
1221  {
1222  free(newHandle);
1223  Log2(PCSC_LOG_CRITICAL, "list_append failed with return value: %d",
1224  lrv);
1225  rv = SCARD_E_NO_MEMORY;
1226  }
1227 end:
1228  (void)pthread_mutex_unlock(&rContext->handlesList_lock);
1229  return rv;
1230 }
1231 
1232 LONG RFRemoveReaderHandle(READER_CONTEXT * rContext, SCARDHANDLE hCard)
1233 {
1234  RDR_CLIHANDLES *currentHandle;
1235  int lrv;
1236  LONG rv = SCARD_S_SUCCESS;
1237 
1238  (void)pthread_mutex_lock(&rContext->handlesList_lock);
1239  currentHandle = list_seek(&rContext->handlesList, &hCard);
1240  if (NULL == currentHandle)
1241  {
1242  Log2(PCSC_LOG_CRITICAL, "list_seek failed to locate hCard=%lX", hCard);
1244  goto end;
1245  }
1246 
1247  lrv = list_delete(&rContext->handlesList, currentHandle);
1248  if (lrv < 0)
1249  Log2(PCSC_LOG_CRITICAL,
1250  "list_delete failed with return value: %d", lrv);
1251 
1252  free(currentHandle);
1253 
1254 end:
1255  (void)pthread_mutex_unlock(&rContext->handlesList_lock);
1256 
1257  /* Not Found */
1258  return rv;
1259 }
1260 
1261 void RFSetReaderEventState(READER_CONTEXT * rContext, DWORD dwEvent)
1262 {
1263  /* Set all the handles for that reader to the event */
1264  int list_index, listSize;
1265  RDR_CLIHANDLES *currentHandle;
1266 
1267  (void)pthread_mutex_lock(&rContext->handlesList_lock);
1268  listSize = list_size(&rContext->handlesList);
1269 
1270  for (list_index = 0; list_index < listSize; list_index++)
1271  {
1272  currentHandle = list_get_at(&rContext->handlesList, list_index);
1273  if (NULL == currentHandle)
1274  {
1275  Log2(PCSC_LOG_CRITICAL, "list_get_at failed at index %d",
1276  list_index);
1277  continue;
1278  }
1279 
1280  currentHandle->dwEventStatus = dwEvent;
1281  }
1282  (void)pthread_mutex_unlock(&rContext->handlesList_lock);
1283 
1284  if (SCARD_REMOVED == dwEvent)
1285  {
1286  /* unlock the card */
1287  rContext->hLockId = 0;
1288  rContext->LockCount = 0;
1289  }
1290 
1291  return;
1292 }
1293 
1294 LONG RFCheckReaderEventState(READER_CONTEXT * rContext, SCARDHANDLE hCard)
1295 {
1296  LONG rv;
1297  RDR_CLIHANDLES *currentHandle;
1298 
1299  (void)pthread_mutex_lock(&rContext->handlesList_lock);
1300  currentHandle = list_seek(&rContext->handlesList, &hCard);
1301  (void)pthread_mutex_unlock(&rContext->handlesList_lock);
1302  if (NULL == currentHandle)
1303  {
1304  /* Not Found */
1305  Log2(PCSC_LOG_CRITICAL, "list_seek failed for hCard 0x%lX", hCard);
1306  return SCARD_E_INVALID_HANDLE;
1307  }
1308 
1309  switch(currentHandle->dwEventStatus)
1310  {
1311  case 0:
1312  rv = SCARD_S_SUCCESS;
1313  break;
1314 
1315  case SCARD_REMOVED:
1316  rv = SCARD_W_REMOVED_CARD;
1317  break;
1318 
1319  case SCARD_RESET:
1320  rv = SCARD_W_RESET_CARD;
1321  break;
1322 
1323  default:
1324  rv = SCARD_E_INVALID_VALUE;
1325  }
1326 
1327  return rv;
1328 }
1329 
1330 LONG RFClearReaderEventState(READER_CONTEXT * rContext, SCARDHANDLE hCard)
1331 {
1332  RDR_CLIHANDLES *currentHandle;
1333 
1334  (void)pthread_mutex_lock(&rContext->handlesList_lock);
1335  currentHandle = list_seek(&rContext->handlesList, &hCard);
1336  (void)pthread_mutex_unlock(&rContext->handlesList_lock);
1337  if (NULL == currentHandle)
1338  /* Not Found */
1339  return SCARD_E_INVALID_HANDLE;
1340 
1341  currentHandle->dwEventStatus = 0;
1342 
1343  /* hCards should be unique so we
1344  * should be able to return
1345  * as soon as we have a hit */
1346  return SCARD_S_SUCCESS;
1347 }
1348 
1349 LONG RFCheckReaderStatus(READER_CONTEXT * rContext)
1350 {
1351  if (rContext->readerState->readerState & SCARD_UNKNOWN)
1353  else
1354  return SCARD_S_SUCCESS;
1355 }
1356 
1357 void RFCleanupReaders(void)
1358 {
1359  int i;
1360 
1361  Log1(PCSC_LOG_INFO, "entering cleaning function");
1362  for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
1363  {
1364  if (sReadersContexts[i]->vHandle != 0)
1365  {
1366  LONG rv;
1367  char lpcStripReader[MAX_READERNAME];
1368 
1369  Log2(PCSC_LOG_INFO, "Stopping reader: %s",
1370  sReadersContexts[i]->readerState->readerName);
1371 
1372  strncpy(lpcStripReader,
1373  sReadersContexts[i]->readerState->readerName,
1374  sizeof(lpcStripReader));
1375  /* strip the 6 last char ' 00 00' */
1376  lpcStripReader[strlen(lpcStripReader) - 6] = '\0';
1377 
1378  rv = RFRemoveReader(lpcStripReader, sReadersContexts[i]->port);
1379 
1380  if (rv != SCARD_S_SUCCESS)
1381  Log2(PCSC_LOG_ERROR, "RFRemoveReader error: 0x%08lX", rv);
1382 
1383  free(sReadersContexts[i]);
1384 
1385  sReadersContexts[i] = NULL;
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 
This handles debugging.
This abstracts dynamic library loading functions.
void EHSignalEventToClients(void)
Sends an asynchronous event to any waiting client.
Definition: eventhandler.c:116
This handles card insertion/removal events, updates ATR, protocol, and status information.
#define PCSCLITE_SHARING_EXCLUSIVE_CONTEXT
Reader used in exclusive mode.
Definition: eventhandler.h:79
#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:84
#define SCARD_E_INVALID_HANDLE
The supplied handle was invalid.
Definition: pcsclite.h:113
#define SCARD_E_UNKNOWN_READER
The specified reader name is not recognized.
Definition: pcsclite.h:125
#define SCARD_W_RESET_CARD
The smart card has been reset, so any shared state information is invalid.
Definition: pcsclite.h:216
#define SCARD_F_UNKNOWN_ERROR
An internal error has been detected, but the source is unknown.
Definition: pcsclite.h:147
#define SCARD_E_INVALID_TARGET
Registry startup information is missing or invalid.
Definition: pcsclite.h:117
#define SCARD_S_SUCCESS
No error was encountered.
Definition: pcsclite.h:107
#define SCARD_E_NO_MEMORY
Not enough memory available to complete this command.
Definition: pcsclite.h:119
#define SCARD_E_SHARING_VIOLATION
The smart card cannot be accessed because of other connections outstanding.
Definition: pcsclite.h:129
#define SCARD_E_DUPLICATE_READER
The reader driver did not produce a unique reader name.
Definition: pcsclite.h:161
#define SCARD_E_INVALID_VALUE
One or more of the supplied parameters values could not be properly interpreted.
Definition: pcsclite.h:141
#define SCARD_W_REMOVED_CARD
The smart card has been removed, so further communication is not possible.
Definition: pcsclite.h:218
#define SCARD_E_NOT_TRANSACTED
An attempt was made to end a non-existent transaction.
Definition: pcsclite.h:151
#define SCARD_E_READER_UNAVAILABLE
The specified reader is not currently available for use.
Definition: pcsclite.h:153
This provides a search API for hot pluggble devices.
#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:371
#define TAG_IFD_SIMULTANEOUS_ACCESS
number of reader the driver can manage
Definition: ifdhandler.h:326
#define TAG_IFD_THREAD_SAFE
driver is thread safe
Definition: ifdhandler.h:324
#define TAG_IFD_SLOTS_NUMBER
number of slots of the reader
Definition: ifdhandler.h:325
#define TAG_IFD_POLLING_THREAD_WITH_TIMEOUT
driver uses a polling thread with a timeout parameter
Definition: ifdhandler.h:330
#define TAG_IFD_SLOT_THREAD_SAFE
support access to different slots of the reader
Definition: ifdhandler.h:323
#define IFD_SUCCESS
no error
Definition: ifdhandler.h:350
RESPONSECODE IFDCloseIFD(READER_CONTEXT *rContext)
Close a communication channel to the IFD.
Definition: ifdwrapper.c:163
RESPONSECODE IFDOpenIFD(READER_CONTEXT *rContext)
Open a communication channel to the IFD.
Definition: ifdwrapper.c:105
RESPONSECODE IFDGetCapabilities(READER_CONTEXT *rContext, DWORD dwTag, PDWORD pdwLength, PUCHAR pucValue)
Get's capabilities in the reader.
Definition: ifdwrapper.c:235
LONG IFDStatusICC(READER_CONTEXT *rContext, PDWORD pdwStatus)
Provide statistical information about the IFD and ICC including insertions, atr, powering status/etc.
Definition: ifdwrapper.c:334
This wraps the dynamic ifdhandler functions.
This keeps a list of defines for pcsc-lite.
@ POWER_STATE_UNPOWERED
auto power off
Definition: pcscd.h:66
#define SCARD_RESET
Card was reset.
Definition: pcscd.h:41
#define SCARD_REMOVED
Card was removed.
Definition: pcscd.h:43
#define SCARD_PROTOCOL_UNDEFINED
protocol not set
Definition: pcsclite.h:239
#define MAX_ATR_SIZE
Maximum ATR size.
Definition: pcsclite.h:59
#define SCARD_UNKNOWN
Unknown state.
Definition: pcsclite.h:257
LONG SCARDHANDLE
hCard returned by SCardConnect()
Definition: pcsclite.h:55
#define PCSCLITE_MAX_READERS_CONTEXTS
Maximum readers context (a slot is count as a reader)
Definition: pcsclite.h:284
This keeps track of a list of currently available reader structures.
DWORD dwEventStatus
Recent event that must be sent.
SCARDHANDLE hCard
hCard for this connection
volatile SCARDHANDLE hLockId
Lock Id.
RESPONSECODE(* pthCardEvent)(DWORD, int)
Card Event sync.
pthread_mutex_t * mMutex
Mutex for this connection.
pthread_mutex_t powerState_lock
powerState mutex
LPVOID vHandle
Dlopen handle.
int port
Port ID.
pthread_t pthThread
Event polling thread.
int LockCount
number of recursive locks
union ReaderContext::@3 psFunctions
driver functions
int slot
Current Reader Slot.
int * pFeeds
Number of shared client to lib.
int * pMutex
Number of client to mutex.
pthread_mutex_t reference_lock
reference mutex
int version
IFD Handler version number.
int reference
number of users of the structure
int32_t contexts
Number of open contexts.
pthread_mutex_t handlesList_lock
lock for the above list
char * library
Library Path.
struct pubReaderStatesList * readerState
link to the reader state
int powerState
auto power off state
char * device
Device Name.
char * pcFriendlyname
FRIENDLYNAME.
Definition: readerfactory.h:50
char * pcLibpath
LIBPATH.
Definition: readerfactory.h:52
char * pcDevicename
DEVICENAME.
Definition: readerfactory.h:51
Define an exported public reader state structure so each application gets instant notification of cha...
Definition: eventhandler.h:53
char readerName[MAX_READERNAME]
reader name
Definition: eventhandler.h:54
int32_t readerSharing
PCSCLITE_SHARING_* sharing status.
Definition: eventhandler.h:57
uint32_t cardProtocol
SCARD_PROTOCOL_* value.
Definition: eventhandler.h:61
UCHAR cardAtr[MAX_ATR_SIZE]
ATR.
Definition: eventhandler.h:59
uint32_t eventCounter
number of card events
Definition: eventhandler.h:55
uint32_t readerState
SCARD_* bit field.
Definition: eventhandler.h:56
uint32_t cardAtrLength
ATR length.
Definition: eventhandler.h:60
This handles abstract system level calls.
int SYS_RandomInt(int, int)
Generate a pseudo random number.
Definition: sys_unix.c:95
int SYS_USleep(int)
Makes the current process sleep for some microseconds.
Definition: sys_unix.c:71
static READER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS]
Area used to read status information about the readers.