pcsc-lite 1.9.9
winscard.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) 2002-2011
7 * Ludovic Rousseau <ludovic.rousseau@free.fr>
8 *
9Redistribution and use in source and binary forms, with or without
10modification, are permitted provided that the following conditions
11are met:
12
131. Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
152. Redistributions in binary form must reproduce the above copyright
16 notice, this list of conditions and the following disclaimer in the
17 documentation and/or other materials provided with the distribution.
183. The name of the author may not be used to endorse or promote products
19 derived from this software without specific prior written permission.
20
21THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
103#include "config.h"
104#include <stdlib.h>
105#include <sys/time.h>
106#include <string.h>
107#include <pthread.h>
108
109#include "pcscd.h"
110#include "winscard.h"
111#include "ifdhandler.h"
112#include "debuglog.h"
113#include "readerfactory.h"
114#include "prothandler.h"
115#include "ifdwrapper.h"
116#include "atrhandler.h"
117#include "sys_generic.h"
118#include "eventhandler.h"
119#include "utils.h"
120#include "reader.h"
121
122#undef DO_PROFILE
123#ifdef DO_PROFILE
124
125#ifndef FALSE
126#define FALSE 0
127#define TRUE 1
128#endif
129
130#define PROFILE_FILE "/tmp/pcscd_profile"
131#include <stdio.h>
132#include <sys/time.h>
133#include <errno.h>
134#include <unistd.h>
135
136struct timeval profile_time_start;
137FILE *fd;
138char profile_tty;
139
140#define PROFILE_START profile_start(__FUNCTION__);
141#define PROFILE_END profile_end(__FUNCTION__, __LINE__);
142
143static void profile_start(const char *f)
144{
145 static char initialized = FALSE;
146
147 if (!initialized)
148 {
149 initialized = TRUE;
150 fd = fopen(PROFILE_FILE, "a+");
151 if (NULL == fd)
152 {
153 fprintf(stderr, "\33[01;31mCan't open %s: %s\33[0m\n",
154 PROFILE_FILE, strerror(errno));
155 exit(-1);
156 }
157 fprintf(fd, "\nStart a new profile\n");
158 fflush(fd);
159
160 if (isatty(fileno(stderr)))
161 profile_tty = TRUE;
162 else
163 profile_tty = FALSE;
164 }
165
166 gettimeofday(&profile_time_start, NULL);
167} /* profile_start */
168
169
170static void profile_end(const char *f, int line)
171{
172 struct timeval profile_time_end;
173 long d;
174
175 gettimeofday(&profile_time_end, NULL);
176 d = time_sub(&profile_time_end, &profile_time_start);
177
178 if (profile_tty)
179 fprintf(stderr, "\33[01;31mRESULT %s \33[35m%ld\33[0m (%d)\n", f, d,
180 line);
181 fprintf(fd, "%s %ld\n", f, d);
182 fflush(fd);
183} /* profile_end */
184
185#else
186#define PROFILE_START
187#define PROFILE_END
188#endif
189
191#define SCARD_PROTOCOL_ANY_OLD 0x1000
192
193static pthread_mutex_t LockMutex = PTHREAD_MUTEX_INITIALIZER;
194
195LONG SCardEstablishContext(DWORD dwScope, /*@unused@*/ LPCVOID pvReserved1,
196 /*@unused@*/ LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
197{
198 (void)pvReserved1;
199 (void)pvReserved2;
200
201 if (dwScope != SCARD_SCOPE_USER && dwScope != SCARD_SCOPE_TERMINAL &&
202 dwScope != SCARD_SCOPE_SYSTEM && dwScope != SCARD_SCOPE_GLOBAL)
203 {
204 *phContext = 0;
206 }
207
208 /*
209 * Unique identifier for this server so that it can uniquely be
210 * identified by clients and distinguished from others
211 */
212
213 *phContext = SYS_RandomInt();
214
215 Log2(PCSC_LOG_DEBUG, "Establishing Context: 0x%lX", *phContext);
216
217 return SCARD_S_SUCCESS;
218}
219
220LONG SCardReleaseContext(SCARDCONTEXT hContext)
221{
222 /*
223 * Nothing to do here RPC layer will handle this
224 */
225#ifdef NO_LOG
226 (void)hContext;
227#endif
228
229 Log2(PCSC_LOG_DEBUG, "Releasing Context: 0x%lX", hContext);
230
231 return SCARD_S_SUCCESS;
232}
233
234LONG SCardConnect(/*@unused@*/ SCARDCONTEXT hContext, LPCSTR szReader,
235 DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
236 LPDWORD pdwActiveProtocol)
237{
238 LONG rv;
239 READER_CONTEXT * rContext = NULL;
240
241 (void)hContext;
242 PROFILE_START
243
244 *phCard = 0;
245
246 if ((dwShareMode != SCARD_SHARE_DIRECT) &&
247 !(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
248 !(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
249 !(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
250 !(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD))
252
253 if (dwShareMode != SCARD_SHARE_EXCLUSIVE &&
254 dwShareMode != SCARD_SHARE_SHARED &&
255 dwShareMode != SCARD_SHARE_DIRECT)
257
258 Log3(PCSC_LOG_DEBUG, "Attempting Connect to %s using protocol: %ld",
259 szReader, dwPreferredProtocols);
260
261 rv = RFReaderInfo((LPSTR) szReader, &rContext);
262 if (rv != SCARD_S_SUCCESS)
263 {
264 Log2(PCSC_LOG_ERROR, "Reader %s Not Found", szReader);
265 return rv;
266 }
267
268 /*
269 * Make sure the reader is working properly
270 */
271 rv = RFCheckReaderStatus(rContext);
272 if (rv != SCARD_S_SUCCESS)
273 goto exit;
274
275 /*******************************************
276 *
277 * This section checks for simple errors
278 *
279 *******************************************/
280
281 /*
282 * Connect if not exclusive mode
283 */
285 {
286 Log1(PCSC_LOG_ERROR, "Error Reader Exclusive");
288 goto exit;
289 }
290
291 /*
292 * wait until a possible transaction is finished
293 */
294 if (rContext->hLockId != 0)
295 {
296 Log1(PCSC_LOG_INFO, "Waiting for release of lock");
297 while (rContext->hLockId != 0)
299 Log1(PCSC_LOG_INFO, "Lock released");
300 }
301
302 /*******************************************
303 *
304 * This section tries to determine the
305 * presence of a card or not
306 *
307 *******************************************/
308 if (dwShareMode != SCARD_SHARE_DIRECT)
309 {
310 if (!(rContext->readerState->readerState & SCARD_PRESENT))
311 {
312 Log1(PCSC_LOG_DEBUG, "Card Not Inserted");
314 goto exit;
315 }
316
317 /* Power on (again) the card if needed */
318 (void)pthread_mutex_lock(&rContext->powerState_lock);
319 if (POWER_STATE_UNPOWERED == rContext->powerState)
320 {
321 DWORD dwAtrLen;
322
323 dwAtrLen = sizeof(rContext->readerState->cardAtr);
324 rv = IFDPowerICC(rContext, IFD_POWER_UP,
325 rContext->readerState->cardAtr, &dwAtrLen);
326 rContext->readerState->cardAtrLength = dwAtrLen;
327
328 if (rv == IFD_SUCCESS)
329 {
331
332 Log1(PCSC_LOG_DEBUG, "power up complete.");
333 LogXxd(PCSC_LOG_DEBUG, "Card ATR: ",
334 rContext->readerState->cardAtr,
335 rContext->readerState->cardAtrLength);
336 }
337 else
338 Log2(PCSC_LOG_ERROR, "Error powering up card: %s",
339 rv2text(rv));
340 }
341
342 if (! (rContext->readerState->readerState & SCARD_POWERED))
343 {
344 Log1(PCSC_LOG_ERROR, "Card Not Powered");
345 (void)pthread_mutex_unlock(&rContext->powerState_lock);
347 goto exit;
348 }
349
350 /* the card is now in use */
351 rContext->powerState = POWER_STATE_IN_USE;
352 Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_IN_USE");
353 (void)pthread_mutex_unlock(&rContext->powerState_lock);
354 }
355
356 /*******************************************
357 *
358 * This section tries to decode the ATR
359 * and set up which protocol to use
360 *
361 *******************************************/
362 if (dwPreferredProtocols & SCARD_PROTOCOL_RAW)
364 else
365 {
366 if (dwShareMode != SCARD_SHARE_DIRECT)
367 {
368 /* lock here instead in IFDSetPTS() to lock up to
369 * setting rContext->readerState->cardProtocol */
370 (void)pthread_mutex_lock(rContext->mMutex);
371
372 /* the protocol is not yet set (no PPS yet) */
374 {
375 int availableProtocols, defaultProtocol;
376 int ret;
377
378 ATRDecodeAtr(&availableProtocols, &defaultProtocol,
379 rContext->readerState->cardAtr,
380 rContext->readerState->cardAtrLength);
381
382 /* If it is set to ANY let it do any of the protocols */
383 if (dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD)
384 dwPreferredProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
385
386 ret = PHSetProtocol(rContext, dwPreferredProtocols,
387 availableProtocols, defaultProtocol);
388
389 /* keep cardProtocol = SCARD_PROTOCOL_UNDEFINED in case of error */
390 if (SET_PROTOCOL_PPS_FAILED == ret)
391 {
392 (void)pthread_mutex_unlock(rContext->mMutex);
394 goto exit;
395 }
396
397 if (SET_PROTOCOL_WRONG_ARGUMENT == ret)
398 {
399 (void)pthread_mutex_unlock(rContext->mMutex);
401 goto exit;
402 }
403
404 /* use negotiated protocol */
405 rContext->readerState->cardProtocol = ret;
406
407 (void)pthread_mutex_unlock(rContext->mMutex);
408 }
409 else
410 {
411 (void)pthread_mutex_unlock(rContext->mMutex);
412
413 if (! (dwPreferredProtocols & rContext->readerState->cardProtocol))
414 {
416 goto exit;
417 }
418 }
419 }
420 }
421
422 *pdwActiveProtocol = rContext->readerState->cardProtocol;
423
424 if (dwShareMode != SCARD_SHARE_DIRECT)
425 {
426 switch (*pdwActiveProtocol)
427 {
430 Log2(PCSC_LOG_DEBUG, "Active Protocol: T=%d",
431 (*pdwActiveProtocol == SCARD_PROTOCOL_T0) ? 0 : 1);
432 break;
433
435 Log1(PCSC_LOG_DEBUG, "Active Protocol: RAW");
436 break;
437
438 default:
439 Log2(PCSC_LOG_ERROR, "Active Protocol: unknown %ld",
440 *pdwActiveProtocol);
441 }
442 }
443 else
444 Log1(PCSC_LOG_DEBUG, "Direct access: no protocol selected");
445
446 /*
447 * Prepare the SCARDHANDLE identity
448 */
449
450 /* we need a lock to avoid concurent generation of handles leading
451 * to a possible hCard handle duplication */
452 (void)pthread_mutex_lock(&LockMutex);
453
454 *phCard = RFCreateReaderHandle(rContext);
455
456 Log2(PCSC_LOG_DEBUG, "hCard Identity: %lx", *phCard);
457
458 /*******************************************
459 *
460 * This section tries to set up the
461 * exclusivity modes. -1 is exclusive
462 *
463 *******************************************/
464
465 if (dwShareMode == SCARD_SHARE_EXCLUSIVE)
466 {
467 if (rContext->contexts == PCSCLITE_SHARING_NO_CONTEXT)
468 {
470 (void)RFLockSharing(*phCard, rContext);
471 }
472 else
473 {
474 *phCard = 0;
476 (void)pthread_mutex_unlock(&LockMutex);
477 goto exit;
478 }
479 }
480 else
481 {
482 /*
483 * Add a connection to the context stack
484 */
485 rContext->contexts += 1;
486 }
487
488 /*
489 * Add this handle to the handle list
490 */
491 rv = RFAddReaderHandle(rContext, *phCard);
492
493 (void)pthread_mutex_unlock(&LockMutex);
494
495 if (rv != SCARD_S_SUCCESS)
496 {
497 /*
498 * Clean up - there is no more room
499 */
502 else
504 rContext->contexts -= 1;
505
506 *phCard = 0;
507
509 goto exit;
510 }
511
512 /*
513 * Propagate new state to reader state
514 */
515 rContext->readerState->readerSharing = rContext->contexts;
516
517exit:
518 UNREF_READER(rContext)
519
520 PROFILE_END
521
522 return rv;
523}
524
525LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
526 DWORD dwPreferredProtocols, DWORD dwInitialization,
527 LPDWORD pdwActiveProtocol)
528{
529 LONG rv;
530 READER_CONTEXT * rContext = NULL;
531
532 Log1(PCSC_LOG_DEBUG, "Attempting reconnect to token.");
533
534 if (hCard == 0)
536
537 /*
538 * Handle the dwInitialization
539 */
540 if (dwInitialization != SCARD_LEAVE_CARD &&
541 dwInitialization != SCARD_RESET_CARD &&
542 dwInitialization != SCARD_UNPOWER_CARD)
544
545 if (dwShareMode != SCARD_SHARE_SHARED &&
546 dwShareMode != SCARD_SHARE_EXCLUSIVE &&
547 dwShareMode != SCARD_SHARE_DIRECT)
549
550 if ((dwShareMode != SCARD_SHARE_DIRECT) &&
551 !(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
552 !(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
553 !(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
554 !(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD))
556
557 /* get rContext corresponding to hCard */
558 rv = RFReaderInfoById(hCard, &rContext);
559 if (rv != SCARD_S_SUCCESS)
560 return rv;
561
562 /*
563 * Make sure the reader is working properly
564 */
565 rv = RFCheckReaderStatus(rContext);
566 if (rv != SCARD_S_SUCCESS)
567 goto exit;
568
569 /*
570 * Make sure no one has a lock on this reader
571 */
572 rv = RFCheckSharing(hCard, rContext);
573 if (rv != SCARD_S_SUCCESS)
574 goto exit;
575
576 if (dwInitialization == SCARD_RESET_CARD ||
577 dwInitialization == SCARD_UNPOWER_CARD)
578 {
579 DWORD dwAtrLen;
580
581 /*
582 * Notify the card has been reset
583 */
584 RFSetReaderEventState(rContext, SCARD_RESET);
585
586 dwAtrLen = sizeof(rContext->readerState->cardAtr);
587 if (SCARD_RESET_CARD == dwInitialization)
588 rv = IFDPowerICC(rContext, IFD_RESET,
589 rContext->readerState->cardAtr, &dwAtrLen);
590 else
591 {
592 IFDPowerICC(rContext, IFD_POWER_DOWN, NULL, NULL);
593 rv = IFDPowerICC(rContext, IFD_POWER_UP,
594 rContext->readerState->cardAtr, &dwAtrLen);
595 }
596
597 /* the protocol is unset after a power on */
599
600 /*
601 * Set up the status bit masks on readerState
602 */
603 if (rv == IFD_SUCCESS)
604 {
605 rContext->readerState->cardAtrLength = dwAtrLen;
606 rContext->readerState->readerState =
608
609 Log1(PCSC_LOG_DEBUG, "Reset complete.");
610 LogXxd(PCSC_LOG_DEBUG, "Card ATR: ",
611 rContext->readerState->cardAtr,
612 rContext->readerState->cardAtrLength);
613 }
614 else
615 {
616 rContext->readerState->cardAtrLength = 0;
617 Log1(PCSC_LOG_ERROR, "Error resetting card.");
618
619 if (rv == SCARD_W_REMOVED_CARD)
620 {
623 goto exit;
624 }
625 else
626 {
627 rContext->readerState->readerState =
630 goto exit;
631 }
632 }
633 }
634 else
635 if (dwInitialization == SCARD_LEAVE_CARD)
636 {
637 uint32_t readerState = rContext->readerState->readerState;
638
639 if (readerState & SCARD_ABSENT)
640 {
642 goto exit;
643 }
644
645 if ((readerState & SCARD_PRESENT)
646 && (readerState & SCARD_SWALLOWED))
647 {
649 goto exit;
650 }
651 }
652
653 /*******************************************
654 *
655 * This section tries to decode the ATR
656 * and set up which protocol to use
657 *
658 *******************************************/
659 if (dwPreferredProtocols & SCARD_PROTOCOL_RAW)
661 else
662 {
663 if (dwShareMode != SCARD_SHARE_DIRECT)
664 {
665 /* lock here instead in IFDSetPTS() to lock up to
666 * setting rContext->readerState->cardProtocol */
667 (void)pthread_mutex_lock(rContext->mMutex);
668
669 /* the protocol is not yet set (no PPS yet) */
671 {
672 int availableProtocols, defaultProtocol;
673 int ret;
674
675 ATRDecodeAtr(&availableProtocols, &defaultProtocol,
676 rContext->readerState->cardAtr,
677 rContext->readerState->cardAtrLength);
678
679 /* If it is set to ANY let it do any of the protocols */
680 if (dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD)
681 dwPreferredProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
682
683 ret = PHSetProtocol(rContext, dwPreferredProtocols,
684 availableProtocols, defaultProtocol);
685
686 /* keep cardProtocol = SCARD_PROTOCOL_UNDEFINED in case of error */
687 if (SET_PROTOCOL_PPS_FAILED == ret)
688 {
689 (void)pthread_mutex_unlock(rContext->mMutex);
691 goto exit;
692 }
693
694 if (SET_PROTOCOL_WRONG_ARGUMENT == ret)
695 {
696 (void)pthread_mutex_unlock(rContext->mMutex);
698 goto exit;
699 }
700
701 /* use negotiated protocol */
702 rContext->readerState->cardProtocol = ret;
703
704 (void)pthread_mutex_unlock(rContext->mMutex);
705 }
706 else
707 {
708 (void)pthread_mutex_unlock(rContext->mMutex);
709
710 if (! (dwPreferredProtocols & rContext->readerState->cardProtocol))
711 {
713 goto exit;
714 }
715 }
716
717 /* the card is now in use */
718 RFSetPowerState(rContext, POWER_STATE_IN_USE);
719 Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_IN_USE");
720 }
721 }
722
723 *pdwActiveProtocol = rContext->readerState->cardProtocol;
724
725 if (dwShareMode != SCARD_SHARE_DIRECT)
726 {
727 switch (*pdwActiveProtocol)
728 {
731 Log2(PCSC_LOG_DEBUG, "Active Protocol: T=%d",
732 (*pdwActiveProtocol == SCARD_PROTOCOL_T0) ? 0 : 1);
733 break;
734
736 Log1(PCSC_LOG_DEBUG, "Active Protocol: RAW");
737 break;
738
739 default:
740 Log2(PCSC_LOG_ERROR, "Active Protocol: unknown %ld",
741 *pdwActiveProtocol);
742 }
743 }
744 else
745 Log1(PCSC_LOG_DEBUG, "Direct access: no protocol selected");
746
747 if (dwShareMode == SCARD_SHARE_EXCLUSIVE)
748 {
750 {
751 /*
752 * Do nothing - we are already exclusive
753 */
754 }
755 else
756 {
758 {
760 (void)RFLockSharing(hCard, rContext);
761 }
762 else
763 {
765 goto exit;
766 }
767 }
768 }
769 else if (dwShareMode == SCARD_SHARE_SHARED)
770 {
772 {
773 /*
774 * Do nothing - in sharing mode already
775 */
776 }
777 else
778 {
779 /*
780 * We are in exclusive mode but want to share now
781 */
782 (void)RFUnlockSharing(hCard, rContext);
784 }
785 }
786 else if (dwShareMode == SCARD_SHARE_DIRECT)
787 {
789 {
790 /*
791 * Do nothing - in sharing mode already
792 */
793 }
794 else
795 {
796 /*
797 * We are in exclusive mode but want to share now
798 */
799 (void)RFUnlockSharing(hCard, rContext);
801 }
802 }
803 else
804 {
806 goto exit;
807 }
808
809 /*
810 * Clear a previous event to the application
811 */
812 (void)RFClearReaderEventState(rContext, hCard);
813
814 /*
815 * Propagate new state to reader state
816 */
817 rContext->readerState->readerSharing = rContext->contexts;
818
819 rv = SCARD_S_SUCCESS;
820
821exit:
822 UNREF_READER(rContext)
823
824 return rv;
825}
826
827LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
828{
829 LONG rv;
830 READER_CONTEXT * rContext = NULL;
831
832 if (hCard == 0)
834
835 if ((dwDisposition != SCARD_LEAVE_CARD)
836 && (dwDisposition != SCARD_UNPOWER_CARD)
837 && (dwDisposition != SCARD_RESET_CARD)
838 && (dwDisposition != SCARD_EJECT_CARD))
840
841 /* get rContext corresponding to hCard */
842 rv = RFReaderInfoById(hCard, &rContext);
843 /* ignore reader removal */
845 return SCARD_S_SUCCESS;
846 if (rv != SCARD_S_SUCCESS)
847 return rv;
848
849 /*
850 * wait until a possible transaction is finished
851 */
852 if ((dwDisposition != SCARD_LEAVE_CARD) && (rContext->hLockId != 0)
853 && (rContext->hLockId != hCard))
854 {
855 Log1(PCSC_LOG_INFO, "Waiting for release of lock");
856 while (rContext->hLockId != 0)
858 Log1(PCSC_LOG_INFO, "Lock released");
859 }
860
861 /*
862 * Try to unlock any blocks on this context
863 *
864 * This may fail with SCARD_E_SHARING_VIOLATION if a transaction is
865 * on going on another card context and dwDisposition == SCARD_LEAVE_CARD.
866 * We should not stop.
867 */
868 rv = RFUnlockAllSharing(hCard, rContext);
869 if (rv != SCARD_S_SUCCESS)
870 {
872 {
873 goto exit;
874 }
875 else
876 {
877 if (SCARD_LEAVE_CARD != dwDisposition)
878 goto exit;
879 }
880 }
881
882 Log2(PCSC_LOG_DEBUG, "Active Contexts: %d", rContext->contexts);
883 Log2(PCSC_LOG_DEBUG, "dwDisposition: %ld", dwDisposition);
884
885 if (dwDisposition == SCARD_RESET_CARD ||
886 dwDisposition == SCARD_UNPOWER_CARD)
887 {
888 DWORD dwAtrLen;
889
890 /*
891 * Notify the card has been reset
892 */
893 RFSetReaderEventState(rContext, SCARD_RESET);
894
895 dwAtrLen = sizeof(rContext->readerState->cardAtr);
896 if (SCARD_RESET_CARD == dwDisposition)
897 rv = IFDPowerICC(rContext, IFD_RESET,
898 rContext->readerState->cardAtr, &dwAtrLen);
899 else
900 {
901 /* SCARD_UNPOWER_CARD */
902 rv = IFDPowerICC(rContext, IFD_POWER_DOWN, NULL, NULL);
903
904 RFSetPowerState(rContext, POWER_STATE_UNPOWERED);
905 Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_UNPOWERED");
906 }
907
908 /* the protocol is unset after a power on */
910
911 if (rv == IFD_SUCCESS)
912 {
913 if (SCARD_UNPOWER_CARD == dwDisposition)
915 else
916 {
917 rContext->readerState->cardAtrLength = dwAtrLen;
918 rContext->readerState->readerState =
920
921 Log1(PCSC_LOG_DEBUG, "Reset complete.");
922 LogXxd(PCSC_LOG_DEBUG, "Card ATR: ",
923 rContext->readerState->cardAtr,
924 rContext->readerState->cardAtrLength);
925 }
926 }
927 else
928 {
929 if (SCARD_UNPOWER_CARD == dwDisposition)
930 Log2(PCSC_LOG_ERROR, "Error powering down card: %s",
931 rv2text(rv));
932 else
933 {
934 rContext->readerState->cardAtrLength = 0;
935 Log1(PCSC_LOG_ERROR, "Error resetting card.");
936 }
937
938 if (rv == SCARD_W_REMOVED_CARD)
940 else
941 rContext->readerState->readerState =
943 }
944 }
945 else if (dwDisposition == SCARD_EJECT_CARD)
946 {
947 UCHAR controlBuffer[5];
948 UCHAR receiveBuffer[MAX_BUFFER_SIZE];
949 DWORD receiveLength;
950
951 /*
952 * Set up the CTBCS command for Eject ICC
953 */
954 controlBuffer[0] = 0x20;
955 controlBuffer[1] = 0x15;
956 controlBuffer[2] = (rContext->slot & 0x0000FFFF) + 1;
957 controlBuffer[3] = 0x00;
958 controlBuffer[4] = 0x00;
959 receiveLength = 2;
960 rv = IFDControl_v2(rContext, controlBuffer, 5, receiveBuffer,
961 &receiveLength);
962
963 if (rv == SCARD_S_SUCCESS)
964 {
965 if (receiveLength == 2 && receiveBuffer[0] == 0x90)
966 {
967 Log1(PCSC_LOG_DEBUG, "Card ejected successfully.");
968 /*
969 * Successful
970 */
971 }
972 else
973 Log1(PCSC_LOG_ERROR, "Error ejecting card.");
974 }
975 else
976 Log1(PCSC_LOG_ERROR, "Error ejecting card.");
977
978 }
979 else if (dwDisposition == SCARD_LEAVE_CARD)
980 {
981 /*
982 * Do nothing
983 */
984 }
985
986 /*
987 * Remove and destroy this handle
988 */
989 (void)RFRemoveReaderHandle(rContext, hCard);
990
991 /*
992 * For exclusive connection reset it to no connections
993 */
996 else
997 {
998 /*
999 * Remove a connection from the context stack
1000 */
1001 rContext->contexts -= 1;
1002
1003 if (rContext->contexts < 0)
1004 rContext->contexts = 0;
1005 }
1006
1007 if (PCSCLITE_SHARING_NO_CONTEXT == rContext->contexts)
1008 {
1009 RESPONSECODE (*fct)(DWORD) = NULL;
1010 DWORD dwGetSize;
1011
1012 (void)pthread_mutex_lock(&rContext->powerState_lock);
1013 /* Switch to POWER_STATE_GRACE_PERIOD unless the card was not
1014 * powered */
1015 if (POWER_STATE_POWERED <= rContext->powerState)
1016 {
1018 Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_GRACE_PERIOD");
1019 }
1020
1021 (void)pthread_mutex_unlock(&rContext->powerState_lock);
1022
1023 /* ask to stop the "polling" thread so it can be restarted using
1024 * the correct timeout */
1025 dwGetSize = sizeof(fct);
1027 &dwGetSize, (PUCHAR)&fct);
1028
1029 if ((IFD_SUCCESS == rv) && (dwGetSize == sizeof(fct)))
1030 {
1031 Log1(PCSC_LOG_INFO, "Stopping polling thread");
1032 fct(rContext->slot);
1033 }
1034 }
1035
1036 /*
1037 * Propagate new state to reader state
1038 */
1039 rContext->readerState->readerSharing = rContext->contexts;
1040
1041 rv = SCARD_S_SUCCESS;
1042
1043exit:
1044 UNREF_READER(rContext)
1045
1046 return rv;
1047}
1048
1049LONG SCardBeginTransaction(SCARDHANDLE hCard)
1050{
1051 LONG rv;
1052 READER_CONTEXT * rContext;
1053
1054 if (hCard == 0)
1056
1057 /* get rContext corresponding to hCard */
1058 rv = RFReaderInfoById(hCard, &rContext);
1059 if (rv != SCARD_S_SUCCESS)
1060 return rv;
1061
1062 /*
1063 * Make sure the reader is working properly
1064 */
1065 rv = RFCheckReaderStatus(rContext);
1066 if (rv != SCARD_S_SUCCESS)
1067 goto exit;
1068
1069 /*
1070 * Make sure some event has not occurred
1071 */
1072 rv = RFCheckReaderEventState(rContext, hCard);
1073 if (rv != SCARD_S_SUCCESS)
1074 goto exit;
1075
1076 rv = RFLockSharing(hCard, rContext);
1077
1078 /* if the transaction is not yet ready we sleep a bit so the client
1079 * do not retry immediately */
1080 if (SCARD_E_SHARING_VIOLATION == rv)
1082
1083 Log2(PCSC_LOG_DEBUG, "Status: %s", rv2text(rv));
1084
1085exit:
1086 UNREF_READER(rContext)
1087
1088 return rv;
1089}
1090
1091LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
1092{
1093 LONG rv;
1094 LONG rv2;
1095 READER_CONTEXT * rContext = NULL;
1096
1097 /*
1098 * Ignoring dwDisposition for now
1099 */
1100 if (hCard == 0)
1102
1103 if ((dwDisposition != SCARD_LEAVE_CARD)
1104 && (dwDisposition != SCARD_UNPOWER_CARD)
1105 && (dwDisposition != SCARD_RESET_CARD)
1106 && (dwDisposition != SCARD_EJECT_CARD))
1107 return SCARD_E_INVALID_VALUE;
1108
1109 /* get rContext corresponding to hCard */
1110 rv = RFReaderInfoById(hCard, &rContext);
1111 if (rv != SCARD_S_SUCCESS)
1112 return rv;
1113
1114 /*
1115 * Make sure some event has not occurred
1116 */
1117 rv = RFCheckReaderEventState(rContext, hCard);
1118 if (rv != SCARD_S_SUCCESS)
1119 goto exit;
1120
1121 /*
1122 * Error if another transaction is ongoing and a card action is
1123 * requested
1124 */
1125 if ((dwDisposition != SCARD_LEAVE_CARD) && (rContext->hLockId != 0)
1126 && (rContext->hLockId != hCard))
1127 {
1128 Log1(PCSC_LOG_INFO, "No card reset within a transaction");
1130 goto exit;
1131 }
1132
1133 if (dwDisposition == SCARD_RESET_CARD ||
1134 dwDisposition == SCARD_UNPOWER_CARD)
1135 {
1136 DWORD dwAtrLen;
1137
1138 dwAtrLen = sizeof(rContext->readerState->cardAtr);
1139 if (SCARD_RESET_CARD == dwDisposition)
1140 rv = IFDPowerICC(rContext, IFD_RESET,
1141 rContext->readerState->cardAtr, &dwAtrLen);
1142 else
1143 {
1144 IFDPowerICC(rContext, IFD_POWER_DOWN, NULL, NULL);
1145 rv = IFDPowerICC(rContext, IFD_POWER_UP,
1146 rContext->readerState->cardAtr, &dwAtrLen);
1147 }
1148
1149 /* the protocol is unset after a power on */
1151
1152 /*
1153 * Notify the card has been reset
1154 */
1155 RFSetReaderEventState(rContext, SCARD_RESET);
1156
1157 /*
1158 * Set up the status bit masks on readerState
1159 */
1160 if (rv == IFD_SUCCESS)
1161 {
1162 rContext->readerState->cardAtrLength = dwAtrLen;
1163 rContext->readerState->readerState =
1165
1166 Log1(PCSC_LOG_DEBUG, "Reset complete.");
1167 LogXxd(PCSC_LOG_DEBUG, "Card ATR: ",
1168 rContext->readerState->cardAtr,
1169 rContext->readerState->cardAtrLength);
1170 }
1171 else
1172 {
1173 rContext->readerState->cardAtrLength = 0;
1174 Log1(PCSC_LOG_ERROR, "Error resetting card.");
1175
1176 if (rv == SCARD_W_REMOVED_CARD)
1178 else
1179 rContext->readerState->readerState =
1181 }
1182 }
1183 else if (dwDisposition == SCARD_EJECT_CARD)
1184 {
1185 UCHAR controlBuffer[5];
1186 UCHAR receiveBuffer[MAX_BUFFER_SIZE];
1187 DWORD receiveLength;
1188
1189 /*
1190 * Set up the CTBCS command for Eject ICC
1191 */
1192 controlBuffer[0] = 0x20;
1193 controlBuffer[1] = 0x15;
1194 controlBuffer[2] = (rContext->slot & 0x0000FFFF) + 1;
1195 controlBuffer[3] = 0x00;
1196 controlBuffer[4] = 0x00;
1197 receiveLength = 2;
1198 rv = IFDControl_v2(rContext, controlBuffer, 5, receiveBuffer,
1199 &receiveLength);
1200
1201 if (rv == SCARD_S_SUCCESS)
1202 {
1203 if (receiveLength == 2 && receiveBuffer[0] == 0x90)
1204 {
1205 Log1(PCSC_LOG_DEBUG, "Card ejected successfully.");
1206 /*
1207 * Successful
1208 */
1209 }
1210 else
1211 Log1(PCSC_LOG_ERROR, "Error ejecting card.");
1212 }
1213 else
1214 Log1(PCSC_LOG_ERROR, "Error ejecting card.");
1215
1216 }
1217 else if (dwDisposition == SCARD_LEAVE_CARD)
1218 {
1219 /*
1220 * Do nothing
1221 */
1222 }
1223
1224 /*
1225 * Unlock any blocks on this context
1226 */
1227 /* we do not want to lose the previous rv value
1228 * So we use another variable */
1229 rv2 = RFUnlockSharing(hCard, rContext);
1230 if (rv2 != SCARD_S_SUCCESS)
1231 /* if rv is already in error then do not change its value */
1232 if (rv == SCARD_S_SUCCESS)
1233 rv = rv2;
1234
1235 Log2(PCSC_LOG_DEBUG, "Status: %s", rv2text(rv));
1236
1237exit:
1238 UNREF_READER(rContext)
1239
1240 return rv;
1241}
1242
1243LONG SCardStatus(SCARDHANDLE hCard, LPSTR szReaderNames,
1244 LPDWORD pcchReaderLen, LPDWORD pdwState,
1245 LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
1246{
1247 LONG rv;
1248 READER_CONTEXT * rContext = NULL;
1249
1250 /* These parameters are not used by the client
1251 * Client side code uses readerStates[] instead */
1252 (void)szReaderNames;
1253 (void)pcchReaderLen;
1254 (void)pdwState;
1255 (void)pdwProtocol;
1256 (void)pbAtr;
1257 (void)pcbAtrLen;
1258
1259 if (hCard == 0)
1261
1262 /* get rContext corresponding to hCard */
1263 rv = RFReaderInfoById(hCard, &rContext);
1264 if (rv != SCARD_S_SUCCESS)
1265 return rv;
1266
1267 /*
1268 * Make sure no one has a lock on this reader
1269 */
1270 rv = RFCheckSharing(hCard, rContext);
1271 if (rv != SCARD_S_SUCCESS)
1272 goto exit;
1273
1274 if (rContext->readerState->cardAtrLength > MAX_ATR_SIZE)
1275 {
1277 goto exit;
1278 }
1279
1280 /*
1281 * This is a client side function however the server maintains the
1282 * list of events between applications so it must be passed through to
1283 * obtain this event if it has occurred
1284 */
1285
1286 /*
1287 * Make sure some event has not occurred
1288 */
1289 rv = RFCheckReaderEventState(rContext, hCard);
1290 if (rv != SCARD_S_SUCCESS)
1291 goto exit;
1292
1293 /*
1294 * Make sure the reader is working properly
1295 */
1296 rv = RFCheckReaderStatus(rContext);
1297 if (rv != SCARD_S_SUCCESS)
1298 goto exit;
1299
1300exit:
1301 UNREF_READER(rContext)
1302
1303 return rv;
1304}
1305
1306LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode,
1307 LPCVOID pbSendBuffer, DWORD cbSendLength,
1308 LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned)
1309{
1310 LONG rv;
1311 READER_CONTEXT * rContext = NULL;
1312
1313 /* 0 bytes returned by default */
1314 *lpBytesReturned = 0;
1315
1316 if (0 == hCard)
1318
1319 /* get rContext corresponding to hCard */
1320 rv = RFReaderInfoById(hCard, &rContext);
1321 if (rv != SCARD_S_SUCCESS)
1322 return rv;
1323
1324 /*
1325 * Make sure no one has a lock on this reader
1326 */
1327 rv = RFCheckSharing(hCard, rContext);
1328 if (rv != SCARD_S_SUCCESS)
1329 goto exit;
1330
1331 if (IFD_HVERSION_2_0 == rContext->version)
1332 if (NULL == pbSendBuffer || 0 == cbSendLength)
1333 {
1335 goto exit;
1336 }
1337
1338 /*
1339 * Make sure the reader is working properly
1340 */
1341 rv = RFCheckReaderStatus(rContext);
1342 if (rv != SCARD_S_SUCCESS)
1343 goto exit;
1344
1345 if (IFD_HVERSION_2_0 == rContext->version)
1346 {
1347 /* we must wrap a API 3.0 client in an API 2.0 driver */
1348 *lpBytesReturned = cbRecvLength;
1349 rv = IFDControl_v2(rContext, (PUCHAR)pbSendBuffer,
1350 cbSendLength, pbRecvBuffer, lpBytesReturned);
1351 }
1352 else
1353 if (IFD_HVERSION_3_0 == rContext->version)
1354 rv = IFDControl(rContext, dwControlCode, pbSendBuffer,
1355 cbSendLength, pbRecvBuffer, cbRecvLength, lpBytesReturned);
1356 else
1358
1359exit:
1360 UNREF_READER(rContext)
1361
1362 return rv;
1363}
1364
1365LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId,
1366 LPBYTE pbAttr, LPDWORD pcbAttrLen)
1367{
1368 LONG rv;
1369 READER_CONTEXT * rContext = NULL;
1370
1371 if (0 == hCard)
1373
1374 /* get rContext corresponding to hCard */
1375 rv = RFReaderInfoById(hCard, &rContext);
1376 if (rv != SCARD_S_SUCCESS)
1377 return rv;
1378
1379 /*
1380 * Make sure no one has a lock on this reader
1381 */
1382 rv = RFCheckSharing(hCard, rContext);
1383 if (rv != SCARD_S_SUCCESS)
1384 goto exit;
1385
1386 /*
1387 * Make sure the reader is working properly
1388 */
1389 rv = RFCheckReaderStatus(rContext);
1390 if (rv != SCARD_S_SUCCESS)
1391 goto exit;
1392
1393 /*
1394 * Make sure some event has not occurred
1395 */
1396 rv = RFCheckReaderEventState(rContext, hCard);
1397 if (rv != SCARD_S_SUCCESS)
1398 goto exit;
1399
1400 rv = IFDGetCapabilities(rContext, dwAttrId, pcbAttrLen, pbAttr);
1401 switch(rv)
1402 {
1403 case IFD_SUCCESS:
1404 rv = SCARD_S_SUCCESS;
1405 break;
1406 case IFD_ERROR_TAG:
1407 /* Special case SCARD_ATTR_DEVICE_FRIENDLY_NAME as it is better
1408 * implemented in pcscd (it knows the friendly name)
1409 */
1410 if ((SCARD_ATTR_DEVICE_FRIENDLY_NAME == dwAttrId)
1411 || (SCARD_ATTR_DEVICE_SYSTEM_NAME == dwAttrId))
1412 {
1413 unsigned int len = strlen(rContext->readerState->readerName)+1;
1414
1415 if (len > *pcbAttrLen)
1417 else
1418 {
1419 strcpy((char *)pbAttr, rContext->readerState->readerName);
1420 rv = SCARD_S_SUCCESS;
1421 }
1422 *pcbAttrLen = len;
1423 }
1424 else
1426 break;
1429 break;
1430 default:
1432 }
1433
1434exit:
1435 UNREF_READER(rContext)
1436
1437 return rv;
1438}
1439
1440LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId,
1441 LPCBYTE pbAttr, DWORD cbAttrLen)
1442{
1443 LONG rv;
1444 READER_CONTEXT * rContext = NULL;
1445
1446 if (0 == hCard)
1448
1449 /* get rContext corresponding to hCard */
1450 rv = RFReaderInfoById(hCard, &rContext);
1451 if (rv != SCARD_S_SUCCESS)
1452 return rv;
1453
1454 /*
1455 * Make sure no one has a lock on this reader
1456 */
1457 rv = RFCheckSharing(hCard, rContext);
1458 if (rv != SCARD_S_SUCCESS)
1459 goto exit;
1460
1461 /*
1462 * Make sure the reader is working properly
1463 */
1464 rv = RFCheckReaderStatus(rContext);
1465 if (rv != SCARD_S_SUCCESS)
1466 goto exit;
1467
1468 /*
1469 * Make sure some event has not occurred
1470 */
1471 rv = RFCheckReaderEventState(rContext, hCard);
1472 if (rv != SCARD_S_SUCCESS)
1473 goto exit;
1474
1475 rv = IFDSetCapabilities(rContext, dwAttrId, cbAttrLen, (PUCHAR)pbAttr);
1476 if (rv == IFD_SUCCESS)
1477 rv = SCARD_S_SUCCESS;
1478 else
1479 if (rv == IFD_ERROR_TAG)
1481 else
1483
1484exit:
1485 UNREF_READER(rContext)
1486
1487 return rv;
1488}
1489
1490LONG SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci,
1491 LPCBYTE pbSendBuffer, DWORD cbSendLength,
1492 SCARD_IO_REQUEST *pioRecvPci, LPBYTE pbRecvBuffer,
1493 LPDWORD pcbRecvLength)
1494{
1495 LONG rv;
1496 READER_CONTEXT * rContext = NULL;
1497 SCARD_IO_HEADER sSendPci, sRecvPci;
1498 DWORD dwRxLength, tempRxLength;
1499
1500 dwRxLength = *pcbRecvLength;
1501 *pcbRecvLength = 0;
1502
1503 if (hCard == 0)
1505
1506 /*
1507 * Must at least have 2 status words even for SCardControl
1508 */
1509 if (dwRxLength < 2)
1511
1512 /* get rContext corresponding to hCard */
1513 rv = RFReaderInfoById(hCard, &rContext);
1514 if (rv != SCARD_S_SUCCESS)
1515 return rv;
1516
1517 /*
1518 * Make sure no one has a lock on this reader
1519 */
1520 rv = RFCheckSharing(hCard, rContext);
1521 if (rv != SCARD_S_SUCCESS)
1522 goto exit;
1523
1524 /*
1525 * Make sure the reader is working properly
1526 */
1527 rv = RFCheckReaderStatus(rContext);
1528 if (rv != SCARD_S_SUCCESS)
1529 goto exit;
1530
1531 /*
1532 * Make sure some event has not occurred
1533 */
1534 rv = RFCheckReaderEventState(rContext, hCard);
1535 if (rv != SCARD_S_SUCCESS)
1536 goto exit;
1537
1538 /*
1539 * Check for some common errors
1540 */
1541 if (pioSendPci->dwProtocol != SCARD_PROTOCOL_RAW)
1542 {
1543 if (rContext->readerState->readerState & SCARD_ABSENT)
1544 {
1546 goto exit;
1547 }
1548 }
1549
1550 if (pioSendPci->dwProtocol != SCARD_PROTOCOL_RAW)
1551 {
1552 if (pioSendPci->dwProtocol != SCARD_PROTOCOL_ANY_OLD)
1553 {
1554 if (pioSendPci->dwProtocol != rContext->readerState->cardProtocol)
1555 {
1557 goto exit;
1558 }
1559 }
1560 }
1561
1562 /*
1563 * Quick fix: PC/SC starts at 1 for bit masking but the IFD_Handler
1564 * just wants 0 or 1
1565 */
1566
1567 sSendPci.Protocol = 0; /* protocol T=0 by default */
1568
1569 if (pioSendPci->dwProtocol == SCARD_PROTOCOL_T1)
1570 {
1571 sSendPci.Protocol = 1;
1572 } else if (pioSendPci->dwProtocol == SCARD_PROTOCOL_RAW)
1573 {
1574 /*
1575 * This is temporary ......
1576 */
1577 sSendPci.Protocol = SCARD_PROTOCOL_RAW;
1578 } else if (pioSendPci->dwProtocol == SCARD_PROTOCOL_ANY_OLD)
1579 {
1580 /* Fix by Amira (Athena) */
1581 unsigned long i;
1582 unsigned long prot = rContext->readerState->cardProtocol;
1583
1584 for (i = 0 ; prot != 1 && i < 16; i++)
1585 prot >>= 1;
1586
1587 sSendPci.Protocol = i;
1588 }
1589
1590 sSendPci.Length = pioSendPci->cbPciLength;
1591
1592 sRecvPci.Protocol = pioRecvPci->dwProtocol;
1593 sRecvPci.Length = pioRecvPci->cbPciLength;
1594
1595 /* the protocol number is decoded a few lines above */
1596 Log2(PCSC_LOG_DEBUG, "Send Protocol: T=%ld", sSendPci.Protocol);
1597
1598 tempRxLength = dwRxLength;
1599
1600 if ((pioSendPci->dwProtocol == SCARD_PROTOCOL_RAW)
1601 && (rContext->version == IFD_HVERSION_2_0))
1602 {
1603 rv = IFDControl_v2(rContext, (PUCHAR) pbSendBuffer, cbSendLength,
1604 pbRecvBuffer, &dwRxLength);
1605 } else
1606 {
1607 rv = IFDTransmit(rContext, sSendPci, (PUCHAR) pbSendBuffer,
1608 cbSendLength, pbRecvBuffer, &dwRxLength, &sRecvPci);
1609 }
1610
1611 pioRecvPci->dwProtocol = sRecvPci.Protocol;
1612 pioRecvPci->cbPciLength = sRecvPci.Length;
1613
1614 /*
1615 * Check for any errors that might have occurred
1616 */
1617
1618 if (rv != SCARD_S_SUCCESS)
1619 {
1620 *pcbRecvLength = 0;
1621 Log2(PCSC_LOG_ERROR, "Card not transacted: %s", rv2text(rv));
1622
1623 if (SCARD_E_NO_SMARTCARD == rv)
1624 {
1625 rContext->readerState->cardAtrLength = 0;
1628 }
1629
1630 goto exit;
1631 }
1632
1633 /*
1634 * Available is less than received
1635 */
1636 if (tempRxLength < dwRxLength)
1637 {
1638 *pcbRecvLength = 0;
1640 goto exit;
1641 }
1642
1643 /*
1644 * Successful return
1645 */
1646 *pcbRecvLength = dwRxLength;
1647
1648exit:
1649 UNREF_READER(rContext)
1650
1651 return rv;
1652}
1653
short ATRDecodeAtr(int *availableProtocols, int *currentProtocol, PUCHAR pucAtr, DWORD dwLength)
parse an ATR
Definition atrhandler.c:66
This keeps track of smart card protocols, timing issues and Answer to Reset ATR handling.
This handles debugging.
This handles card insertion/removal events, updates ATR, protocol, and status information.
#define PCSCLITE_SHARING_EXCLUSIVE_CONTEXT
Reader used in exclusive mode.
#define PCSCLITE_SHARING_NO_CONTEXT
No application is using the reader.
#define PCSCLITE_SHARING_LAST_CONTEXT
One application is using the reader.
#define SCARD_E_INVALID_HANDLE
The supplied handle was invalid.
Definition pcsclite.h:113
#define SCARD_F_INTERNAL_ERROR
An internal consistency check failed.
Definition pcsclite.h:109
#define SCARD_W_UNRESPONSIVE_CARD
The smart card is not responding to a reset.
Definition pcsclite.h:212
#define SCARD_E_PROTO_MISMATCH
The requested protocols are incompatible with the protocol currently in use with the smart card.
Definition pcsclite.h:137
#define SCARD_E_INVALID_PARAMETER
One or more of the supplied parameters could not be properly interpreted.
Definition pcsclite.h:115
#define SCARD_S_SUCCESS
No error was encountered.
Definition pcsclite.h:107
#define SCARD_E_SHARING_VIOLATION
The smart card cannot be accessed because of other connections outstanding.
Definition pcsclite.h:129
#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_INSUFFICIENT_BUFFER
The data buffer to receive returned data is too small for the returned data.
Definition pcsclite.h:123
#define SCARD_E_NO_SMARTCARD
The operation requires a Smart Card, but no Smart Card is currently in the device.
Definition pcsclite.h:131
#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
#define SCARD_W_UNPOWERED_CARD
Power has been removed from the smart card, so that further communication is not possible.
Definition pcsclite.h:214
#define SCARD_E_UNSUPPORTED_FEATURE
This smart card does not support the requested feature.
Definition pcsclite.h:171
#define IFD_POWER_UP
power up the card
Definition ifdhandler.h:343
#define IFD_ERROR_TAG
tag unknown
Definition ifdhandler.h:352
#define TAG_IFD_STOP_POLLING_THREAD
method used to stop the polling thread (instead of just pthread_kill())
Definition ifdhandler.h:329
#define IFD_POWER_DOWN
power down the card
Definition ifdhandler.h:344
#define IFD_RESET
warm reset
Definition ifdhandler.h:345
#define IFD_ERROR_INSUFFICIENT_BUFFER
buffer is too small
Definition ifdhandler.h:373
#define IFD_SUCCESS
no error
Definition ifdhandler.h:351
LONG IFDControl(READER_CONTEXT *rContext, DWORD ControlCode, LPCVOID TxBuffer, DWORD TxLength, LPVOID RxBuffer, DWORD RxLength, LPDWORD BytesReturned)
Provide a means for toggling a specific action on the reader such as swallow, eject,...
Definition ifdwrapper.c:442
RESPONSECODE IFDGetCapabilities(READER_CONTEXT *rContext, DWORD dwTag, PDWORD pdwLength, PUCHAR pucValue)
Get's capabilities in the reader.
Definition ifdwrapper.c:235
LONG IFDTransmit(READER_CONTEXT *rContext, SCARD_IO_HEADER pioTxPci, PUCHAR pucTxBuffer, DWORD dwTxLength, PUCHAR pucRxBuffer, PDWORD pdwRxLength, PSCARD_IO_HEADER pioRxPci)
Transmit an APDU to the ICC.
Definition ifdwrapper.c:502
RESPONSECODE IFDSetCapabilities(READER_CONTEXT *rContext, DWORD dwTag, DWORD dwLength, PUCHAR pucValue)
Set capabilities in the reader.
Definition ifdwrapper.c:204
RESPONSECODE IFDPowerICC(READER_CONTEXT *rContext, DWORD dwAction, PUCHAR pucAtr, PDWORD pdwAtrLen)
Power up/down or reset's an ICC located in the IFD.
Definition ifdwrapper.c:265
This wraps the dynamic ifdhandler functions.
This keeps a list of defines for pcsc-lite.
@ POWER_STATE_IN_USE
card is used
Definition pcscd.h:66
@ POWER_STATE_UNPOWERED
auto power off
Definition pcscd.h:63
@ POWER_STATE_GRACE_PERIOD
card was in use
Definition pcscd.h:65
#define SCARD_RESET
Card was reset.
Definition pcscd.h:41
#define PCSCLITE_LOCK_POLL_RATE
Lock polling rate.
Definition pcscd.h:54
#define SCARD_SCOPE_SYSTEM
Scope in system.
Definition pcsclite.h:236
#define SCARD_RESET_CARD
Reset on close.
Definition pcsclite.h:253
#define SCARD_SWALLOWED
Card not powered.
Definition pcsclite.h:260
LONG SCARDCONTEXT
hContext returned by SCardEstablishContext()
Definition pcsclite.h:52
#define SCARD_PROTOCOL_UNDEFINED
protocol not set
Definition pcsclite.h:239
#define SCARD_PROTOCOL_T1
T=1 active protocol.
Definition pcsclite.h:242
#define SCARD_SHARE_DIRECT
Raw mode only.
Definition pcsclite.h:250
#define SCARD_SCOPE_USER
Scope in user space.
Definition pcsclite.h:234
#define SCARD_SCOPE_GLOBAL
Scope is global.
Definition pcsclite.h:237
#define SCARD_PRESENT
Card is present.
Definition pcsclite.h:259
#define SCARD_PROTOCOL_T0
T=0 active protocol.
Definition pcsclite.h:241
#define SCARD_EJECT_CARD
Eject on close.
Definition pcsclite.h:255
#define SCARD_UNPOWER_CARD
Power down on close.
Definition pcsclite.h:254
#define SCARD_SHARE_SHARED
Shared mode only.
Definition pcsclite.h:249
#define SCARD_POWERED
Card is powered.
Definition pcsclite.h:261
#define MAX_ATR_SIZE
Maximum ATR size.
Definition pcsclite.h:59
#define SCARD_ABSENT
Card is absent.
Definition pcsclite.h:258
#define SCARD_SCOPE_TERMINAL
Scope in terminal.
Definition pcsclite.h:235
#define SCARD_PROTOCOL_RAW
Raw active protocol.
Definition pcsclite.h:243
#define SCARD_LEAVE_CARD
Do nothing on close.
Definition pcsclite.h:252
#define MAX_BUFFER_SIZE
Maximum Tx/Rx Buffer for short APDU.
Definition pcsclite.h:297
#define SCARD_SHARE_EXCLUSIVE
Exclusive mode only.
Definition pcsclite.h:248
#define SCARD_NEGOTIABLE
Ready for PTS.
Definition pcsclite.h:262
LONG SCARDHANDLE
hCard returned by SCardConnect()
Definition pcsclite.h:55
DWORD PHSetProtocol(struct ReaderContext *rContext, DWORD dwPreferred, UCHAR ucAvailable, UCHAR ucDefault)
Determine which protocol to use.
Definition prothandler.c:60
This handles protocol defaults, PTS, etc.
This keeps a list of defines shared between the driver and the application.
#define SCARD_ATTR_DEVICE_FRIENDLY_NAME
Reader's display name.
Definition reader.h:111
#define SCARD_ATTR_DEVICE_SYSTEM_NAME
Reader's system name.
Definition reader.h:112
This keeps track of a list of currently available reader structures.
pthread_mutex_t * mMutex
Mutex for this connection.
pthread_mutex_t powerState_lock
powerState mutex
_Atomic int32_t contexts
Number of open contexts.
int slot
Current Reader Slot.
_Atomic SCARDHANDLE hLockId
Lock Id.
int version
IFD Handler version number.
struct pubReaderStatesList * readerState
link to the reader state
int powerState
auto power off state
Protocol Control Information (PCI)
Definition pcsclite.h:80
unsigned long dwProtocol
Protocol identifier.
Definition pcsclite.h:81
unsigned long cbPciLength
Protocol Control Inf Length.
Definition pcsclite.h:82
Use by SCardTransmit()
Definition ifdhandler.h:311
char readerName[MAX_READERNAME]
reader name
int32_t readerSharing
PCSCLITE_SHARING_* sharing status.
uint32_t cardProtocol
SCARD_PROTOCOL_* value.
UCHAR cardAtr[MAX_ATR_SIZE]
ATR.
uint32_t readerState
SCARD_* bit field.
uint32_t cardAtrLength
ATR length.
This handles abstract system level calls.
int SYS_RandomInt(void)
Generate a pseudo random number.
Definition sys_unix.c:106
int SYS_USleep(int)
Makes the current process sleep for some microseconds.
Definition sys_unix.c:78
long int time_sub(struct timeval *a, struct timeval *b)
return the difference (as long int) in µs between 2 struct timeval r = a - b
Definition utils.c:138
#define SCARD_PROTOCOL_ANY_OLD
used for backward compatibility
Definition winscard.c:191
This handles smart card reader communications.