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