pcsc-lite  1.8.8
winscard.c
Go to the documentation of this file.
1 /*
2  * MUSCLE SmartCard Development ( http://www.linuxnet.com )
3  *
4  * Copyright (C) 1999-2004
5  * David Corcoran <corcoran@linuxnet.com>
6  * Copyright (C) 2002-2011
7  * Ludovic Rousseau <ludovic.rousseau@free.fr>
8  *
9  * $Id: winscard.c 6391 2012-07-26 18:44:54Z rousseau $
10  */
11 
82 #include "config.h"
83 #include <stdlib.h>
84 #include <sys/time.h>
85 #include <string.h>
86 #include <pthread.h>
87 
88 #include "pcscd.h"
89 #include "winscard.h"
90 #include "ifdhandler.h"
91 #include "debuglog.h"
92 #include "readerfactory.h"
93 #include "prothandler.h"
94 #include "ifdwrapper.h"
95 #include "atrhandler.h"
96 #include "sys_generic.h"
97 #include "eventhandler.h"
98 #include "utils.h"
99 #include "reader.h"
100 #include "strlcpycat.h"
101 
102 #undef DO_PROFILE
103 #ifdef DO_PROFILE
104 
105 #ifndef FALSE
106 #define FALSE 0
107 #define TRUE 1
108 #endif
109 
110 #define PROFILE_FILE "/tmp/pcscd_profile"
111 #include <stdio.h>
112 #include <sys/time.h>
113 #include <errno.h>
114 #include <unistd.h>
115 
116 struct timeval profile_time_start;
117 FILE *fd;
118 char profile_tty;
119 
120 #define PROFILE_START profile_start(__FUNCTION__);
121 #define PROFILE_END profile_end(__FUNCTION__, __LINE__);
122 
123 static void profile_start(const char *f)
124 {
125  static char initialized = FALSE;
126 
127  if (!initialized)
128  {
129  initialized = TRUE;
130  fd = fopen(PROFILE_FILE, "a+");
131  if (NULL == fd)
132  {
133  fprintf(stderr, "\33[01;31mCan't open %s: %s\33[0m\n",
134  PROFILE_FILE, strerror(errno));
135  exit(-1);
136  }
137  fprintf(fd, "\nStart a new profile\n");
138  fflush(fd);
139 
140  if (isatty(fileno(stderr)))
141  profile_tty = TRUE;
142  else
143  profile_tty = FALSE;
144  }
145 
146  gettimeofday(&profile_time_start, NULL);
147 } /* profile_start */
148 
149 
150 static void profile_end(const char *f, int line)
151 {
152  struct timeval profile_time_end;
153  long d;
154 
155  gettimeofday(&profile_time_end, NULL);
156  d = time_sub(&profile_time_end, &profile_time_start);
157 
158  if (profile_tty)
159  fprintf(stderr, "\33[01;31mRESULT %s \33[35m%ld\33[0m (%d)\n", f, d,
160  line);
161  fprintf(fd, "%s %ld\n", f, d);
162  fflush(fd);
163 } /* profile_end */
164 
165 #else
166 #define PROFILE_START
167 #define PROFILE_END
168 #endif
169 
171 #define SCARD_PROTOCOL_ANY_OLD 0x1000
172 
173 LONG SCardEstablishContext(DWORD dwScope, /*@unused@*/ LPCVOID pvReserved1,
174  /*@unused@*/ LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
175 {
176  (void)pvReserved1;
177  (void)pvReserved2;
178 
179  if (dwScope != SCARD_SCOPE_USER && dwScope != SCARD_SCOPE_TERMINAL &&
180  dwScope != SCARD_SCOPE_SYSTEM && dwScope != SCARD_SCOPE_GLOBAL)
181  {
182  *phContext = 0;
183  return SCARD_E_INVALID_VALUE;
184  }
185 
186  /*
187  * Unique identifier for this server so that it can uniquely be
188  * identified by clients and distinguished from others
189  */
190 
191  *phContext = SYS_RandomInt(0, -1);
192 
193  Log2(PCSC_LOG_DEBUG, "Establishing Context: 0x%lX", *phContext);
194 
195  return SCARD_S_SUCCESS;
196 }
197 
199 {
200  /*
201  * Nothing to do here RPC layer will handle this
202  */
203 
204  Log2(PCSC_LOG_DEBUG, "Releasing Context: 0x%lX", hContext);
205 
206  return SCARD_S_SUCCESS;
207 }
208 
209 LONG SCardConnect(/*@unused@*/ SCARDCONTEXT hContext, LPCSTR szReader,
210  DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
211  LPDWORD pdwActiveProtocol)
212 {
213  LONG rv;
214  READER_CONTEXT * rContext = NULL;
215  uint32_t readerState;
216 
217  (void)hContext;
218  PROFILE_START
219 
220  *phCard = 0;
221 
222  if ((dwShareMode != SCARD_SHARE_DIRECT) &&
223  !(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
224  !(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
225  !(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
226  !(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD))
227  return SCARD_E_PROTO_MISMATCH;
228 
229  if (dwShareMode != SCARD_SHARE_EXCLUSIVE &&
230  dwShareMode != SCARD_SHARE_SHARED &&
231  dwShareMode != SCARD_SHARE_DIRECT)
232  return SCARD_E_INVALID_VALUE;
233 
234  Log3(PCSC_LOG_DEBUG, "Attempting Connect to %s using protocol: %ld",
235  szReader, dwPreferredProtocols);
236 
237  rv = RFReaderInfo((LPSTR) szReader, &rContext);
238  if (rv != SCARD_S_SUCCESS)
239  {
240  Log2(PCSC_LOG_ERROR, "Reader %s Not Found", szReader);
241  return rv;
242  }
243 
244  /*
245  * Make sure the reader is working properly
246  */
247  rv = RFCheckReaderStatus(rContext);
248  if (rv != SCARD_S_SUCCESS)
249  goto exit;
250 
251  /*******************************************
252  *
253  * This section checks for simple errors
254  *
255  *******************************************/
256 
257  /*
258  * Connect if not exclusive mode
259  */
261  {
262  Log1(PCSC_LOG_ERROR, "Error Reader Exclusive");
264  goto exit;
265  }
266 
267  /*
268  * wait until a possible transaction is finished
269  */
270  if (rContext->hLockId != 0)
271  {
272  Log1(PCSC_LOG_INFO, "Waiting for release of lock");
273  while (rContext->hLockId != 0)
275  Log1(PCSC_LOG_INFO, "Lock released");
276  }
277 
278  /*******************************************
279  *
280  * This section tries to determine the
281  * presence of a card or not
282  *
283  *******************************************/
284  readerState = rContext->readerState->readerState;
285 
286  if (dwShareMode != SCARD_SHARE_DIRECT)
287  {
288  if (!(readerState & SCARD_PRESENT))
289  {
290  Log1(PCSC_LOG_DEBUG, "Card Not Inserted");
292  goto exit;
293  }
294 
295  /* Power on (again) the card if needed */
296  (void)pthread_mutex_lock(&rContext->powerState_lock);
297  if (POWER_STATE_UNPOWERED == rContext->powerState)
298  {
299  DWORD dwAtrLen;
300 
301  dwAtrLen = sizeof(rContext->readerState->cardAtr);
302  rv = IFDPowerICC(rContext, IFD_POWER_UP,
303  rContext->readerState->cardAtr, &dwAtrLen);
304  rContext->readerState->cardAtrLength = dwAtrLen;
305 
306  if (rv == IFD_SUCCESS)
307  {
308  readerState = SCARD_PRESENT | SCARD_POWERED | SCARD_NEGOTIABLE;
309 
310  Log1(PCSC_LOG_DEBUG, "power up complete.");
311  LogXxd(PCSC_LOG_DEBUG, "Card ATR: ",
312  rContext->readerState->cardAtr,
313  rContext->readerState->cardAtrLength);
314  }
315  else
316  Log3(PCSC_LOG_ERROR, "Error powering up card: %ld 0x%04lX",
317  rv, rv);
318  }
319 
320  if (! (readerState & SCARD_POWERED))
321  {
322  Log1(PCSC_LOG_ERROR, "Card Not Powered");
323  (void)pthread_mutex_unlock(&rContext->powerState_lock);
325  goto exit;
326  }
327 
328  /* the card is now in use */
329  rContext->powerState = POWER_STATE_INUSE;
330  Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_INUSE");
331  (void)pthread_mutex_unlock(&rContext->powerState_lock);
332  }
333 
334  /*******************************************
335  *
336  * This section tries to decode the ATR
337  * and set up which protocol to use
338  *
339  *******************************************/
340  if (dwPreferredProtocols & SCARD_PROTOCOL_RAW)
342  else
343  {
344  if (dwShareMode != SCARD_SHARE_DIRECT)
345  {
346  /* lock here instead in IFDSetPTS() to lock up to
347  * setting rContext->readerState->cardProtocol */
348  (void)pthread_mutex_lock(rContext->mMutex);
349 
350  /* the protocol is not yet set (no PPS yet) */
352  {
353  int availableProtocols, defaultProtocol;
354  int ret;
355 
356  ATRDecodeAtr(&availableProtocols, &defaultProtocol,
357  rContext->readerState->cardAtr,
358  rContext->readerState->cardAtrLength);
359 
360  /* If it is set to ANY let it do any of the protocols */
361  if (dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD)
362  dwPreferredProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
363 
364  ret = PHSetProtocol(rContext, dwPreferredProtocols,
365  availableProtocols, defaultProtocol);
366 
367  /* keep cardProtocol = SCARD_PROTOCOL_UNDEFINED in case of error */
368  if (SET_PROTOCOL_PPS_FAILED == ret)
369  {
370  (void)pthread_mutex_unlock(rContext->mMutex);
372  goto exit;
373  }
374 
375  if (SET_PROTOCOL_WRONG_ARGUMENT == ret)
376  {
377  (void)pthread_mutex_unlock(rContext->mMutex);
379  goto exit;
380  }
381 
382  /* use negotiated protocol */
383  rContext->readerState->cardProtocol = ret;
384 
385  (void)pthread_mutex_unlock(rContext->mMutex);
386  }
387  else
388  {
389  (void)pthread_mutex_unlock(rContext->mMutex);
390 
391  if (! (dwPreferredProtocols & rContext->readerState->cardProtocol))
392  {
394  goto exit;
395  }
396  }
397  }
398  }
399 
400  *pdwActiveProtocol = rContext->readerState->cardProtocol;
401 
402  if (dwShareMode != SCARD_SHARE_DIRECT)
403  {
404  switch (*pdwActiveProtocol)
405  {
406  case SCARD_PROTOCOL_T0:
407  case SCARD_PROTOCOL_T1:
408  Log2(PCSC_LOG_DEBUG, "Active Protocol: T=%d",
409  (*pdwActiveProtocol == SCARD_PROTOCOL_T0) ? 0 : 1);
410  break;
411 
412  case SCARD_PROTOCOL_RAW:
413  Log1(PCSC_LOG_DEBUG, "Active Protocol: RAW");
414  break;
415 
416  default:
417  Log2(PCSC_LOG_ERROR, "Active Protocol: unknown %ld",
418  *pdwActiveProtocol);
419  }
420  }
421  else
422  Log1(PCSC_LOG_DEBUG, "Direct access: no protocol selected");
423 
424  /*
425  * Prepare the SCARDHANDLE identity
426  */
427  *phCard = RFCreateReaderHandle(rContext);
428 
429  Log2(PCSC_LOG_DEBUG, "hCard Identity: %lx", *phCard);
430 
431  /*******************************************
432  *
433  * This section tries to set up the
434  * exclusivity modes. -1 is exclusive
435  *
436  *******************************************/
437 
438  if (dwShareMode == SCARD_SHARE_EXCLUSIVE)
439  {
440  if (rContext->contexts == PCSCLITE_SHARING_NO_CONTEXT)
441  {
443  (void)RFLockSharing(*phCard, rContext);
444  }
445  else
446  {
447  (void)RFDestroyReaderHandle(*phCard);
448  *phCard = 0;
450  goto exit;
451  }
452  }
453  else
454  {
455  /*
456  * Add a connection to the context stack
457  */
458  rContext->contexts += 1;
459  }
460 
461  /*
462  * Add this handle to the handle list
463  */
464  rv = RFAddReaderHandle(rContext, *phCard);
465 
466  if (rv != SCARD_S_SUCCESS)
467  {
468  /*
469  * Clean up - there is no more room
470  */
471  (void)RFDestroyReaderHandle(*phCard);
474  else
475  if (rContext->contexts > PCSCLITE_SHARING_NO_CONTEXT)
476  rContext->contexts -= 1;
477 
478  *phCard = 0;
479 
481  goto exit;
482  }
483 
484  /*
485  * Propagate new state to reader state
486  */
487  rContext->readerState->readerSharing = rContext->contexts;
488 
489 exit:
490  UNREF_READER(rContext)
491 
492  PROFILE_END
493 
494  return rv;
495 }
496 
497 LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
498  DWORD dwPreferredProtocols, DWORD dwInitialization,
499  LPDWORD pdwActiveProtocol)
500 {
501  LONG rv;
502  READER_CONTEXT * rContext = NULL;
503 
504  Log1(PCSC_LOG_DEBUG, "Attempting reconnect to token.");
505 
506  if (hCard == 0)
507  return SCARD_E_INVALID_HANDLE;
508 
509  /*
510  * Handle the dwInitialization
511  */
512  if (dwInitialization != SCARD_LEAVE_CARD &&
513  dwInitialization != SCARD_RESET_CARD &&
514  dwInitialization != SCARD_UNPOWER_CARD)
515  return SCARD_E_INVALID_VALUE;
516 
517  if (dwShareMode != SCARD_SHARE_SHARED &&
518  dwShareMode != SCARD_SHARE_EXCLUSIVE &&
519  dwShareMode != SCARD_SHARE_DIRECT)
520  return SCARD_E_INVALID_VALUE;
521 
522  if ((dwShareMode != SCARD_SHARE_DIRECT) &&
523  !(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
524  !(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
525  !(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
526  !(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD))
527  return SCARD_E_PROTO_MISMATCH;
528 
529  /* get rContext corresponding to hCard */
530  rv = RFReaderInfoById(hCard, &rContext);
531  if (rv != SCARD_S_SUCCESS)
532  return rv;
533 
534  /*
535  * Make sure the reader is working properly
536  */
537  rv = RFCheckReaderStatus(rContext);
538  if (rv != SCARD_S_SUCCESS)
539  goto exit;
540 
541  /*
542  * Make sure no one has a lock on this reader
543  */
544  rv = RFCheckSharing(hCard, rContext);
545  if (rv != SCARD_S_SUCCESS)
546  goto exit;
547 
548  if (dwInitialization == SCARD_RESET_CARD ||
549  dwInitialization == SCARD_UNPOWER_CARD)
550  {
551  DWORD dwAtrLen;
552 
553  /*
554  * Notify the card has been reset
555  */
556  (void)RFSetReaderEventState(rContext, SCARD_RESET);
557 
558  /*
559  * Currently pcsc-lite keeps the card powered constantly
560  */
561  dwAtrLen = sizeof(rContext->readerState->cardAtr);
562  if (SCARD_RESET_CARD == dwInitialization)
563  rv = IFDPowerICC(rContext, IFD_RESET,
564  rContext->readerState->cardAtr, &dwAtrLen);
565  else
566  {
567  IFDPowerICC(rContext, IFD_POWER_DOWN, NULL, NULL);
568  rv = IFDPowerICC(rContext, IFD_POWER_UP,
569  rContext->readerState->cardAtr, &dwAtrLen);
570  }
571  rContext->readerState->cardAtrLength = dwAtrLen;
572 
573  /* the protocol is unset after a power on */
575 
576  /*
577  * Set up the status bit masks on readerState
578  */
579  if (rv == SCARD_S_SUCCESS)
580  {
581  rContext->readerState->cardAtrLength = dwAtrLen;
582  rContext->readerState->readerState =
584 
585  Log1(PCSC_LOG_DEBUG, "Reset complete.");
586  LogXxd(PCSC_LOG_DEBUG, "Card ATR: ",
587  rContext->readerState->cardAtr,
588  rContext->readerState->cardAtrLength);
589  }
590  else
591  {
592  rContext->readerState->cardAtrLength = 0;
593  Log1(PCSC_LOG_ERROR, "Error resetting card.");
594 
595  if (rv == SCARD_W_REMOVED_CARD)
596  {
597  rContext->readerState->readerState = SCARD_ABSENT;
599  goto exit;
600  }
601  else
602  {
603  rContext->readerState->readerState =
606  goto exit;
607  }
608  }
609  }
610  else
611  if (dwInitialization == SCARD_LEAVE_CARD)
612  {
613  uint32_t readerState = rContext->readerState->readerState;
614 
615  if (readerState & SCARD_ABSENT)
616  {
618  goto exit;
619  }
620 
621  if ((readerState & SCARD_PRESENT)
622  && (readerState & SCARD_SWALLOWED))
623  {
625  goto exit;
626  }
627  }
628 
629  /*******************************************
630  *
631  * This section tries to decode the ATR
632  * and set up which protocol to use
633  *
634  *******************************************/
635  if (dwPreferredProtocols & SCARD_PROTOCOL_RAW)
637  else
638  {
639  if (dwShareMode != SCARD_SHARE_DIRECT)
640  {
641  /* lock here instead in IFDSetPTS() to lock up to
642  * setting rContext->readerState->cardProtocol */
643  (void)pthread_mutex_lock(rContext->mMutex);
644 
645  /* the protocol is not yet set (no PPS yet) */
647  {
648  int availableProtocols, defaultProtocol;
649  int ret;
650 
651  ATRDecodeAtr(&availableProtocols, &defaultProtocol,
652  rContext->readerState->cardAtr,
653  rContext->readerState->cardAtrLength);
654 
655  /* If it is set to ANY let it do any of the protocols */
656  if (dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD)
657  dwPreferredProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
658 
659  ret = PHSetProtocol(rContext, dwPreferredProtocols,
660  availableProtocols, defaultProtocol);
661 
662  /* keep cardProtocol = SCARD_PROTOCOL_UNDEFINED in case of error */
663  if (SET_PROTOCOL_PPS_FAILED == ret)
664  {
665  (void)pthread_mutex_unlock(rContext->mMutex);
667  goto exit;
668  }
669 
670  if (SET_PROTOCOL_WRONG_ARGUMENT == ret)
671  {
672  (void)pthread_mutex_unlock(rContext->mMutex);
674  goto exit;
675  }
676 
677  /* use negotiated protocol */
678  rContext->readerState->cardProtocol = ret;
679 
680  (void)pthread_mutex_unlock(rContext->mMutex);
681  }
682  else
683  {
684  (void)pthread_mutex_unlock(rContext->mMutex);
685 
686  if (! (dwPreferredProtocols & rContext->readerState->cardProtocol))
687  {
689  goto exit;
690  }
691  }
692  }
693  }
694 
695  *pdwActiveProtocol = rContext->readerState->cardProtocol;
696 
697  if (dwShareMode != SCARD_SHARE_DIRECT)
698  {
699  switch (*pdwActiveProtocol)
700  {
701  case SCARD_PROTOCOL_T0:
702  case SCARD_PROTOCOL_T1:
703  Log2(PCSC_LOG_DEBUG, "Active Protocol: T=%d",
704  (*pdwActiveProtocol == SCARD_PROTOCOL_T0) ? 0 : 1);
705  break;
706 
707  case SCARD_PROTOCOL_RAW:
708  Log1(PCSC_LOG_DEBUG, "Active Protocol: RAW");
709  break;
710 
711  default:
712  Log2(PCSC_LOG_ERROR, "Active Protocol: unknown %ld",
713  *pdwActiveProtocol);
714  }
715  }
716  else
717  Log1(PCSC_LOG_DEBUG, "Direct access: no protocol selected");
718 
719  if (dwShareMode == SCARD_SHARE_EXCLUSIVE)
720  {
722  {
723  /*
724  * Do nothing - we are already exclusive
725  */
726  }
727  else
728  {
729  if (rContext->contexts == PCSCLITE_SHARING_LAST_CONTEXT)
730  {
732  (void)RFLockSharing(hCard, rContext);
733  }
734  else
735  {
737  goto exit;
738  }
739  }
740  }
741  else if (dwShareMode == SCARD_SHARE_SHARED)
742  {
744  {
745  /*
746  * Do nothing - in sharing mode already
747  */
748  }
749  else
750  {
751  /*
752  * We are in exclusive mode but want to share now
753  */
754  (void)RFUnlockSharing(hCard, rContext);
756  }
757  }
758  else if (dwShareMode == SCARD_SHARE_DIRECT)
759  {
761  {
762  /*
763  * Do nothing - in sharing mode already
764  */
765  }
766  else
767  {
768  /*
769  * We are in exclusive mode but want to share now
770  */
771  (void)RFUnlockSharing(hCard, rContext);
773  }
774  }
775  else
776  {
778  goto exit;
779  }
780 
781  /*
782  * Clear a previous event to the application
783  */
784  (void)RFClearReaderEventState(rContext, hCard);
785 
786  /*
787  * Propagate new state to reader state
788  */
789  rContext->readerState->readerSharing = rContext->contexts;
790 
791  rv = SCARD_S_SUCCESS;
792 
793 exit:
794  UNREF_READER(rContext)
795 
796  return rv;
797 }
798 
799 LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
800 {
801  LONG rv;
802  READER_CONTEXT * rContext = NULL;
803 
804  if (hCard == 0)
805  return SCARD_E_INVALID_HANDLE;
806 
807  if ((dwDisposition != SCARD_LEAVE_CARD)
808  && (dwDisposition != SCARD_UNPOWER_CARD)
809  && (dwDisposition != SCARD_RESET_CARD)
810  && (dwDisposition != SCARD_EJECT_CARD))
811  return SCARD_E_INVALID_VALUE;
812 
813  /* get rContext corresponding to hCard */
814  rv = RFReaderInfoById(hCard, &rContext);
815  if (rv != SCARD_S_SUCCESS)
816  return rv;
817 
818  /*
819  * wait until a possible transaction is finished
820  */
821  if ((dwDisposition != SCARD_LEAVE_CARD) && (rContext->hLockId != 0)
822  && (rContext->hLockId != hCard))
823  {
824  Log1(PCSC_LOG_INFO, "Waiting for release of lock");
825  while (rContext->hLockId != 0)
827  Log1(PCSC_LOG_INFO, "Lock released");
828  }
829 
830  /*
831  * Try to unlock any blocks on this context
832  *
833  * This may fail with SCARD_E_SHARING_VIOLATION if a transaction is
834  * on going on another card context and dwDisposition == SCARD_LEAVE_CARD.
835  * We should not stop.
836  */
837  rv = RFUnlockAllSharing(hCard, rContext);
838  if (rv != SCARD_S_SUCCESS)
839  {
840  if (rv != SCARD_E_SHARING_VIOLATION)
841  {
842  goto exit;
843  }
844  else
845  {
846  if (SCARD_LEAVE_CARD != dwDisposition)
847  goto exit;
848  }
849  }
850 
851  Log2(PCSC_LOG_DEBUG, "Active Contexts: %d", rContext->contexts);
852  Log2(PCSC_LOG_DEBUG, "dwDisposition: %ld", dwDisposition);
853 
854  if (dwDisposition == SCARD_RESET_CARD ||
855  dwDisposition == SCARD_UNPOWER_CARD)
856  {
857  DWORD dwAtrLen;
858 
859  /*
860  * Notify the card has been reset
861  */
862  (void)RFSetReaderEventState(rContext, SCARD_RESET);
863 
864  /*
865  * Currently pcsc-lite keeps the card powered constantly
866  * unless DISABLE_AUTO_POWER_ON is defined
867  */
868  dwAtrLen = sizeof(rContext->readerState->cardAtr);
869  if (SCARD_RESET_CARD == dwDisposition)
870  rv = IFDPowerICC(rContext, IFD_RESET,
871  rContext->readerState->cardAtr, &dwAtrLen);
872  else
873  {
874  IFDPowerICC(rContext, IFD_POWER_DOWN, NULL, NULL);
875 
876 #ifdef DISABLE_AUTO_POWER_ON
877  rContext->powerState = POWER_STATE_UNPOWERED;
878  Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_UNPOWERED");
879 #else
880  rv = IFDPowerICC(rContext, IFD_POWER_UP,
881  rContext->readerState->cardAtr, &dwAtrLen);
882 #endif
883  }
884 
885  /* the protocol is unset after a power on */
887 
888 #ifdef DISABLE_AUTO_POWER_ON
889  if (SCARD_UNPOWER_CARD == dwDisposition)
890  {
891  rContext->readerState->cardAtrLength = 0;
892  if (rv == SCARD_S_SUCCESS)
894  else
895  {
896  Log3(PCSC_LOG_ERROR, "Error powering down card: %d 0x%04X",
897  rv, rv);
898  if (rv == SCARD_W_REMOVED_CARD)
899  rContext->readerState->readerState = SCARD_ABSENT;
900  else
901  rContext->readerState->readerState =
903  }
904  Log1(PCSC_LOG_INFO, "Skip card power on");
905  }
906  else
907 #endif
908  {
909  /*
910  * Set up the status bit masks on readerState
911  */
912  if (rv == SCARD_S_SUCCESS)
913  {
914  rContext->readerState->cardAtrLength = dwAtrLen;
915  rContext->readerState->readerState =
917 
918  Log1(PCSC_LOG_DEBUG, "Reset complete.");
919  LogXxd(PCSC_LOG_DEBUG, "Card ATR: ",
920  rContext->readerState->cardAtr,
921  rContext->readerState->cardAtrLength);
922  }
923  else
924  {
925  rContext->readerState->cardAtrLength = 0;
926  Log1(PCSC_LOG_ERROR, "Error resetting card.");
927 
928  if (rv == SCARD_W_REMOVED_CARD)
929  rContext->readerState->readerState = SCARD_ABSENT;
930  else
931  rContext->readerState->readerState =
933  }
934  }
935  }
936  else if (dwDisposition == SCARD_EJECT_CARD)
937  {
938  UCHAR controlBuffer[5];
939  UCHAR receiveBuffer[MAX_BUFFER_SIZE];
940  DWORD receiveLength;
941 
942  /*
943  * Set up the CTBCS command for Eject ICC
944  */
945  controlBuffer[0] = 0x20;
946  controlBuffer[1] = 0x15;
947  controlBuffer[2] = (rContext->slot & 0x0000FFFF) + 1;
948  controlBuffer[3] = 0x00;
949  controlBuffer[4] = 0x00;
950  receiveLength = 2;
951  rv = IFDControl_v2(rContext, controlBuffer, 5, receiveBuffer,
952  &receiveLength);
953 
954  if (rv == SCARD_S_SUCCESS)
955  {
956  if (receiveLength == 2 && receiveBuffer[0] == 0x90)
957  {
958  Log1(PCSC_LOG_DEBUG, "Card ejected successfully.");
959  /*
960  * Successful
961  */
962  }
963  else
964  Log1(PCSC_LOG_ERROR, "Error ejecting card.");
965  }
966  else
967  Log1(PCSC_LOG_ERROR, "Error ejecting card.");
968 
969  }
970  else if (dwDisposition == SCARD_LEAVE_CARD)
971  {
972  /*
973  * Do nothing
974  */
975  }
976 
977  /*
978  * Remove and destroy this handle
979  */
980  (void)RFRemoveReaderHandle(rContext, hCard);
981  (void)RFDestroyReaderHandle(hCard);
982 
983  /*
984  * For exclusive connection reset it to no connections
985  */
988  else
989  {
990  /*
991  * Remove a connection from the context stack
992  */
993  rContext->contexts -= 1;
994 
995  if (rContext->contexts < 0)
996  rContext->contexts = 0;
997  }
998 
999  if (PCSCLITE_SHARING_NO_CONTEXT == rContext->contexts)
1000  {
1001  RESPONSECODE (*fct)(DWORD) = NULL;
1002  DWORD dwGetSize;
1003 
1004  (void)pthread_mutex_lock(&rContext->powerState_lock);
1005  /* Switch to POWER_STATE_GRACE_PERIOD unless the card was not
1006  * powered */
1007  if (POWER_STATE_POWERED <= rContext->powerState)
1008  {
1009 #ifdef DISABLE_AUTO_POWER_ON
1010  if (SCARD_RESET_CARD == dwDisposition)
1011  {
1013  Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_GRACE_PERIOD");
1014  }
1015 #else
1017  Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_GRACE_PERIOD");
1018 #endif
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 
1043 exit:
1044  UNREF_READER(rContext)
1045 
1046  return rv;
1047 }
1048 
1050 {
1051  LONG rv;
1052  READER_CONTEXT * rContext;
1053 
1054  if (hCard == 0)
1055  return SCARD_E_INVALID_HANDLE;
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: 0x%08lX", rv);
1084 
1085 exit:
1086  UNREF_READER(rContext)
1087 
1088  return rv;
1089 }
1090 
1091 LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
1092 {
1093  LONG rv;
1094  READER_CONTEXT * rContext = NULL;
1095 
1096  /*
1097  * Ignoring dwDisposition for now
1098  */
1099  if (hCard == 0)
1100  return SCARD_E_INVALID_HANDLE;
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  if (dwDisposition == SCARD_RESET_CARD ||
1121  dwDisposition == SCARD_UNPOWER_CARD)
1122  {
1123  DWORD dwAtrLen;
1124 
1125  /*
1126  * Currently pcsc-lite keeps the card always powered
1127  */
1128  dwAtrLen = sizeof(rContext->readerState->cardAtr);
1129  if (SCARD_RESET_CARD == dwDisposition)
1130  rv = IFDPowerICC(rContext, IFD_RESET,
1131  rContext->readerState->cardAtr, &dwAtrLen);
1132  else
1133  {
1134  IFDPowerICC(rContext, IFD_POWER_DOWN, NULL, NULL);
1135  rv = IFDPowerICC(rContext, IFD_POWER_UP,
1136  rContext->readerState->cardAtr, &dwAtrLen);
1137  }
1138 
1139  /* the protocol is unset after a power on */
1141 
1142  /*
1143  * Notify the card has been reset
1144  */
1145  (void)RFSetReaderEventState(rContext, SCARD_RESET);
1146 
1147  /*
1148  * Set up the status bit masks on readerState
1149  */
1150  if (rv == SCARD_S_SUCCESS)
1151  {
1152  rContext->readerState->cardAtrLength = dwAtrLen;
1153  rContext->readerState->readerState =
1155 
1156  Log1(PCSC_LOG_DEBUG, "Reset complete.");
1157  LogXxd(PCSC_LOG_DEBUG, "Card ATR: ",
1158  rContext->readerState->cardAtr,
1159  rContext->readerState->cardAtrLength);
1160  }
1161  else
1162  {
1163  rContext->readerState->cardAtrLength = 0;
1164  Log1(PCSC_LOG_ERROR, "Error resetting card.");
1165 
1166  if (rv == SCARD_W_REMOVED_CARD)
1167  rContext->readerState->readerState = SCARD_ABSENT;
1168  else
1169  rContext->readerState->readerState =
1171  }
1172  }
1173  else if (dwDisposition == SCARD_EJECT_CARD)
1174  {
1175  UCHAR controlBuffer[5];
1176  UCHAR receiveBuffer[MAX_BUFFER_SIZE];
1177  DWORD receiveLength;
1178 
1179  /*
1180  * Set up the CTBCS command for Eject ICC
1181  */
1182  controlBuffer[0] = 0x20;
1183  controlBuffer[1] = 0x15;
1184  controlBuffer[2] = (rContext->slot & 0x0000FFFF) + 1;
1185  controlBuffer[3] = 0x00;
1186  controlBuffer[4] = 0x00;
1187  receiveLength = 2;
1188  rv = IFDControl_v2(rContext, controlBuffer, 5, receiveBuffer,
1189  &receiveLength);
1190 
1191  if (rv == SCARD_S_SUCCESS)
1192  {
1193  if (receiveLength == 2 && receiveBuffer[0] == 0x90)
1194  {
1195  Log1(PCSC_LOG_DEBUG, "Card ejected successfully.");
1196  /*
1197  * Successful
1198  */
1199  }
1200  else
1201  Log1(PCSC_LOG_ERROR, "Error ejecting card.");
1202  }
1203  else
1204  Log1(PCSC_LOG_ERROR, "Error ejecting card.");
1205 
1206  }
1207  else if (dwDisposition == SCARD_LEAVE_CARD)
1208  {
1209  /*
1210  * Do nothing
1211  */
1212  }
1213 
1214  /*
1215  * Unlock any blocks on this context
1216  */
1217  (void)RFUnlockSharing(hCard, rContext);
1218 
1219  Log2(PCSC_LOG_DEBUG, "Status: 0x%08lX", rv);
1220 
1221 exit:
1222  UNREF_READER(rContext)
1223 
1224  return rv;
1225 }
1226 
1227 LONG SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderNames,
1228  LPDWORD pcchReaderLen, LPDWORD pdwState,
1229  LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
1230 {
1231  LONG rv;
1232  READER_CONTEXT * rContext = NULL;
1233 
1234  /* These parameters are not used by the client
1235  * Client side code uses readerStates[] instead */
1236  (void)mszReaderNames;
1237  (void)pcchReaderLen;
1238  (void)pdwState;
1239  (void)pdwProtocol;
1240  (void)pbAtr;
1241  (void)pcbAtrLen;
1242 
1243  if (hCard == 0)
1244  return SCARD_E_INVALID_HANDLE;
1245 
1246  /* get rContext corresponding to hCard */
1247  rv = RFReaderInfoById(hCard, &rContext);
1248  if (rv != SCARD_S_SUCCESS)
1249  return rv;
1250 
1251  /*
1252  * Make sure no one has a lock on this reader
1253  */
1254  rv = RFCheckSharing(hCard, rContext);
1255  if (rv != SCARD_S_SUCCESS)
1256  goto exit;
1257 
1258  if (rContext->readerState->cardAtrLength > MAX_ATR_SIZE)
1259  {
1261  goto exit;
1262  }
1263 
1264  /*
1265  * This is a client side function however the server maintains the
1266  * list of events between applications so it must be passed through to
1267  * obtain this event if it has occurred
1268  */
1269 
1270  /*
1271  * Make sure some event has not occurred
1272  */
1273  rv = RFCheckReaderEventState(rContext, hCard);
1274  if (rv != SCARD_S_SUCCESS)
1275  goto exit;
1276 
1277  /*
1278  * Make sure the reader is working properly
1279  */
1280  rv = RFCheckReaderStatus(rContext);
1281  if (rv != SCARD_S_SUCCESS)
1282  goto exit;
1283 
1284 exit:
1285  UNREF_READER(rContext)
1286 
1287  return rv;
1288 }
1289 
1290 LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode,
1291  LPCVOID pbSendBuffer, DWORD cbSendLength,
1292  LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned)
1293 {
1294  LONG rv;
1295  READER_CONTEXT * rContext = NULL;
1296 
1297  /* 0 bytes returned by default */
1298  *lpBytesReturned = 0;
1299 
1300  if (0 == hCard)
1301  return SCARD_E_INVALID_HANDLE;
1302 
1303  /* get rContext corresponding to hCard */
1304  rv = RFReaderInfoById(hCard, &rContext);
1305  if (rv != SCARD_S_SUCCESS)
1306  return rv;
1307 
1308  /*
1309  * Make sure no one has a lock on this reader
1310  */
1311  rv = RFCheckSharing(hCard, rContext);
1312  if (rv != SCARD_S_SUCCESS)
1313  goto exit;
1314 
1315  if (IFD_HVERSION_2_0 == rContext->version)
1316  if (NULL == pbSendBuffer || 0 == cbSendLength)
1317  {
1319  goto exit;
1320  }
1321 
1322  /*
1323  * Make sure the reader is working properly
1324  */
1325  rv = RFCheckReaderStatus(rContext);
1326  if (rv != SCARD_S_SUCCESS)
1327  goto exit;
1328 
1329  if (IFD_HVERSION_2_0 == rContext->version)
1330  {
1331  /* we must wrap a API 3.0 client in an API 2.0 driver */
1332  *lpBytesReturned = cbRecvLength;
1333  rv = IFDControl_v2(rContext, (PUCHAR)pbSendBuffer,
1334  cbSendLength, pbRecvBuffer, lpBytesReturned);
1335  }
1336  else
1337  if (IFD_HVERSION_3_0 == rContext->version)
1338  rv = IFDControl(rContext, dwControlCode, pbSendBuffer,
1339  cbSendLength, pbRecvBuffer, cbRecvLength, lpBytesReturned);
1340  else
1342 
1343 exit:
1344  UNREF_READER(rContext)
1345 
1346  return rv;
1347 }
1348 
1349 LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId,
1350  LPBYTE pbAttr, LPDWORD pcbAttrLen)
1351 {
1352  LONG rv;
1353  READER_CONTEXT * rContext = NULL;
1354 
1355  if (0 == hCard)
1356  return SCARD_E_INVALID_HANDLE;
1357 
1358  /* get rContext corresponding to hCard */
1359  rv = RFReaderInfoById(hCard, &rContext);
1360  if (rv != SCARD_S_SUCCESS)
1361  return rv;
1362 
1363  /*
1364  * Make sure no one has a lock on this reader
1365  */
1366  rv = RFCheckSharing(hCard, rContext);
1367  if (rv != SCARD_S_SUCCESS)
1368  goto exit;
1369 
1370  /*
1371  * Make sure the reader is working properly
1372  */
1373  rv = RFCheckReaderStatus(rContext);
1374  if (rv != SCARD_S_SUCCESS)
1375  goto exit;
1376 
1377  /*
1378  * Make sure some event has not occurred
1379  */
1380  rv = RFCheckReaderEventState(rContext, hCard);
1381  if (rv != SCARD_S_SUCCESS)
1382  goto exit;
1383 
1384  rv = IFDGetCapabilities(rContext, dwAttrId, pcbAttrLen, pbAttr);
1385  switch(rv)
1386  {
1387  case IFD_SUCCESS:
1388  rv = SCARD_S_SUCCESS;
1389  break;
1390  case IFD_ERROR_TAG:
1391  /* Special case SCARD_ATTR_DEVICE_FRIENDLY_NAME as it is better
1392  * implemented in pcscd (it knows the friendly name)
1393  */
1394  if (dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME)
1395  {
1396  unsigned int len = strlen(rContext->readerState->readerName)+1;
1397 
1398  *pcbAttrLen = len;
1399  if (len > *pcbAttrLen)
1401  else
1402  {
1403  (void)strlcpy((char *)pbAttr,
1404  rContext->readerState->readerName, *pcbAttrLen);
1405  rv = SCARD_S_SUCCESS;
1406  }
1407 
1408  }
1409  else
1411  break;
1414  break;
1415  default:
1417  }
1418 
1419 exit:
1420  UNREF_READER(rContext)
1421 
1422  return rv;
1423 }
1424 
1425 LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId,
1426  LPCBYTE pbAttr, DWORD cbAttrLen)
1427 {
1428  LONG rv;
1429  READER_CONTEXT * rContext = NULL;
1430 
1431  if (0 == hCard)
1432  return SCARD_E_INVALID_HANDLE;
1433 
1434  /* get rContext corresponding to hCard */
1435  rv = RFReaderInfoById(hCard, &rContext);
1436  if (rv != SCARD_S_SUCCESS)
1437  return rv;
1438 
1439  /*
1440  * Make sure no one has a lock on this reader
1441  */
1442  rv = RFCheckSharing(hCard, rContext);
1443  if (rv != SCARD_S_SUCCESS)
1444  goto exit;
1445 
1446  /*
1447  * Make sure the reader is working properly
1448  */
1449  rv = RFCheckReaderStatus(rContext);
1450  if (rv != SCARD_S_SUCCESS)
1451  goto exit;
1452 
1453  /*
1454  * Make sure some event has not occurred
1455  */
1456  rv = RFCheckReaderEventState(rContext, hCard);
1457  if (rv != SCARD_S_SUCCESS)
1458  goto exit;
1459 
1460  rv = IFDSetCapabilities(rContext, dwAttrId, cbAttrLen, (PUCHAR)pbAttr);
1461  if (rv == IFD_SUCCESS)
1462  rv = SCARD_S_SUCCESS;
1463  else
1464  if (rv == IFD_ERROR_TAG)
1466  else
1468 
1469 exit:
1470  UNREF_READER(rContext)
1471 
1472  return rv;
1473 }
1474 
1475 LONG SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci,
1476  LPCBYTE pbSendBuffer, DWORD cbSendLength,
1477  SCARD_IO_REQUEST *pioRecvPci, LPBYTE pbRecvBuffer,
1478  LPDWORD pcbRecvLength)
1479 {
1480  LONG rv;
1481  READER_CONTEXT * rContext = NULL;
1482  SCARD_IO_HEADER sSendPci, sRecvPci;
1483  DWORD dwRxLength, tempRxLength;
1484 
1485  dwRxLength = *pcbRecvLength;
1486  *pcbRecvLength = 0;
1487 
1488  if (hCard == 0)
1489  return SCARD_E_INVALID_HANDLE;
1490 
1491  /*
1492  * Must at least have 2 status words even for SCardControl
1493  */
1494  if (dwRxLength < 2)
1496 
1497  /* get rContext corresponding to hCard */
1498  rv = RFReaderInfoById(hCard, &rContext);
1499  if (rv != SCARD_S_SUCCESS)
1500  return rv;
1501 
1502  /*
1503  * Make sure no one has a lock on this reader
1504  */
1505  rv = RFCheckSharing(hCard, rContext);
1506  if (rv != SCARD_S_SUCCESS)
1507  goto exit;
1508 
1509  /*
1510  * Make sure the reader is working properly
1511  */
1512  rv = RFCheckReaderStatus(rContext);
1513  if (rv != SCARD_S_SUCCESS)
1514  goto exit;
1515 
1516  /*
1517  * Make sure some event has not occurred
1518  */
1519  rv = RFCheckReaderEventState(rContext, hCard);
1520  if (rv != SCARD_S_SUCCESS)
1521  goto exit;
1522 
1523  /*
1524  * Check for some common errors
1525  */
1526  if (pioSendPci->dwProtocol != SCARD_PROTOCOL_RAW)
1527  {
1528  if (rContext->readerState->readerState & SCARD_ABSENT)
1529  {
1530  rv = SCARD_E_NO_SMARTCARD;
1531  goto exit;
1532  }
1533  }
1534 
1535  if (pioSendPci->dwProtocol != SCARD_PROTOCOL_RAW)
1536  {
1537  if (pioSendPci->dwProtocol != SCARD_PROTOCOL_ANY_OLD)
1538  {
1539  if (pioSendPci->dwProtocol != rContext->readerState->cardProtocol)
1540  {
1542  goto exit;
1543  }
1544  }
1545  }
1546 
1547  /*
1548  * Quick fix: PC/SC starts at 1 for bit masking but the IFD_Handler
1549  * just wants 0 or 1
1550  */
1551 
1552  sSendPci.Protocol = 0; /* protocol T=0 by default */
1553 
1554  if (pioSendPci->dwProtocol == SCARD_PROTOCOL_T1)
1555  {
1556  sSendPci.Protocol = 1;
1557  } else if (pioSendPci->dwProtocol == SCARD_PROTOCOL_RAW)
1558  {
1559  /*
1560  * This is temporary ......
1561  */
1562  sSendPci.Protocol = SCARD_PROTOCOL_RAW;
1563  } else if (pioSendPci->dwProtocol == SCARD_PROTOCOL_ANY_OLD)
1564  {
1565  /* Fix by Amira (Athena) */
1566  unsigned long i;
1567  unsigned long prot = rContext->readerState->cardProtocol;
1568 
1569  for (i = 0 ; prot != 1 ; i++)
1570  prot >>= 1;
1571 
1572  sSendPci.Protocol = i;
1573  }
1574 
1575  sSendPci.Length = pioSendPci->cbPciLength;
1576 
1577  sRecvPci.Protocol = pioRecvPci->dwProtocol;
1578  sRecvPci.Length = pioRecvPci->cbPciLength;
1579 
1580  /* the protocol number is decoded a few lines above */
1581  Log2(PCSC_LOG_DEBUG, "Send Protocol: T=%ld", sSendPci.Protocol);
1582 
1583  tempRxLength = dwRxLength;
1584 
1585  if ((pioSendPci->dwProtocol == SCARD_PROTOCOL_RAW)
1586  && (rContext->version == IFD_HVERSION_2_0))
1587  {
1588  rv = IFDControl_v2(rContext, (PUCHAR) pbSendBuffer, cbSendLength,
1589  pbRecvBuffer, &dwRxLength);
1590  } else
1591  {
1592  rv = IFDTransmit(rContext, sSendPci, (PUCHAR) pbSendBuffer,
1593  cbSendLength, pbRecvBuffer, &dwRxLength, &sRecvPci);
1594  }
1595 
1596  pioRecvPci->dwProtocol = sRecvPci.Protocol;
1597  pioRecvPci->cbPciLength = sRecvPci.Length;
1598 
1599  /*
1600  * Check for any errors that might have occurred
1601  */
1602 
1603  if (rv != SCARD_S_SUCCESS)
1604  {
1605  *pcbRecvLength = 0;
1606  Log2(PCSC_LOG_ERROR, "Card not transacted: 0x%08lX", rv);
1607  goto exit;
1608  }
1609 
1610  /*
1611  * Available is less than received
1612  */
1613  if (tempRxLength < dwRxLength)
1614  {
1615  *pcbRecvLength = 0;
1617  goto exit;
1618  }
1619 
1620  /*
1621  * Successful return
1622  */
1623  *pcbRecvLength = dwRxLength;
1624 
1625 exit:
1626  UNREF_READER(rContext)
1627 
1628  return rv;
1629 }
1630 
struct pubReaderStatesList * readerState
link to the reader state
uint32_t cardAtrLength
ATR length.
Definition: eventhandler.h:35
#define SCARD_ATTR_DEVICE_FRIENDLY_NAME
Reader&#39;s display name.
Definition: reader.h:90
int32_t contexts
Number of open contexts.
#define IFD_ERROR_TAG
tag unknown
Definition: ifdhandler.h:329
#define SCARD_E_PROTO_MISMATCH
The requested protocols are incompatible with the protocol currently in use with the smart card...
Definition: pcsclite.h:95
volatile SCARDHANDLE hLockId
Lock Id.
#define SCARD_SCOPE_USER
Scope in user space.
Definition: pcsclite.h:146
#define TAG_IFD_STOP_POLLING_THREAD
method used to stop the polling thread (instead of just pthread_kill())
Definition: ifdhandler.h:307
#define PCSCLITE_SHARING_NO_CONTEXT
No application is using the reader.
Definition: eventhandler.h:51
#define MAX_BUFFER_SIZE
Maximum Tx/Rx Buffer for short APDU.
Definition: pcsclite.h:208
LONG IFDGetCapabilities(READER_CONTEXT *rContext, DWORD dwTag, PDWORD pdwLength, PUCHAR pucValue)
Get&#39;s capabilities in the reader.
Definition: ifdwrapper.c:214
This keeps a list of defines shared between the driver and the application.
char readerName[MAX_READERNAME]
reader name
Definition: eventhandler.h:29
PCSC_API LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
Creates an Application Context to the PC/SC Resource Manager.
Definition: winscard.c:173
unsigned long cbPciLength
Protocol Control Inf Length.
Definition: pcsclite.h:61
int32_t readerSharing
PCSCLITE_SHARING_* sharing status.
Definition: eventhandler.h:32
#define SCARD_E_INVALID_PARAMETER
One or more of the supplied parameters could not be properly interpreted.
Definition: pcsclite.h:84
#define SCARD_E_NOT_TRANSACTED
An attempt was made to end a non-existent transaction.
Definition: pcsclite.h:102
#define SCARD_LEAVE_CARD
Do nothing on close.
Definition: pcsclite.h:163
This handles protocol defaults, PTS, etc.
This handles abstract system level calls.
int slot
Current Reader Slot.
This wraps the dynamic ifdhandler functions.
#define SCARD_PROTOCOL_T1
T=1 active protocol.
Definition: pcsclite.h:153
#define SCARD_E_INVALID_HANDLE
The supplied handle was invalid.
Definition: pcsclite.h:83
#define SCARD_SCOPE_TERMINAL
Scope in terminal.
Definition: pcsclite.h:147
#define SCARD_W_UNRESPONSIVE_CARD
The smart card is not responding to a reset.
Definition: pcsclite.h:133
PCSC_API LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, LPDWORD pcbAttrLen)
Get an attribute from the IFD Handler (reader driver).
Definition: winscard.c:1349
#define SCARD_PROTOCOL_ANY_OLD
used for backward compatibility
Definition: winscard.c:171
#define SCARD_PRESENT
Card is present.
Definition: pcsclite.h:170
PCSC_API LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
Terminates a connection made through SCardConnect().
Definition: winscard.c:799
int SYS_USleep(int)
Makes the current process sleep for some microseconds.
Definition: sys_unix.c:62
#define SCARD_NEGOTIABLE
Ready for PTS.
Definition: pcsclite.h:173
#define PCSCLITE_SHARING_EXCLUSIVE_CONTEXT
Reader used in exclusive mode.
Definition: eventhandler.h:53
#define PCSCLITE_LOCK_POLL_RATE
Lock polling rate.
Definition: pcscd.h:35
LONG SCARDCONTEXT
hContext returned by SCardEstablishContext()
Definition: pcsclite.h:31
This keeps track of smart card protocols, timing issues and Answer to Reset ATR handling.
#define SCARD_E_INVALID_VALUE
One or more of the supplied parameters values could not be properly interpreted.
Definition: pcsclite.h:97
#define SCARD_RESET
Card was reset.
Definition: pcscd.h:22
#define SCARD_SHARE_SHARED
Shared mode only.
Definition: pcsclite.h:160
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:486
unsigned long dwProtocol
Protocol identifier.
Definition: pcsclite.h:60
prototypes of strlcpy()/strlcat() imported from OpenBSD
#define IFD_POWER_DOWN
power down the card
Definition: ifdhandler.h:321
card is used
Definition: pcscd.h:50
int version
IFD Handler version number.
#define SCARD_PROTOCOL_T0
T=0 active protocol.
Definition: pcsclite.h:152
pthread_mutex_t * mMutex
Mutex for this connection.
Definition: readerfactory.h:91
PCSC_API LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode, DWORD dwPreferredProtocols, DWORD dwInitialization, LPDWORD pdwActiveProtocol)
Reestablishes a connection to a reader that was previously connected to using SCardConnect().
Definition: winscard.c:497
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:106
short ATRDecodeAtr(int *availableProtocols, int *currentProtocol, PUCHAR pucAtr, DWORD dwLength)
parse an ATR
Definition: atrhandler.c:45
This handles card insertion/removal events, updates ATR, protocol, and status information.
#define SCARD_UNPOWER_CARD
Power down on close.
Definition: pcsclite.h:165
LONG IFDSetCapabilities(READER_CONTEXT *rContext, DWORD dwTag, DWORD dwLength, PUCHAR pucValue)
Set capabilities in the reader.
Definition: ifdwrapper.c:183
#define SCARD_W_REMOVED_CARD
The smart card has been removed, so further communication is not possible.
Definition: pcsclite.h:136
PCSC_API LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
Establishes a connection to the reader specified in * szReader.
Definition: winscard.c:209
PCSC_API LONG SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderName, LPDWORD pcchReaderLen, LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
Returns the current status of the reader connected to by hCard.
Definition: winscard.c:1227
PCSC_API LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr, DWORD cbAttrLen)
Set an attribute of the IFD Handler.
Definition: winscard.c:1425
#define SCARD_SWALLOWED
Card not powered.
Definition: pcsclite.h:171
#define SCARD_E_UNSUPPORTED_FEATURE
This smart card does not support the requested feature.
Definition: pcsclite.h:112
int powerState
auto power off state
#define SCARD_PROTOCOL_UNDEFINED
protocol not set
Definition: pcsclite.h:150
#define SCARD_RESET_CARD
Reset on close.
Definition: pcsclite.h:164
UCHAR cardAtr[MAX_ATR_SIZE]
ATR.
Definition: eventhandler.h:34
LONG SCARDHANDLE
hCard returned by SCardConnect()
Definition: pcsclite.h:34
LONG IFDPowerICC(READER_CONTEXT *rContext, DWORD dwAction, PUCHAR pucAtr, PDWORD pdwAtrLen)
Power up/down or reset&#39;s an ICC located in the IFD.
Definition: ifdwrapper.c:244
#define SCARD_SHARE_EXCLUSIVE
Exclusive mode only.
Definition: pcsclite.h:159
#define SCARD_POWERED
Card is powered.
Definition: pcsclite.h:172
card was in use
Definition: pcscd.h:49
DWORD PHSetProtocol(struct ReaderContext *rContext, DWORD dwPreferred, UCHAR ucAvailable, UCHAR ucDefault)
Determine which protocol to use.
Definition: prothandler.c:39
PCSC_API LONG SCardBeginTransaction(SCARDHANDLE hCard)
Establishes a temporary exclusive access mode for doing a serie of commands in a transaction.
Definition: winscard.c:1049
This keeps a list of defines for pcsc-lite.
#define SCARD_PROTOCOL_RAW
Raw active protocol.
Definition: pcsclite.h:154
#define SCARD_EJECT_CARD
Eject on close.
Definition: pcsclite.h:166
Protocol Control Information (PCI)
Definition: pcsclite.h:58
PCSC_API LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer, DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned)
Sends a command directly to the IFD Handler (reader driver) to be processed by the reader...
Definition: winscard.c:1290
#define SCARD_E_SHARING_VIOLATION
The smart card cannot be accessed because of other connections outstanding.
Definition: pcsclite.h:91
#define SCARD_SCOPE_GLOBAL
Scope is global.
Definition: pcscd.h:20
#define SCARD_W_UNPOWERED_CARD
Power has been removed from the smart card, so that further communication is not possible.
Definition: pcsclite.h:134
#define SCARD_ABSENT
Card is absent.
Definition: pcsclite.h:169
uint32_t cardProtocol
SCARD_PROTOCOL_* value.
Definition: eventhandler.h:36
auto power off
Definition: pcscd.h:47
#define SCARD_E_NO_SMARTCARD
The operation requires a Smart Card, but no Smart Card is currently in the device.
Definition: pcsclite.h:92
This keeps track of a list of currently available reader structures.
#define MAX_ATR_SIZE
Maximum ATR size.
Definition: pcsclite.h:38
#define IFD_ERROR_INSUFFICIENT_BUFFER
buffer is too small
Definition: ifdhandler.h:350
uint32_t readerState
SCARD_* bit field.
Definition: eventhandler.h:31
#define SCARD_E_INSUFFICIENT_BUFFER
The data buffer to receive returned data is too small for the returned data.
Definition: pcsclite.h:88
#define SCARD_SHARE_DIRECT
Raw mode only.
Definition: pcsclite.h:161
#define PCSCLITE_SHARING_LAST_CONTEXT
One application is using the reader.
Definition: eventhandler.h:49
pthread_mutex_t powerState_lock
powerState mutex
PCSC_API LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
Ends a previously begun transaction.
Definition: winscard.c:1091
PCSC_API LONG SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci, LPCBYTE pbSendBuffer, DWORD cbSendLength, SCARD_IO_REQUEST *pioRecvPci, LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength)
Sends an APDU to the smart card contained in the reader connected to by SCardConnect().
Definition: winscard.c:1475
Use by SCardTransmit()
Definition: ifdhandler.h:288
#define IFD_RESET
warm reset
Definition: ifdhandler.h:322
#define SCARD_S_SUCCESS
error codes from http://msdn.microsoft.com/en-us/library/aa924526.aspx
Definition: pcsclite.h:80
#define SCARD_SCOPE_SYSTEM
Scope in system.
Definition: pcsclite.h:148
This handles smart card reader communications.
PCSC_API LONG SCardReleaseContext(SCARDCONTEXT hContext)
Destroys a communication context to the PC/SC Resource Manager.
Definition: winscard.c:198
#define IFD_POWER_UP
power up the card
Definition: ifdhandler.h:320
This handles debugging.
#define IFD_SUCCESS
no error
Definition: ifdhandler.h:328
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, biometric.
Definition: ifdwrapper.c:426
#define SCARD_F_INTERNAL_ERROR
An internal consistency check failed.
Definition: pcsclite.h:81