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 *
13Redistribution and use in source and binary forms, with or without
14modification, are permitted provided that the following conditions
15are met:
16
171. Redistributions of source code must retain the above copyright
18 notice, this list of conditions and the following disclaimer.
192. 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.
223. 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
25THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34THIS 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
73static READER_CONTEXT * sReadersContexts[PCSCLITE_MAX_READERS_CONTEXTS];
75static int maxReaderHandles = PCSC_MAX_READER_HANDLES;
76static DWORD dwNumReadersContexts = 0;
77#ifdef USE_SERIAL
78static char *ConfigFile = NULL;
79static int ConfigFileCRC = 0;
80#endif
81static pthread_mutex_t LockMutex = PTHREAD_MUTEX_INITIALIZER;
82
83#define IDENTITY_SHIFT 16
84static LONG removeReader(READER_CONTEXT * sReader);
85
86static 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
105LONG _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
117LONG _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
132LONG 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);
153
154 sReadersContexts[i]->readerState = &readerStates[i];
155 }
156
157 /* Create public event structures */
158 return EHInitializeEventStructures();
159}
160
161LONG 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))
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
582LONG 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)
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
640LONG 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");
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
712LONG 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
828LONG RFReaderInfo(const char *readerName, READER_CONTEXT ** sReader)
829{
830 int i;
831
832 if (readerName == NULL)
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
852}
853
854LONG 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
879}
880
881LONG 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
894LONG 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");
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");
991 }
992
993 return SCARD_S_SUCCESS;
994}
995
996LONG 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
1004LONG 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
1018LONG RFCheckSharing(SCARDHANDLE hCard, READER_CONTEXT * rContext)
1019{
1020 if (rContext->hLockId == 0 || rContext->hLockId == hCard)
1021 return SCARD_S_SUCCESS;
1022 else
1024}
1025
1026LONG 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
1042LONG 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
1075LONG 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
1091LONG 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
1149void 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
1177SCARDHANDLE 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
1207LONG 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 }
1245end:
1246 (void)pthread_mutex_unlock(&rContext->handlesList_lock);
1247 return rv;
1248}
1249
1250LONG 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
1272end:
1273 (void)pthread_mutex_unlock(&rContext->handlesList_lock);
1274
1275 /* Not Found */
1276 return rv;
1277}
1278
1279void 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
1312LONG 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);
1325 }
1326
1327 switch(currentHandle->dwEventStatus)
1328 {
1329 case 0:
1330 rv = SCARD_S_SUCCESS;
1331 break;
1332
1333 case SCARD_REMOVED:
1335 break;
1336
1337 case SCARD_RESET:
1338 rv = SCARD_W_RESET_CARD;
1339 break;
1340
1341 default:
1343 }
1344
1345 return rv;
1346}
1347
1348LONG 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 */
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
1367LONG RFCheckReaderStatus(READER_CONTEXT * rContext)
1368{
1369 if (rContext->readerState->readerState & SCARD_UNKNOWN)
1371 else
1372 return SCARD_S_SUCCESS;
1373}
1374
1375void 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
1422void 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
1452int 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
1492void 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
1594void 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.