pcsc-lite 1.9.4
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(0, -1);
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 Log3(PCSC_LOG_ERROR, "Error powering up card: %ld 0x%04lX",
339 rv, 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 (void)pthread_mutex_lock(&rContext->powerState_lock);
719 rContext->powerState = POWER_STATE_IN_USE;
720 Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_IN_USE");
721 (void)pthread_mutex_unlock(&rContext->powerState_lock);
722 }
723 }
724
725 *pdwActiveProtocol = rContext->readerState->cardProtocol;
726
727 if (dwShareMode != SCARD_SHARE_DIRECT)
728 {
729 switch (*pdwActiveProtocol)
730 {
733 Log2(PCSC_LOG_DEBUG, "Active Protocol: T=%d",
734 (*pdwActiveProtocol == SCARD_PROTOCOL_T0) ? 0 : 1);
735 break;
736
738 Log1(PCSC_LOG_DEBUG, "Active Protocol: RAW");
739 break;
740
741 default:
742 Log2(PCSC_LOG_ERROR, "Active Protocol: unknown %ld",
743 *pdwActiveProtocol);
744 }
745 }
746 else
747 Log1(PCSC_LOG_DEBUG, "Direct access: no protocol selected");
748
749 if (dwShareMode == SCARD_SHARE_EXCLUSIVE)
750 {
752 {
753 /*
754 * Do nothing - we are already exclusive
755 */
756 }
757 else
758 {
760 {
762 (void)RFLockSharing(hCard, rContext);
763 }
764 else
765 {
767 goto exit;
768 }
769 }
770 }
771 else if (dwShareMode == SCARD_SHARE_SHARED)
772 {
774 {
775 /*
776 * Do nothing - in sharing mode already
777 */
778 }
779 else
780 {
781 /*
782 * We are in exclusive mode but want to share now
783 */
784 (void)RFUnlockSharing(hCard, rContext);
786 }
787 }
788 else if (dwShareMode == SCARD_SHARE_DIRECT)
789 {
791 {
792 /*
793 * Do nothing - in sharing mode already
794 */
795 }
796 else
797 {
798 /*
799 * We are in exclusive mode but want to share now
800 */
801 (void)RFUnlockSharing(hCard, rContext);
803 }
804 }
805 else
806 {
808 goto exit;
809 }
810
811 /*
812 * Clear a previous event to the application
813 */
814 (void)RFClearReaderEventState(rContext, hCard);
815
816 /*
817 * Propagate new state to reader state
818 */
819 rContext->readerState->readerSharing = rContext->contexts;
820
821 rv = SCARD_S_SUCCESS;
822
823exit:
824 UNREF_READER(rContext)
825
826 return rv;
827}
828
829LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
830{
831 LONG rv;
832 READER_CONTEXT * rContext = NULL;
833
834 if (hCard == 0)
836
837 if ((dwDisposition != SCARD_LEAVE_CARD)
838 && (dwDisposition != SCARD_UNPOWER_CARD)
839 && (dwDisposition != SCARD_RESET_CARD)
840 && (dwDisposition != SCARD_EJECT_CARD))
842
843 /* get rContext corresponding to hCard */
844 rv = RFReaderInfoById(hCard, &rContext);
845 if (rv != SCARD_S_SUCCESS)
846 return rv;
847
848 /*
849 * wait until a possible transaction is finished
850 */
851 if ((dwDisposition != SCARD_LEAVE_CARD) && (rContext->hLockId != 0)
852 && (rContext->hLockId != hCard))
853 {
854 Log1(PCSC_LOG_INFO, "Waiting for release of lock");
855 while (rContext->hLockId != 0)
857 Log1(PCSC_LOG_INFO, "Lock released");
858 }
859
860 /*
861 * Try to unlock any blocks on this context
862 *
863 * This may fail with SCARD_E_SHARING_VIOLATION if a transaction is
864 * on going on another card context and dwDisposition == SCARD_LEAVE_CARD.
865 * We should not stop.
866 */
867 rv = RFUnlockAllSharing(hCard, rContext);
868 if (rv != SCARD_S_SUCCESS)
869 {
871 {
872 goto exit;
873 }
874 else
875 {
876 if (SCARD_LEAVE_CARD != dwDisposition)
877 goto exit;
878 }
879 }
880
881 Log2(PCSC_LOG_DEBUG, "Active Contexts: %d", rContext->contexts);
882 Log2(PCSC_LOG_DEBUG, "dwDisposition: %ld", dwDisposition);
883
884 if (dwDisposition == SCARD_RESET_CARD ||
885 dwDisposition == SCARD_UNPOWER_CARD)
886 {
887 DWORD dwAtrLen;
888
889 /*
890 * Notify the card has been reset
891 */
892 RFSetReaderEventState(rContext, SCARD_RESET);
893
894 dwAtrLen = sizeof(rContext->readerState->cardAtr);
895 if (SCARD_RESET_CARD == dwDisposition)
896 rv = IFDPowerICC(rContext, IFD_RESET,
897 rContext->readerState->cardAtr, &dwAtrLen);
898 else
899 {
900 /* SCARD_UNPOWER_CARD */
901 rv = IFDPowerICC(rContext, IFD_POWER_DOWN, NULL, NULL);
902
904 Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_UNPOWERED");
905 }
906
907 /* the protocol is unset after a power on */
909
910 if (rv == IFD_SUCCESS)
911 {
912 if (SCARD_UNPOWER_CARD == dwDisposition)
914 else
915 {
916 rContext->readerState->cardAtrLength = dwAtrLen;
917 rContext->readerState->readerState =
919
920 Log1(PCSC_LOG_DEBUG, "Reset complete.");
921 LogXxd(PCSC_LOG_DEBUG, "Card ATR: ",
922 rContext->readerState->cardAtr,
923 rContext->readerState->cardAtrLength);
924 }
925 }
926 else
927 {
928 if (SCARD_UNPOWER_CARD == dwDisposition)
929 Log3(PCSC_LOG_ERROR, "Error powering down card: %ld 0x%04lX",
930 rv, rv);
931 else
932 {
933 rContext->readerState->cardAtrLength = 0;
934 Log1(PCSC_LOG_ERROR, "Error resetting card.");
935 }
936
937 if (rv == SCARD_W_REMOVED_CARD)
939 else
940 rContext->readerState->readerState =
942 }
943 }
944 else if (dwDisposition == SCARD_EJECT_CARD)
945 {
946 UCHAR controlBuffer[5];
947 UCHAR receiveBuffer[MAX_BUFFER_SIZE];
948 DWORD receiveLength;
949
950 /*
951 * Set up the CTBCS command for Eject ICC
952 */
953 controlBuffer[0] = 0x20;
954 controlBuffer[1] = 0x15;
955 controlBuffer[2] = (rContext->slot & 0x0000FFFF) + 1;
956 controlBuffer[3] = 0x00;
957 controlBuffer[4] = 0x00;
958 receiveLength = 2;
959 rv = IFDControl_v2(rContext, controlBuffer, 5, receiveBuffer,
960 &receiveLength);
961
962 if (rv == SCARD_S_SUCCESS)
963 {
964 if (receiveLength == 2 && receiveBuffer[0] == 0x90)
965 {
966 Log1(PCSC_LOG_DEBUG, "Card ejected successfully.");
967 /*
968 * Successful
969 */
970 }
971 else
972 Log1(PCSC_LOG_ERROR, "Error ejecting card.");
973 }
974 else
975 Log1(PCSC_LOG_ERROR, "Error ejecting card.");
976
977 }
978 else if (dwDisposition == SCARD_LEAVE_CARD)
979 {
980 /*
981 * Do nothing
982 */
983 }
984
985 /*
986 * Remove and destroy this handle
987 */
988 (void)RFRemoveReaderHandle(rContext, hCard);
989
990 /*
991 * For exclusive connection reset it to no connections
992 */
995 else
996 {
997 /*
998 * Remove a connection from the context stack
999 */
1000 rContext->contexts -= 1;
1001
1002 if (rContext->contexts < 0)
1003 rContext->contexts = 0;
1004 }
1005
1006 if (PCSCLITE_SHARING_NO_CONTEXT == rContext->contexts)
1007 {
1008 RESPONSECODE (*fct)(DWORD) = NULL;
1009 DWORD dwGetSize;
1010
1011 (void)pthread_mutex_lock(&rContext->powerState_lock);
1012 /* Switch to POWER_STATE_GRACE_PERIOD unless the card was not
1013 * powered */
1014 if (POWER_STATE_POWERED <= rContext->powerState)
1015 {
1017 Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_GRACE_PERIOD");
1018 }
1019
1020 (void)pthread_mutex_unlock(&rContext->powerState_lock);
1021
1022 /* ask to stop the "polling" thread so it can be restarted using
1023 * the correct timeout */
1024 dwGetSize = sizeof(fct);
1026 &dwGetSize, (PUCHAR)&fct);
1027
1028 if ((IFD_SUCCESS == rv) && (dwGetSize == sizeof(fct)))
1029 {
1030 Log1(PCSC_LOG_INFO, "Stopping polling thread");
1031 fct(rContext->slot);
1032 }
1033 }
1034
1035 /*
1036 * Propagate new state to reader state
1037 */
1038 rContext->readerState->readerSharing = rContext->contexts;
1039
1040 rv = SCARD_S_SUCCESS;
1041
1042exit:
1043 UNREF_READER(rContext)
1044
1045 return rv;
1046}
1047
1048LONG SCardBeginTransaction(SCARDHANDLE hCard)
1049{
1050 LONG rv;
1051 READER_CONTEXT * rContext;
1052
1053 if (hCard == 0)
1055
1056 /* get rContext corresponding to hCard */
1057 rv = RFReaderInfoById(hCard, &rContext);
1058 if (rv != SCARD_S_SUCCESS)
1059 return rv;
1060
1061 /*
1062 * Make sure the reader is working properly
1063 */
1064 rv = RFCheckReaderStatus(rContext);
1065 if (rv != SCARD_S_SUCCESS)
1066 goto exit;
1067
1068 /*
1069 * Make sure some event has not occurred
1070 */
1071 rv = RFCheckReaderEventState(rContext, hCard);
1072 if (rv != SCARD_S_SUCCESS)
1073 goto exit;
1074
1075 rv = RFLockSharing(hCard, rContext);
1076
1077 /* if the transaction is not yet ready we sleep a bit so the client
1078 * do not retry immediately */
1079 if (SCARD_E_SHARING_VIOLATION == rv)
1081
1082 Log2(PCSC_LOG_DEBUG, "Status: 0x%08lX", rv);
1083
1084exit:
1085 UNREF_READER(rContext)
1086
1087 return rv;
1088}
1089
1090LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
1091{
1092 LONG rv;
1093 LONG rv2;
1094 READER_CONTEXT * rContext = NULL;
1095
1096 /*
1097 * Ignoring dwDisposition for now
1098 */
1099 if (hCard == 0)
1101
1102 if ((dwDisposition != SCARD_LEAVE_CARD)
1103 && (dwDisposition != SCARD_UNPOWER_CARD)
1104 && (dwDisposition != SCARD_RESET_CARD)
1105 && (dwDisposition != SCARD_EJECT_CARD))
1106 return SCARD_E_INVALID_VALUE;
1107
1108 /* get rContext corresponding to hCard */
1109 rv = RFReaderInfoById(hCard, &rContext);
1110 if (rv != SCARD_S_SUCCESS)
1111 return rv;
1112
1113 /*
1114 * Make sure some event has not occurred
1115 */
1116 rv = RFCheckReaderEventState(rContext, hCard);
1117 if (rv != SCARD_S_SUCCESS)
1118 goto exit;
1119
1120 /*
1121 * Error if another transaction is ongoing and a card action is
1122 * requested
1123 */
1124 if ((dwDisposition != SCARD_LEAVE_CARD) && (rContext->hLockId != 0)
1125 && (rContext->hLockId != hCard))
1126 {
1127 Log1(PCSC_LOG_INFO, "No card reset within a transaction");
1129 goto exit;
1130 }
1131
1132 if (dwDisposition == SCARD_RESET_CARD ||
1133 dwDisposition == SCARD_UNPOWER_CARD)
1134 {
1135 DWORD dwAtrLen;
1136
1137 dwAtrLen = sizeof(rContext->readerState->cardAtr);
1138 if (SCARD_RESET_CARD == dwDisposition)
1139 rv = IFDPowerICC(rContext, IFD_RESET,
1140 rContext->readerState->cardAtr, &dwAtrLen);
1141 else
1142 {
1143 IFDPowerICC(rContext, IFD_POWER_DOWN, NULL, NULL);
1144 rv = IFDPowerICC(rContext, IFD_POWER_UP,
1145 rContext->readerState->cardAtr, &dwAtrLen);
1146 }
1147
1148 /* the protocol is unset after a power on */
1150
1151 /*
1152 * Notify the card has been reset
1153 */
1154 RFSetReaderEventState(rContext, SCARD_RESET);
1155
1156 /*
1157 * Set up the status bit masks on readerState
1158 */
1159 if (rv == IFD_SUCCESS)
1160 {
1161 rContext->readerState->cardAtrLength = dwAtrLen;
1162 rContext->readerState->readerState =
1164
1165 Log1(PCSC_LOG_DEBUG, "Reset complete.");
1166 LogXxd(PCSC_LOG_DEBUG, "Card ATR: ",
1167 rContext->readerState->cardAtr,
1168 rContext->readerState->cardAtrLength);
1169 }
1170 else
1171 {
1172 rContext->readerState->cardAtrLength = 0;
1173 Log1(PCSC_LOG_ERROR, "Error resetting card.");
1174
1175 if (rv == SCARD_W_REMOVED_CARD)
1177 else
1178 rContext->readerState->readerState =
1180 }
1181 }
1182 else if (dwDisposition == SCARD_EJECT_CARD)
1183 {
1184 UCHAR controlBuffer[5];
1185 UCHAR receiveBuffer[MAX_BUFFER_SIZE];
1186 DWORD receiveLength;
1187
1188 /*
1189 * Set up the CTBCS command for Eject ICC
1190 */
1191 controlBuffer[0] = 0x20;
1192 controlBuffer[1] = 0x15;
1193 controlBuffer[2] = (rContext->slot & 0x0000FFFF) + 1;
1194 controlBuffer[3] = 0x00;
1195 controlBuffer[4] = 0x00;
1196 receiveLength = 2;
1197 rv = IFDControl_v2(rContext, controlBuffer, 5, receiveBuffer,
1198 &receiveLength);
1199
1200 if (rv == SCARD_S_SUCCESS)
1201 {
1202 if (receiveLength == 2 && receiveBuffer[0] == 0x90)
1203 {
1204 Log1(PCSC_LOG_DEBUG, "Card ejected successfully.");
1205 /*
1206 * Successful
1207 */
1208 }
1209 else
1210 Log1(PCSC_LOG_ERROR, "Error ejecting card.");
1211 }
1212 else
1213 Log1(PCSC_LOG_ERROR, "Error ejecting card.");
1214
1215 }
1216 else if (dwDisposition == SCARD_LEAVE_CARD)
1217 {
1218 /*
1219 * Do nothing
1220 */
1221 }
1222
1223 /*
1224 * Unlock any blocks on this context
1225 */
1226 /* we do not want to lose the previous rv value
1227 * So we use another variable */
1228 rv2 = RFUnlockSharing(hCard, rContext);
1229 if (rv2 != SCARD_S_SUCCESS)
1230 /* if rv is already in error then do not change its value */
1231 if (rv == SCARD_S_SUCCESS)
1232 rv = rv2;
1233
1234 Log2(PCSC_LOG_DEBUG, "Status: 0x%08lX", rv);
1235
1236exit:
1237 UNREF_READER(rContext)
1238
1239 return rv;
1240}
1241
1242LONG SCardStatus(SCARDHANDLE hCard, LPSTR szReaderNames,
1243 LPDWORD pcchReaderLen, LPDWORD pdwState,
1244 LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
1245{
1246 LONG rv;
1247 READER_CONTEXT * rContext = NULL;
1248
1249 /* These parameters are not used by the client
1250 * Client side code uses readerStates[] instead */
1251 (void)szReaderNames;
1252 (void)pcchReaderLen;
1253 (void)pdwState;
1254 (void)pdwProtocol;
1255 (void)pbAtr;
1256 (void)pcbAtrLen;
1257
1258 if (hCard == 0)
1260
1261 /* get rContext corresponding to hCard */
1262 rv = RFReaderInfoById(hCard, &rContext);
1263 if (rv != SCARD_S_SUCCESS)
1264 return rv;
1265
1266 /*
1267 * Make sure no one has a lock on this reader
1268 */
1269 rv = RFCheckSharing(hCard, rContext);
1270 if (rv != SCARD_S_SUCCESS)
1271 goto exit;
1272
1273 if (rContext->readerState->cardAtrLength > MAX_ATR_SIZE)
1274 {
1276 goto exit;
1277 }
1278
1279 /*
1280 * This is a client side function however the server maintains the
1281 * list of events between applications so it must be passed through to
1282 * obtain this event if it has occurred
1283 */
1284
1285 /*
1286 * Make sure some event has not occurred
1287 */
1288 rv = RFCheckReaderEventState(rContext, hCard);
1289 if (rv != SCARD_S_SUCCESS)
1290 goto exit;
1291
1292 /*
1293 * Make sure the reader is working properly
1294 */
1295 rv = RFCheckReaderStatus(rContext);
1296 if (rv != SCARD_S_SUCCESS)
1297 goto exit;
1298
1299exit:
1300 UNREF_READER(rContext)
1301
1302 return rv;
1303}
1304
1305LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode,
1306 LPCVOID pbSendBuffer, DWORD cbSendLength,
1307 LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned)
1308{
1309 LONG rv;
1310 READER_CONTEXT * rContext = NULL;
1311
1312 /* 0 bytes returned by default */
1313 *lpBytesReturned = 0;
1314
1315 if (0 == hCard)
1317
1318 /* get rContext corresponding to hCard */
1319 rv = RFReaderInfoById(hCard, &rContext);
1320 if (rv != SCARD_S_SUCCESS)
1321 return rv;
1322
1323 /*
1324 * Make sure no one has a lock on this reader
1325 */
1326 rv = RFCheckSharing(hCard, rContext);
1327 if (rv != SCARD_S_SUCCESS)
1328 goto exit;
1329
1330 if (IFD_HVERSION_2_0 == rContext->version)
1331 if (NULL == pbSendBuffer || 0 == cbSendLength)
1332 {
1334 goto exit;
1335 }
1336
1337 /*
1338 * Make sure the reader is working properly
1339 */
1340 rv = RFCheckReaderStatus(rContext);
1341 if (rv != SCARD_S_SUCCESS)
1342 goto exit;
1343
1344 if (IFD_HVERSION_2_0 == rContext->version)
1345 {
1346 /* we must wrap a API 3.0 client in an API 2.0 driver */
1347 *lpBytesReturned = cbRecvLength;
1348 rv = IFDControl_v2(rContext, (PUCHAR)pbSendBuffer,
1349 cbSendLength, pbRecvBuffer, lpBytesReturned);
1350 }
1351 else
1352 if (IFD_HVERSION_3_0 == rContext->version)
1353 rv = IFDControl(rContext, dwControlCode, pbSendBuffer,
1354 cbSendLength, pbRecvBuffer, cbRecvLength, lpBytesReturned);
1355 else
1357
1358exit:
1359 UNREF_READER(rContext)
1360
1361 return rv;
1362}
1363
1364LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId,
1365 LPBYTE pbAttr, LPDWORD pcbAttrLen)
1366{
1367 LONG rv;
1368 READER_CONTEXT * rContext = NULL;
1369
1370 if (0 == hCard)
1372
1373 /* get rContext corresponding to hCard */
1374 rv = RFReaderInfoById(hCard, &rContext);
1375 if (rv != SCARD_S_SUCCESS)
1376 return rv;
1377
1378 /*
1379 * Make sure no one has a lock on this reader
1380 */
1381 rv = RFCheckSharing(hCard, rContext);
1382 if (rv != SCARD_S_SUCCESS)
1383 goto exit;
1384
1385 /*
1386 * Make sure the reader is working properly
1387 */
1388 rv = RFCheckReaderStatus(rContext);
1389 if (rv != SCARD_S_SUCCESS)
1390 goto exit;
1391
1392 /*
1393 * Make sure some event has not occurred
1394 */
1395 rv = RFCheckReaderEventState(rContext, hCard);
1396 if (rv != SCARD_S_SUCCESS)
1397 goto exit;
1398
1399 rv = IFDGetCapabilities(rContext, dwAttrId, pcbAttrLen, pbAttr);
1400 switch(rv)
1401 {
1402 case IFD_SUCCESS:
1403 rv = SCARD_S_SUCCESS;
1404 break;
1405 case IFD_ERROR_TAG:
1406 /* Special case SCARD_ATTR_DEVICE_FRIENDLY_NAME as it is better
1407 * implemented in pcscd (it knows the friendly name)
1408 */
1409 if ((SCARD_ATTR_DEVICE_FRIENDLY_NAME == dwAttrId)
1410 || (SCARD_ATTR_DEVICE_SYSTEM_NAME == dwAttrId))
1411 {
1412 unsigned int len = strlen(rContext->readerState->readerName)+1;
1413
1414 if (len > *pcbAttrLen)
1416 else
1417 {
1418 strcpy((char *)pbAttr, rContext->readerState->readerName);
1419 rv = SCARD_S_SUCCESS;
1420 }
1421 *pcbAttrLen = len;
1422 }
1423 else
1425 break;
1428 break;
1429 default:
1431 }
1432
1433exit:
1434 UNREF_READER(rContext)
1435
1436 return rv;
1437}
1438
1439LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId,
1440 LPCBYTE pbAttr, DWORD cbAttrLen)
1441{
1442 LONG rv;
1443 READER_CONTEXT * rContext = NULL;
1444
1445 if (0 == hCard)
1447
1448 /* get rContext corresponding to hCard */
1449 rv = RFReaderInfoById(hCard, &rContext);
1450 if (rv != SCARD_S_SUCCESS)
1451 return rv;
1452
1453 /*
1454 * Make sure no one has a lock on this reader
1455 */
1456 rv = RFCheckSharing(hCard, rContext);
1457 if (rv != SCARD_S_SUCCESS)
1458 goto exit;
1459
1460 /*
1461 * Make sure the reader is working properly
1462 */
1463 rv = RFCheckReaderStatus(rContext);
1464 if (rv != SCARD_S_SUCCESS)
1465 goto exit;
1466
1467 /*
1468 * Make sure some event has not occurred
1469 */
1470 rv = RFCheckReaderEventState(rContext, hCard);
1471 if (rv != SCARD_S_SUCCESS)
1472 goto exit;
1473
1474 rv = IFDSetCapabilities(rContext, dwAttrId, cbAttrLen, (PUCHAR)pbAttr);
1475 if (rv == IFD_SUCCESS)
1476 rv = SCARD_S_SUCCESS;
1477 else
1478 if (rv == IFD_ERROR_TAG)
1480 else
1482
1483exit:
1484 UNREF_READER(rContext)
1485
1486 return rv;
1487}
1488
1489LONG SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci,
1490 LPCBYTE pbSendBuffer, DWORD cbSendLength,
1491 SCARD_IO_REQUEST *pioRecvPci, LPBYTE pbRecvBuffer,
1492 LPDWORD pcbRecvLength)
1493{
1494 LONG rv;
1495 READER_CONTEXT * rContext = NULL;
1496 SCARD_IO_HEADER sSendPci, sRecvPci;
1497 DWORD dwRxLength, tempRxLength;
1498
1499 dwRxLength = *pcbRecvLength;
1500 *pcbRecvLength = 0;
1501
1502 if (hCard == 0)
1504
1505 /*
1506 * Must at least have 2 status words even for SCardControl
1507 */
1508 if (dwRxLength < 2)
1510
1511 /* get rContext corresponding to hCard */
1512 rv = RFReaderInfoById(hCard, &rContext);
1513 if (rv != SCARD_S_SUCCESS)
1514 return rv;
1515
1516 /*
1517 * Make sure no one has a lock on this reader
1518 */
1519 rv = RFCheckSharing(hCard, rContext);
1520 if (rv != SCARD_S_SUCCESS)
1521 goto exit;
1522
1523 /*
1524 * Make sure the reader is working properly
1525 */
1526 rv = RFCheckReaderStatus(rContext);
1527 if (rv != SCARD_S_SUCCESS)
1528 goto exit;
1529
1530 /*
1531 * Make sure some event has not occurred
1532 */
1533 rv = RFCheckReaderEventState(rContext, hCard);
1534 if (rv != SCARD_S_SUCCESS)
1535 goto exit;
1536
1537 /*
1538 * Check for some common errors
1539 */
1540 if (pioSendPci->dwProtocol != SCARD_PROTOCOL_RAW)
1541 {
1542 if (rContext->readerState->readerState & SCARD_ABSENT)
1543 {
1545 goto exit;
1546 }
1547 }
1548
1549 if (pioSendPci->dwProtocol != SCARD_PROTOCOL_RAW)
1550 {
1551 if (pioSendPci->dwProtocol != SCARD_PROTOCOL_ANY_OLD)
1552 {
1553 if (pioSendPci->dwProtocol != rContext->readerState->cardProtocol)
1554 {
1556 goto exit;
1557 }
1558 }
1559 }
1560
1561 /*
1562 * Quick fix: PC/SC starts at 1 for bit masking but the IFD_Handler
1563 * just wants 0 or 1
1564 */
1565
1566 sSendPci.Protocol = 0; /* protocol T=0 by default */
1567
1568 if (pioSendPci->dwProtocol == SCARD_PROTOCOL_T1)
1569 {
1570 sSendPci.Protocol = 1;
1571 } else if (pioSendPci->dwProtocol == SCARD_PROTOCOL_RAW)
1572 {
1573 /*
1574 * This is temporary ......
1575 */
1576 sSendPci.Protocol = SCARD_PROTOCOL_RAW;
1577 } else if (pioSendPci->dwProtocol == SCARD_PROTOCOL_ANY_OLD)
1578 {
1579 /* Fix by Amira (Athena) */
1580 unsigned long i;
1581 unsigned long prot = rContext->readerState->cardProtocol;
1582
1583 for (i = 0 ; prot != 1 && i < 16; i++)
1584 prot >>= 1;
1585
1586 sSendPci.Protocol = i;
1587 }
1588
1589 sSendPci.Length = pioSendPci->cbPciLength;
1590
1591 sRecvPci.Protocol = pioRecvPci->dwProtocol;
1592 sRecvPci.Length = pioRecvPci->cbPciLength;
1593
1594 /* the protocol number is decoded a few lines above */
1595 Log2(PCSC_LOG_DEBUG, "Send Protocol: T=%ld", sSendPci.Protocol);
1596
1597 tempRxLength = dwRxLength;
1598
1599 if ((pioSendPci->dwProtocol == SCARD_PROTOCOL_RAW)
1600 && (rContext->version == IFD_HVERSION_2_0))
1601 {
1602 rv = IFDControl_v2(rContext, (PUCHAR) pbSendBuffer, cbSendLength,
1603 pbRecvBuffer, &dwRxLength);
1604 } else
1605 {
1606 rv = IFDTransmit(rContext, sSendPci, (PUCHAR) pbSendBuffer,
1607 cbSendLength, pbRecvBuffer, &dwRxLength, &sRecvPci);
1608 }
1609
1610 pioRecvPci->dwProtocol = sRecvPci.Protocol;
1611 pioRecvPci->cbPciLength = sRecvPci.Length;
1612
1613 /*
1614 * Check for any errors that might have occurred
1615 */
1616
1617 if (rv != SCARD_S_SUCCESS)
1618 {
1619 *pcbRecvLength = 0;
1620 Log2(PCSC_LOG_ERROR, "Card not transacted: 0x%08lX", rv);
1621
1622 if (SCARD_E_NO_SMARTCARD == rv)
1623 {
1624 rContext->readerState->cardAtrLength = 0;
1627 }
1628
1629 goto exit;
1630 }
1631
1632 /*
1633 * Available is less than received
1634 */
1635 if (tempRxLength < dwRxLength)
1636 {
1637 *pcbRecvLength = 0;
1639 goto exit;
1640 }
1641
1642 /*
1643 * Successful return
1644 */
1645 *pcbRecvLength = dwRxLength;
1646
1647exit:
1648 UNREF_READER(rContext)
1649
1650 return rv;
1651}
1652
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.
Definition: eventhandler.h:79
#define PCSCLITE_SHARING_NO_CONTEXT
No application is using the reader.
Definition: eventhandler.h:77
#define PCSCLITE_SHARING_LAST_CONTEXT
One application is using the reader.
Definition: eventhandler.h:75
#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_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:342
#define IFD_ERROR_TAG
tag unknown
Definition: ifdhandler.h:351
#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:343
#define IFD_RESET
warm reset
Definition: ifdhandler.h:344
#define IFD_ERROR_INSUFFICIENT_BUFFER
buffer is too small
Definition: ifdhandler.h:372
#define IFD_SUCCESS
no error
Definition: ifdhandler.h:350
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:69
@ POWER_STATE_UNPOWERED
auto power off
Definition: pcscd.h:66
@ POWER_STATE_GRACE_PERIOD
card was in use
Definition: pcscd.h:68
#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.
volatile SCARDHANDLE hLockId
Lock Id.
pthread_mutex_t * mMutex
Mutex for this connection.
pthread_mutex_t powerState_lock
powerState mutex
int slot
Current Reader Slot.
int version
IFD Handler version number.
int32_t contexts
Number of open contexts.
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
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 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
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.