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