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