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