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