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