pcsc-lite  2.0.1
winscard.c
Go to the documentation of this file.
1 /*
2  * MUSCLE SmartCard Development ( https://pcsclite.apdu.fr/ )
3  *
4  * Copyright (C) 1999-2004
5  * David Corcoran <corcoran@musclecard.com>
6  * Copyright (C) 2002-2011
7  * Ludovic Rousseau <ludovic.rousseau@free.fr>
8  *
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions
11 are met:
12 
13 1. Redistributions of source code must retain the above copyright
14  notice, this list of conditions and the following disclaimer.
15 2. 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.
18 3. 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 
21 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 THIS 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 
131 struct timeval profile_time_start;
132 FILE *fd;
133 bool profile_tty;
134 
135 #define PROFILE_START profile_start(__FUNCTION__);
136 #define PROFILE_END profile_end(__FUNCTION__, __LINE__);
137 
138 static 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 
165 static 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 
188 static pthread_mutex_t LockMutex = PTHREAD_MUTEX_INITIALIZER;
189 
190 LONG 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;
200  return SCARD_E_INVALID_VALUE;
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 
215 LONG 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 
229 LONG 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))
246  return SCARD_E_PROTO_MISMATCH;
247 
248  if (dwShareMode != SCARD_SHARE_EXCLUSIVE &&
249  dwShareMode != SCARD_SHARE_SHARED &&
250  dwShareMode != SCARD_SHARE_DIRECT)
251  return SCARD_E_INVALID_VALUE;
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)
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  ret = PHSetProtocol(rContext, dwPreferredProtocols,
382  availableProtocols, defaultProtocol);
383 
384  /* keep cardProtocol = SCARD_PROTOCOL_UNDEFINED in case of error */
385  if (SET_PROTOCOL_PPS_FAILED == ret)
386  {
387  (void)pthread_mutex_unlock(rContext->mMutex);
389  goto exit;
390  }
391 
392  if (SET_PROTOCOL_WRONG_ARGUMENT == ret)
393  {
394  (void)pthread_mutex_unlock(rContext->mMutex);
396  goto exit;
397  }
398 
399  /* use negotiated protocol */
400  rContext->readerState->cardProtocol = ret;
401 
402  (void)pthread_mutex_unlock(rContext->mMutex);
403  }
404  else
405  {
406  (void)pthread_mutex_unlock(rContext->mMutex);
407 
408  /*
409  * If it is set to ANY let it do any of the protocols
410  */
411  if (dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD)
412  dwPreferredProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
413 
414  if (! (dwPreferredProtocols & rContext->readerState->cardProtocol))
415  {
417  goto exit;
418  }
419  }
420  }
421  }
422 
423  *pdwActiveProtocol = rContext->readerState->cardProtocol;
424 
425  if (dwShareMode != SCARD_SHARE_DIRECT)
426  {
427  switch (*pdwActiveProtocol)
428  {
429  case SCARD_PROTOCOL_T0:
430  case SCARD_PROTOCOL_T1:
431  Log2(PCSC_LOG_DEBUG, "Active Protocol: T=%d",
432  (*pdwActiveProtocol == SCARD_PROTOCOL_T0) ? 0 : 1);
433  break;
434 
435  case SCARD_PROTOCOL_RAW:
436  Log1(PCSC_LOG_DEBUG, "Active Protocol: RAW");
437  break;
438 
439  default:
440  Log2(PCSC_LOG_ERROR, "Active Protocol: unknown %ld",
441  *pdwActiveProtocol);
442  }
443  }
444  else
445  Log1(PCSC_LOG_DEBUG, "Direct access: no protocol selected");
446 
447  /*
448  * Prepare the SCARDHANDLE identity
449  */
450 
451  /* we need a lock to avoid concurrent generation of handles leading
452  * to a possible hCard handle duplication */
453  (void)pthread_mutex_lock(&LockMutex);
454 
455  *phCard = RFCreateReaderHandle(rContext);
456 
457  Log2(PCSC_LOG_DEBUG, "hCard Identity: %lx", *phCard);
458 
459  /*******************************************
460  *
461  * This section tries to set up the
462  * exclusivity modes. -1 is exclusive
463  *
464  *******************************************/
465 
466  if (dwShareMode == SCARD_SHARE_EXCLUSIVE)
467  {
468  if (rContext->contexts == PCSCLITE_SHARING_NO_CONTEXT)
469  {
471  (void)RFLockSharing(*phCard, rContext);
472  }
473  else
474  {
475  *phCard = 0;
477  (void)pthread_mutex_unlock(&LockMutex);
478  goto exit;
479  }
480  }
481  else
482  {
483  /*
484  * Add a connection to the context stack
485  */
486  rContext->contexts += 1;
487  }
488 
489  /*
490  * Add this handle to the handle list
491  */
492  rv = RFAddReaderHandle(rContext, *phCard);
493 
494  (void)pthread_mutex_unlock(&LockMutex);
495 
496  if (rv != SCARD_S_SUCCESS)
497  {
498  /*
499  * Clean up - there is no more room
500  */
503  else
504  if (rContext->contexts > PCSCLITE_SHARING_NO_CONTEXT)
505  rContext->contexts -= 1;
506 
507  *phCard = 0;
508 
510  goto exit;
511  }
512 
513  /*
514  * Propagate new state to reader state
515  */
516  rContext->readerState->readerSharing = rContext->contexts;
517 
518 exit:
519  UNREF_READER(rContext)
520 
521  PROFILE_END
522 
523  return rv;
524 }
525 
526 LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
527  DWORD dwPreferredProtocols, DWORD dwInitialization,
528  LPDWORD pdwActiveProtocol)
529 {
530  LONG rv;
531  READER_CONTEXT * rContext = NULL;
532 
533  Log1(PCSC_LOG_DEBUG, "Attempting reconnect to token.");
534 
535  if (hCard == 0)
536  return SCARD_E_INVALID_HANDLE;
537 
538  /*
539  * Handle the dwInitialization
540  */
541  if (dwInitialization != SCARD_LEAVE_CARD &&
542  dwInitialization != SCARD_RESET_CARD &&
543  dwInitialization != SCARD_UNPOWER_CARD)
544  return SCARD_E_INVALID_VALUE;
545 
546  if (dwShareMode != SCARD_SHARE_SHARED &&
547  dwShareMode != SCARD_SHARE_EXCLUSIVE &&
548  dwShareMode != SCARD_SHARE_DIRECT)
549  return SCARD_E_INVALID_VALUE;
550 
551  if ((dwShareMode != SCARD_SHARE_DIRECT) &&
552  !(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
553  !(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
554  !(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
555  !(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD))
556  return SCARD_E_PROTO_MISMATCH;
557 
558  /* get rContext corresponding to hCard */
559  rv = RFReaderInfoById(hCard, &rContext);
560  if (rv != SCARD_S_SUCCESS)
561  return rv;
562 
563  /*
564  * Make sure the reader is working properly
565  */
566  rv = RFCheckReaderStatus(rContext);
567  if (rv != SCARD_S_SUCCESS)
568  goto exit;
569 
570  /*
571  * Make sure no one has a lock on this reader
572  */
573  rv = RFCheckSharing(hCard, rContext);
574  if (rv != SCARD_S_SUCCESS)
575  goto exit;
576 
577  if (dwInitialization == SCARD_RESET_CARD ||
578  dwInitialization == SCARD_UNPOWER_CARD)
579  {
580  DWORD dwAtrLen;
581 
582  /*
583  * Notify the card has been reset
584  */
585  RFSetReaderEventState(rContext, SCARD_RESET);
586 
587  dwAtrLen = sizeof(rContext->readerState->cardAtr);
588  if (SCARD_RESET_CARD == dwInitialization)
589  rv = IFDPowerICC(rContext, IFD_RESET,
590  rContext->readerState->cardAtr, &dwAtrLen);
591  else
592  {
593  IFDPowerICC(rContext, IFD_POWER_DOWN, NULL, NULL);
594  rv = IFDPowerICC(rContext, IFD_POWER_UP,
595  rContext->readerState->cardAtr, &dwAtrLen);
596  }
597 
598  /* the protocol is unset after a power on */
600 
601  /*
602  * Set up the status bit masks on readerState
603  */
604  if (rv == IFD_SUCCESS)
605  {
606  rContext->readerState->cardAtrLength = dwAtrLen;
607  rContext->readerState->readerState =
609 
610  Log1(PCSC_LOG_DEBUG, "Reset complete.");
611  LogXxd(PCSC_LOG_DEBUG, "Card ATR: ",
612  rContext->readerState->cardAtr,
613  rContext->readerState->cardAtrLength);
614  }
615  else
616  {
617  rContext->readerState->cardAtrLength = 0;
618  Log1(PCSC_LOG_ERROR, "Error resetting card.");
619 
620  if (rv == SCARD_W_REMOVED_CARD)
621  {
622  rContext->readerState->readerState = SCARD_ABSENT;
624  goto exit;
625  }
626  else
627  {
628  rContext->readerState->readerState =
631  goto exit;
632  }
633  }
634  }
635  else
636  if (dwInitialization == SCARD_LEAVE_CARD)
637  {
638  uint32_t readerState = rContext->readerState->readerState;
639 
640  if (readerState & SCARD_ABSENT)
641  {
643  goto exit;
644  }
645 
646  if ((readerState & SCARD_PRESENT)
647  && (readerState & SCARD_SWALLOWED))
648  {
650  goto exit;
651  }
652  }
653 
654  /*******************************************
655  *
656  * This section tries to decode the ATR
657  * and set up which protocol to use
658  *
659  *******************************************/
660  if (dwPreferredProtocols & SCARD_PROTOCOL_RAW)
662  else
663  {
664  if (dwShareMode != SCARD_SHARE_DIRECT)
665  {
666  /* lock here instead in IFDSetPTS() to lock up to
667  * setting rContext->readerState->cardProtocol */
668  (void)pthread_mutex_lock(rContext->mMutex);
669 
670  /* the protocol is not yet set (no PPS yet) */
672  {
673  int availableProtocols, defaultProtocol;
674  int ret;
675 
676  ATRDecodeAtr(&availableProtocols, &defaultProtocol,
677  rContext->readerState->cardAtr,
678  rContext->readerState->cardAtrLength);
679 
680  /* If it is set to ANY let it do any of the protocols */
681  if (dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD)
682  dwPreferredProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
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  /*
712  * If it is set to ANY let it do any of the protocols
713  */
714  if (dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD)
715  dwPreferredProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
716 
717  if (! (dwPreferredProtocols & rContext->readerState->cardProtocol))
718  {
720  goto exit;
721  }
722  }
723 
724  /* the card is now in use */
725  RFSetPowerState(rContext, POWER_STATE_IN_USE);
726  Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_IN_USE");
727  }
728  }
729 
730  *pdwActiveProtocol = rContext->readerState->cardProtocol;
731 
732  if (dwShareMode != SCARD_SHARE_DIRECT)
733  {
734  switch (*pdwActiveProtocol)
735  {
736  case SCARD_PROTOCOL_T0:
737  case SCARD_PROTOCOL_T1:
738  Log2(PCSC_LOG_DEBUG, "Active Protocol: T=%d",
739  (*pdwActiveProtocol == SCARD_PROTOCOL_T0) ? 0 : 1);
740  break;
741 
742  case SCARD_PROTOCOL_RAW:
743  Log1(PCSC_LOG_DEBUG, "Active Protocol: RAW");
744  break;
745 
746  default:
747  Log2(PCSC_LOG_ERROR, "Active Protocol: unknown %ld",
748  *pdwActiveProtocol);
749  }
750  }
751  else
752  Log1(PCSC_LOG_DEBUG, "Direct access: no protocol selected");
753 
754  if (dwShareMode == SCARD_SHARE_EXCLUSIVE)
755  {
757  {
758  /*
759  * Do nothing - we are already exclusive
760  */
761  }
762  else
763  {
764  if (rContext->contexts == PCSCLITE_SHARING_LAST_CONTEXT)
765  {
767  (void)RFLockSharing(hCard, rContext);
768  }
769  else
770  {
772  goto exit;
773  }
774  }
775  }
776  else if (dwShareMode == SCARD_SHARE_SHARED)
777  {
779  {
780  /*
781  * Do nothing - in sharing mode already
782  */
783  }
784  else
785  {
786  /*
787  * We are in exclusive mode but want to share now
788  */
789  (void)RFUnlockSharing(hCard, rContext);
791  }
792  }
793  else if (dwShareMode == SCARD_SHARE_DIRECT)
794  {
796  {
797  /*
798  * Do nothing - in sharing mode already
799  */
800  }
801  else
802  {
803  /*
804  * We are in exclusive mode but want to share now
805  */
806  (void)RFUnlockSharing(hCard, rContext);
808  }
809  }
810  else
811  {
813  goto exit;
814  }
815 
816  /*
817  * Clear a previous event to the application
818  */
819  (void)RFClearReaderEventState(rContext, hCard);
820 
821  /*
822  * Propagate new state to reader state
823  */
824  rContext->readerState->readerSharing = rContext->contexts;
825 
826  rv = SCARD_S_SUCCESS;
827 
828 exit:
829  UNREF_READER(rContext)
830 
831  return rv;
832 }
833 
834 LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
835 {
836  LONG rv;
837  READER_CONTEXT * rContext = NULL;
838 
839  if (hCard == 0)
840  return SCARD_E_INVALID_HANDLE;
841 
842  if ((dwDisposition != SCARD_LEAVE_CARD)
843  && (dwDisposition != SCARD_UNPOWER_CARD)
844  && (dwDisposition != SCARD_RESET_CARD)
845  && (dwDisposition != SCARD_EJECT_CARD))
846  return SCARD_E_INVALID_VALUE;
847 
848  /* get rContext corresponding to hCard */
849  rv = RFReaderInfoById(hCard, &rContext);
850  /* ignore reader removal */
852  return SCARD_S_SUCCESS;
853  if (rv != SCARD_S_SUCCESS)
854  return rv;
855 
856  /*
857  * wait until a possible transaction is finished
858  */
859  if ((dwDisposition != SCARD_LEAVE_CARD) && (rContext->hLockId != 0)
860  && (rContext->hLockId != hCard))
861  {
862  Log1(PCSC_LOG_INFO, "Waiting for release of lock");
863  while (rContext->hLockId != 0)
865  Log1(PCSC_LOG_INFO, "Lock released");
866  }
867 
868  /*
869  * Try to unlock any blocks on this context
870  *
871  * This may fail with SCARD_E_SHARING_VIOLATION if a transaction is
872  * on going on another card context and dwDisposition == SCARD_LEAVE_CARD.
873  * We should not stop.
874  */
875  rv = RFUnlockAllSharing(hCard, rContext);
876  if (rv != SCARD_S_SUCCESS)
877  {
878  if (rv != SCARD_E_SHARING_VIOLATION)
879  {
880  goto exit;
881  }
882  else
883  {
884  if (SCARD_LEAVE_CARD != dwDisposition)
885  goto exit;
886  }
887  }
888 
889  Log2(PCSC_LOG_DEBUG, "Active Contexts: %d", rContext->contexts);
890  Log2(PCSC_LOG_DEBUG, "dwDisposition: %ld", dwDisposition);
891 
892  if (dwDisposition == SCARD_RESET_CARD ||
893  dwDisposition == SCARD_UNPOWER_CARD)
894  {
895  DWORD dwAtrLen;
896 
897  /*
898  * Notify the card has been reset
899  */
900  RFSetReaderEventState(rContext, SCARD_RESET);
901 
902  dwAtrLen = sizeof(rContext->readerState->cardAtr);
903  if (SCARD_RESET_CARD == dwDisposition)
904  rv = IFDPowerICC(rContext, IFD_RESET,
905  rContext->readerState->cardAtr, &dwAtrLen);
906  else
907  {
908  /* SCARD_UNPOWER_CARD */
909  rv = IFDPowerICC(rContext, IFD_POWER_DOWN, NULL, NULL);
910 
911  RFSetPowerState(rContext, POWER_STATE_UNPOWERED);
912  Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_UNPOWERED");
913  }
914 
915  /* the protocol is unset after a power on */
917 
918  if (rv == IFD_SUCCESS)
919  {
920  if (SCARD_UNPOWER_CARD == dwDisposition)
922  else
923  {
924  rContext->readerState->cardAtrLength = dwAtrLen;
925  rContext->readerState->readerState =
927 
928  Log1(PCSC_LOG_DEBUG, "Reset complete.");
929  LogXxd(PCSC_LOG_DEBUG, "Card ATR: ",
930  rContext->readerState->cardAtr,
931  rContext->readerState->cardAtrLength);
932  }
933  }
934  else
935  {
936  if (SCARD_UNPOWER_CARD == dwDisposition)
937  Log2(PCSC_LOG_ERROR, "Error powering down card: %s",
938  rv2text(rv));
939  else
940  {
941  rContext->readerState->cardAtrLength = 0;
942  Log1(PCSC_LOG_ERROR, "Error resetting card.");
943  }
944 
945  if (rv == SCARD_W_REMOVED_CARD)
946  rContext->readerState->readerState = SCARD_ABSENT;
947  else
948  rContext->readerState->readerState =
950  }
951  }
952  else if (dwDisposition == SCARD_EJECT_CARD)
953  {
954  UCHAR controlBuffer[5];
955  UCHAR receiveBuffer[MAX_BUFFER_SIZE];
956  DWORD receiveLength;
957 
958  /*
959  * Set up the CTBCS command for Eject ICC
960  */
961  controlBuffer[0] = 0x20;
962  controlBuffer[1] = 0x15;
963  controlBuffer[2] = (rContext->slot & 0x0000FFFF) + 1;
964  controlBuffer[3] = 0x00;
965  controlBuffer[4] = 0x00;
966  receiveLength = 2;
967  rv = IFDControl_v2(rContext, controlBuffer, 5, receiveBuffer,
968  &receiveLength);
969 
970  if (rv == SCARD_S_SUCCESS)
971  {
972  if (receiveLength == 2 && receiveBuffer[0] == 0x90)
973  {
974  Log1(PCSC_LOG_DEBUG, "Card ejected successfully.");
975  /*
976  * Successful
977  */
978  }
979  else
980  Log1(PCSC_LOG_ERROR, "Error ejecting card.");
981  }
982  else
983  Log1(PCSC_LOG_ERROR, "Error ejecting card.");
984 
985  }
986  else if (dwDisposition == SCARD_LEAVE_CARD)
987  {
988  /*
989  * Do nothing
990  */
991  }
992 
993  /*
994  * Remove and destroy this handle
995  */
996  (void)RFRemoveReaderHandle(rContext, hCard);
997 
998  /*
999  * For exclusive connection reset it to no connections
1000  */
1003  else
1004  {
1005  /*
1006  * Remove a connection from the context stack
1007  */
1008  rContext->contexts -= 1;
1009 
1010  if (rContext->contexts < 0)
1011  rContext->contexts = 0;
1012  }
1013 
1014  if (PCSCLITE_SHARING_NO_CONTEXT == rContext->contexts)
1015  {
1016  RESPONSECODE (*fct)(DWORD) = NULL;
1017  DWORD dwGetSize;
1018 
1019  (void)pthread_mutex_lock(&rContext->powerState_lock);
1020  /* Switch to POWER_STATE_GRACE_PERIOD unless the card was not
1021  * powered */
1022  if (POWER_STATE_POWERED <= rContext->powerState)
1023  {
1025  Log1(PCSC_LOG_DEBUG, "powerState: POWER_STATE_GRACE_PERIOD");
1026  }
1027 
1028  (void)pthread_mutex_unlock(&rContext->powerState_lock);
1029 
1030  /* ask to stop the "polling" thread so it can be restarted using
1031  * the correct timeout */
1032  dwGetSize = sizeof(fct);
1034  &dwGetSize, (PUCHAR)&fct);
1035 
1036  if ((IFD_SUCCESS == rv) && (dwGetSize == sizeof(fct)))
1037  {
1038  Log1(PCSC_LOG_INFO, "Stopping polling thread");
1039  fct(rContext->slot);
1040  }
1041  }
1042 
1043  /*
1044  * Propagate new state to reader state
1045  */
1046  rContext->readerState->readerSharing = rContext->contexts;
1047 
1048  rv = SCARD_S_SUCCESS;
1049 
1050 exit:
1051  UNREF_READER(rContext)
1052 
1053  return rv;
1054 }
1055 
1056 LONG SCardBeginTransaction(SCARDHANDLE hCard)
1057 {
1058  LONG rv;
1059  READER_CONTEXT * rContext;
1060 
1061  if (hCard == 0)
1062  return SCARD_E_INVALID_HANDLE;
1063 
1064  /* get rContext corresponding to hCard */
1065  rv = RFReaderInfoById(hCard, &rContext);
1066  if (rv != SCARD_S_SUCCESS)
1067  return rv;
1068 
1069  /*
1070  * Make sure the reader is working properly
1071  */
1072  rv = RFCheckReaderStatus(rContext);
1073  if (rv != SCARD_S_SUCCESS)
1074  goto exit;
1075 
1076  /*
1077  * Make sure some event has not occurred
1078  */
1079  rv = RFCheckReaderEventState(rContext, hCard);
1080  if (rv != SCARD_S_SUCCESS)
1081  goto exit;
1082 
1083  rv = RFLockSharing(hCard, rContext);
1084 
1085  /* if the transaction is not yet ready we sleep a bit so the client
1086  * do not retry immediately */
1087  if (SCARD_E_SHARING_VIOLATION == rv)
1089 
1090  Log2(PCSC_LOG_DEBUG, "Status: %s", rv2text(rv));
1091 
1092 exit:
1093  UNREF_READER(rContext)
1094 
1095  return rv;
1096 }
1097 
1098 LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
1099 {
1100  LONG rv;
1101  LONG rv2;
1102  READER_CONTEXT * rContext = NULL;
1103 
1104  /*
1105  * Ignoring dwDisposition for now
1106  */
1107  if (hCard == 0)
1108  return SCARD_E_INVALID_HANDLE;
1109 
1110  if ((dwDisposition != SCARD_LEAVE_CARD)
1111  && (dwDisposition != SCARD_UNPOWER_CARD)
1112  && (dwDisposition != SCARD_RESET_CARD)
1113  && (dwDisposition != SCARD_EJECT_CARD))
1114  return SCARD_E_INVALID_VALUE;
1115 
1116  /* get rContext corresponding to hCard */
1117  rv = RFReaderInfoById(hCard, &rContext);
1118  if (rv != SCARD_S_SUCCESS)
1119  return rv;
1120 
1121  /*
1122  * Make sure some event has not occurred
1123  */
1124  rv = RFCheckReaderEventState(rContext, hCard);
1125  if (rv != SCARD_S_SUCCESS)
1126  goto exit;
1127 
1128  /*
1129  * Error if another transaction is ongoing and a card action is
1130  * requested
1131  */
1132  if ((dwDisposition != SCARD_LEAVE_CARD) && (rContext->hLockId != 0)
1133  && (rContext->hLockId != hCard))
1134  {
1135  Log1(PCSC_LOG_INFO, "No card reset within a transaction");
1137  goto exit;
1138  }
1139 
1140  if (dwDisposition == SCARD_RESET_CARD ||
1141  dwDisposition == SCARD_UNPOWER_CARD)
1142  {
1143  DWORD dwAtrLen;
1144 
1145  dwAtrLen = sizeof(rContext->readerState->cardAtr);
1146  if (SCARD_RESET_CARD == dwDisposition)
1147  rv = IFDPowerICC(rContext, IFD_RESET,
1148  rContext->readerState->cardAtr, &dwAtrLen);
1149  else
1150  {
1151  IFDPowerICC(rContext, IFD_POWER_DOWN, NULL, NULL);
1152  rv = IFDPowerICC(rContext, IFD_POWER_UP,
1153  rContext->readerState->cardAtr, &dwAtrLen);
1154  }
1155 
1156  /* the protocol is unset after a power on */
1158 
1159  /*
1160  * Notify the card has been reset
1161  */
1162  RFSetReaderEventState(rContext, SCARD_RESET);
1163 
1164  /*
1165  * Set up the status bit masks on readerState
1166  */
1167  if (rv == IFD_SUCCESS)
1168  {
1169  rContext->readerState->cardAtrLength = dwAtrLen;
1170  rContext->readerState->readerState =
1172 
1173  Log1(PCSC_LOG_DEBUG, "Reset complete.");
1174  LogXxd(PCSC_LOG_DEBUG, "Card ATR: ",
1175  rContext->readerState->cardAtr,
1176  rContext->readerState->cardAtrLength);
1177  }
1178  else
1179  {
1180  rContext->readerState->cardAtrLength = 0;
1181  Log1(PCSC_LOG_ERROR, "Error resetting card.");
1182 
1183  if (rv == SCARD_W_REMOVED_CARD)
1184  rContext->readerState->readerState = SCARD_ABSENT;
1185  else
1186  rContext->readerState->readerState =
1188  }
1189  }
1190  else if (dwDisposition == SCARD_EJECT_CARD)
1191  {
1192  UCHAR controlBuffer[5];
1193  UCHAR receiveBuffer[MAX_BUFFER_SIZE];
1194  DWORD receiveLength;
1195 
1196  /*
1197  * Set up the CTBCS command for Eject ICC
1198  */
1199  controlBuffer[0] = 0x20;
1200  controlBuffer[1] = 0x15;
1201  controlBuffer[2] = (rContext->slot & 0x0000FFFF) + 1;
1202  controlBuffer[3] = 0x00;
1203  controlBuffer[4] = 0x00;
1204  receiveLength = 2;
1205  rv = IFDControl_v2(rContext, controlBuffer, 5, receiveBuffer,
1206  &receiveLength);
1207 
1208  if (rv == SCARD_S_SUCCESS)
1209  {
1210  if (receiveLength == 2 && receiveBuffer[0] == 0x90)
1211  {
1212  Log1(PCSC_LOG_DEBUG, "Card ejected successfully.");
1213  /*
1214  * Successful
1215  */
1216  }
1217  else
1218  Log1(PCSC_LOG_ERROR, "Error ejecting card.");
1219  }
1220  else
1221  Log1(PCSC_LOG_ERROR, "Error ejecting card.");
1222 
1223  }
1224  else if (dwDisposition == SCARD_LEAVE_CARD)
1225  {
1226  /*
1227  * Do nothing
1228  */
1229  }
1230 
1231  /*
1232  * Unlock any blocks on this context
1233  */
1234  /* we do not want to lose the previous rv value
1235  * So we use another variable */
1236  rv2 = RFUnlockSharing(hCard, rContext);
1237  if (rv2 != SCARD_S_SUCCESS)
1238  /* if rv is already in error then do not change its value */
1239  if (rv == SCARD_S_SUCCESS)
1240  rv = rv2;
1241 
1242  Log2(PCSC_LOG_DEBUG, "Status: %s", rv2text(rv));
1243 
1244 exit:
1245  UNREF_READER(rContext)
1246 
1247  return rv;
1248 }
1249 
1250 LONG SCardStatus(SCARDHANDLE hCard, LPSTR szReaderNames,
1251  LPDWORD pcchReaderLen, LPDWORD pdwState,
1252  LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
1253 {
1254  LONG rv;
1255  READER_CONTEXT * rContext = NULL;
1256 
1257  /* These parameters are not used by the client
1258  * Client side code uses readerStates[] instead */
1259  (void)szReaderNames;
1260  (void)pcchReaderLen;
1261  (void)pdwState;
1262  (void)pdwProtocol;
1263  (void)pbAtr;
1264  (void)pcbAtrLen;
1265 
1266  if (hCard == 0)
1267  return SCARD_E_INVALID_HANDLE;
1268 
1269  /* get rContext corresponding to hCard */
1270  rv = RFReaderInfoById(hCard, &rContext);
1271  if (rv != SCARD_S_SUCCESS)
1272  return rv;
1273 
1274  /*
1275  * Make sure no one has a lock on this reader
1276  */
1277  rv = RFCheckSharing(hCard, rContext);
1278  if (rv != SCARD_S_SUCCESS)
1279  goto exit;
1280 
1281  if (rContext->readerState->cardAtrLength > MAX_ATR_SIZE)
1282  {
1284  goto exit;
1285  }
1286 
1287  /*
1288  * This is a client side function however the server maintains the
1289  * list of events between applications so it must be passed through to
1290  * obtain this event if it has occurred
1291  */
1292 
1293  /*
1294  * Make sure some event has not occurred
1295  */
1296  rv = RFCheckReaderEventState(rContext, hCard);
1297  if (rv != SCARD_S_SUCCESS)
1298  goto exit;
1299 
1300  /*
1301  * Make sure the reader is working properly
1302  */
1303  rv = RFCheckReaderStatus(rContext);
1304  if (rv != SCARD_S_SUCCESS)
1305  goto exit;
1306 
1307 exit:
1308  UNREF_READER(rContext)
1309 
1310  return rv;
1311 }
1312 
1313 LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode,
1314  LPCVOID pbSendBuffer, DWORD cbSendLength,
1315  LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned)
1316 {
1317  LONG rv;
1318  READER_CONTEXT * rContext = NULL;
1319 
1320  /* 0 bytes returned by default */
1321  *lpBytesReturned = 0;
1322 
1323  if (0 == hCard)
1324  return SCARD_E_INVALID_HANDLE;
1325 
1326  /* get rContext corresponding to hCard */
1327  rv = RFReaderInfoById(hCard, &rContext);
1328  if (rv != SCARD_S_SUCCESS)
1329  return rv;
1330 
1331  /*
1332  * Make sure no one has a lock on this reader
1333  */
1334  rv = RFCheckSharing(hCard, rContext);
1335  if (rv != SCARD_S_SUCCESS)
1336  goto exit;
1337 
1338  if (IFD_HVERSION_2_0 == rContext->version)
1339  if (NULL == pbSendBuffer || 0 == cbSendLength)
1340  {
1342  goto exit;
1343  }
1344 
1345  /*
1346  * Make sure the reader is working properly
1347  */
1348  rv = RFCheckReaderStatus(rContext);
1349  if (rv != SCARD_S_SUCCESS)
1350  goto exit;
1351 
1352  if (IFD_HVERSION_2_0 == rContext->version)
1353  {
1354  /* we must wrap a API 3.0 client in an API 2.0 driver */
1355  *lpBytesReturned = cbRecvLength;
1356  rv = IFDControl_v2(rContext, (PUCHAR)pbSendBuffer,
1357  cbSendLength, pbRecvBuffer, lpBytesReturned);
1358  }
1359  else
1360  if (IFD_HVERSION_3_0 == rContext->version)
1361  rv = IFDControl(rContext, dwControlCode, pbSendBuffer,
1362  cbSendLength, pbRecvBuffer, cbRecvLength, lpBytesReturned);
1363  else
1365 
1366 exit:
1367  UNREF_READER(rContext)
1368 
1369  return rv;
1370 }
1371 
1372 LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId,
1373  LPBYTE pbAttr, LPDWORD pcbAttrLen)
1374 {
1375  LONG rv;
1376  READER_CONTEXT * rContext = NULL;
1377 
1378  if (0 == hCard)
1379  return SCARD_E_INVALID_HANDLE;
1380 
1381  /* get rContext corresponding to hCard */
1382  rv = RFReaderInfoById(hCard, &rContext);
1383  if (rv != SCARD_S_SUCCESS)
1384  return rv;
1385 
1386  /*
1387  * Make sure no one has a lock on this reader
1388  */
1389  rv = RFCheckSharing(hCard, rContext);
1390  if (rv != SCARD_S_SUCCESS)
1391  goto exit;
1392 
1393  /*
1394  * Make sure the reader is working properly
1395  */
1396  rv = RFCheckReaderStatus(rContext);
1397  if (rv != SCARD_S_SUCCESS)
1398  goto exit;
1399 
1400  /*
1401  * Make sure some event has not occurred
1402  */
1403  rv = RFCheckReaderEventState(rContext, hCard);
1404  if (rv != SCARD_S_SUCCESS)
1405  goto exit;
1406 
1407  rv = IFDGetCapabilities(rContext, dwAttrId, pcbAttrLen, pbAttr);
1408  switch(rv)
1409  {
1410  case IFD_SUCCESS:
1411  rv = SCARD_S_SUCCESS;
1412  break;
1413  case IFD_ERROR_TAG:
1414  /* Special case SCARD_ATTR_DEVICE_FRIENDLY_NAME as it is better
1415  * implemented in pcscd (it knows the friendly name)
1416  */
1417  if ((SCARD_ATTR_DEVICE_FRIENDLY_NAME == dwAttrId)
1418  || (SCARD_ATTR_DEVICE_SYSTEM_NAME == dwAttrId))
1419  {
1420  unsigned int len = strlen(rContext->readerState->readerName)+1;
1421 
1422  if (len > *pcbAttrLen)
1424  else
1425  {
1426  strcpy((char *)pbAttr, rContext->readerState->readerName);
1427  rv = SCARD_S_SUCCESS;
1428  }
1429  *pcbAttrLen = len;
1430  }
1431  else
1433  break;
1436  break;
1437  default:
1439  }
1440 
1441 exit:
1442  UNREF_READER(rContext)
1443 
1444  return rv;
1445 }
1446 
1447 LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId,
1448  LPCBYTE pbAttr, DWORD cbAttrLen)
1449 {
1450  LONG rv;
1451  READER_CONTEXT * rContext = NULL;
1452 
1453  if (0 == hCard)
1454  return SCARD_E_INVALID_HANDLE;
1455 
1456  /* get rContext corresponding to hCard */
1457  rv = RFReaderInfoById(hCard, &rContext);
1458  if (rv != SCARD_S_SUCCESS)
1459  return rv;
1460 
1461  /*
1462  * Make sure no one has a lock on this reader
1463  */
1464  rv = RFCheckSharing(hCard, rContext);
1465  if (rv != SCARD_S_SUCCESS)
1466  goto exit;
1467 
1468  /*
1469  * Make sure the reader is working properly
1470  */
1471  rv = RFCheckReaderStatus(rContext);
1472  if (rv != SCARD_S_SUCCESS)
1473  goto exit;
1474 
1475  /*
1476  * Make sure some event has not occurred
1477  */
1478  rv = RFCheckReaderEventState(rContext, hCard);
1479  if (rv != SCARD_S_SUCCESS)
1480  goto exit;
1481 
1482  rv = IFDSetCapabilities(rContext, dwAttrId, cbAttrLen, (PUCHAR)pbAttr);
1483  if (rv == IFD_SUCCESS)
1484  rv = SCARD_S_SUCCESS;
1485  else
1486  if (rv == IFD_ERROR_TAG)
1488  else
1490 
1491 exit:
1492  UNREF_READER(rContext)
1493 
1494  return rv;
1495 }
1496 
1497 LONG SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci,
1498  LPCBYTE pbSendBuffer, DWORD cbSendLength,
1499  SCARD_IO_REQUEST *pioRecvPci, LPBYTE pbRecvBuffer,
1500  LPDWORD pcbRecvLength)
1501 {
1502  LONG rv;
1503  READER_CONTEXT * rContext = NULL;
1504  SCARD_IO_HEADER sSendPci, sRecvPci;
1505  DWORD dwRxLength, tempRxLength;
1506 
1507  dwRxLength = *pcbRecvLength;
1508  *pcbRecvLength = 0;
1509 
1510  if (hCard == 0)
1511  return SCARD_E_INVALID_HANDLE;
1512 
1513  /*
1514  * Must at least have 2 status words even for SCardControl
1515  */
1516  if (dwRxLength < 2)
1518 
1519  /* get rContext corresponding to hCard */
1520  rv = RFReaderInfoById(hCard, &rContext);
1521  if (rv != SCARD_S_SUCCESS)
1522  return rv;
1523 
1524  /*
1525  * Make sure no one has a lock on this reader
1526  */
1527  rv = RFCheckSharing(hCard, rContext);
1528  if (rv != SCARD_S_SUCCESS)
1529  goto exit;
1530 
1531  /*
1532  * Make sure the reader is working properly
1533  */
1534  rv = RFCheckReaderStatus(rContext);
1535  if (rv != SCARD_S_SUCCESS)
1536  goto exit;
1537 
1538  /*
1539  * Make sure some event has not occurred
1540  */
1541  rv = RFCheckReaderEventState(rContext, hCard);
1542  if (rv != SCARD_S_SUCCESS)
1543  goto exit;
1544 
1545  /*
1546  * Check for some common errors
1547  */
1548  if (pioSendPci->dwProtocol != SCARD_PROTOCOL_RAW)
1549  {
1550  if (rContext->readerState->readerState & SCARD_ABSENT)
1551  {
1552  rv = SCARD_E_NO_SMARTCARD;
1553  goto exit;
1554  }
1555  }
1556 
1557  if (pioSendPci->dwProtocol != SCARD_PROTOCOL_RAW)
1558  {
1559  if (pioSendPci->dwProtocol != SCARD_PROTOCOL_ANY_OLD)
1560  {
1561  if (pioSendPci->dwProtocol != rContext->readerState->cardProtocol)
1562  {
1564  goto exit;
1565  }
1566  }
1567  }
1568 
1569  /*
1570  * Quick fix: PC/SC starts at 1 for bit masking but the IFD_Handler
1571  * just wants 0 or 1
1572  */
1573 
1574  sSendPci.Protocol = 0; /* protocol T=0 by default */
1575 
1576  if (pioSendPci->dwProtocol == SCARD_PROTOCOL_T1)
1577  {
1578  sSendPci.Protocol = 1;
1579  } else if (pioSendPci->dwProtocol == SCARD_PROTOCOL_RAW)
1580  {
1581  /*
1582  * This is temporary ......
1583  */
1584  sSendPci.Protocol = SCARD_PROTOCOL_RAW;
1585  } else if (pioSendPci->dwProtocol == SCARD_PROTOCOL_ANY_OLD)
1586  {
1587  /* Fix by Amira (Athena) */
1588  unsigned long i;
1589  unsigned long prot = rContext->readerState->cardProtocol;
1590 
1591  for (i = 0 ; prot != 1 && i < 16; i++)
1592  prot >>= 1;
1593 
1594  sSendPci.Protocol = i;
1595  }
1596 
1597  sSendPci.Length = pioSendPci->cbPciLength;
1598 
1599  sRecvPci.Protocol = pioRecvPci->dwProtocol;
1600  sRecvPci.Length = pioRecvPci->cbPciLength;
1601 
1602  /* the protocol number is decoded a few lines above */
1603  Log2(PCSC_LOG_DEBUG, "Send Protocol: T=%ld", sSendPci.Protocol);
1604 
1605  tempRxLength = dwRxLength;
1606 
1607  if ((pioSendPci->dwProtocol == SCARD_PROTOCOL_RAW)
1608  && (rContext->version == IFD_HVERSION_2_0))
1609  {
1610  rv = IFDControl_v2(rContext, (PUCHAR) pbSendBuffer, cbSendLength,
1611  pbRecvBuffer, &dwRxLength);
1612  } else
1613  {
1614  rv = IFDTransmit(rContext, sSendPci, (PUCHAR) pbSendBuffer,
1615  cbSendLength, pbRecvBuffer, &dwRxLength, &sRecvPci);
1616  }
1617 
1618  pioRecvPci->dwProtocol = sRecvPci.Protocol;
1619  pioRecvPci->cbPciLength = sRecvPci.Length;
1620 
1621  /*
1622  * Check for any errors that might have occurred
1623  */
1624 
1625  if (rv != SCARD_S_SUCCESS)
1626  {
1627  *pcbRecvLength = 0;
1628  Log2(PCSC_LOG_ERROR, "Card not transacted: %s", rv2text(rv));
1629 
1630  if (SCARD_E_NO_SMARTCARD == rv)
1631  {
1632  rContext->readerState->cardAtrLength = 0;
1634  rContext->readerState->readerState = SCARD_ABSENT;
1635  }
1636 
1637  goto exit;
1638  }
1639 
1640  /*
1641  * Available is less than received
1642  */
1643  if (tempRxLength < dwRxLength)
1644  {
1645  *pcbRecvLength = 0;
1647  goto exit;
1648  }
1649 
1650  /*
1651  * Successful return
1652  */
1653  *pcbRecvLength = dwRxLength;
1654 
1655 exit:
1656  UNREF_READER(rContext)
1657 
1658  return rv;
1659 }
1660 
struct pubReaderStatesList * readerState
link to the reader state
#define SCARD_E_INVALID_VALUE
One or more of the supplied parameters values could not be properly interpreted.
Definition: pcsclite.h:141
#define SCARD_ATTR_DEVICE_FRIENDLY_NAME
Reader's display name.
Definition: reader.h:111
#define IFD_ERROR_TAG
tag unknown
Definition: ifdhandler.h:352
#define SCARD_SCOPE_USER
Scope in user space.
Definition: pcsclite.h:234
#define TAG_IFD_STOP_POLLING_THREAD
method used to stop the polling thread (instead of just pthread_kill())
Definition: ifdhandler.h:329
#define SCARD_ATTR_DEVICE_SYSTEM_NAME
Reader's system name.
Definition: reader.h:112
#define SCARD_S_SUCCESS
No error was encountered.
Definition: pcsclite.h:107
#define PCSCLITE_SHARING_NO_CONTEXT
No application is using the reader.
Definition: eventhandler.h:77
#define SCARD_SCOPE_GLOBAL
Scope is global.
Definition: pcsclite.h:237
#define MAX_BUFFER_SIZE
Maximum Tx/Rx Buffer for short APDU.
Definition: pcsclite.h:297
_Atomic uint32_t cardAtrLength
ATR length.
Definition: eventhandler.h:60
#define SCARD_E_INVALID_PARAMETER
One or more of the supplied parameters could not be properly interpreted.
Definition: pcsclite.h:115
This keeps a list of defines shared between the driver and the application.
char readerName[MAX_READERNAME]
reader name
Definition: eventhandler.h:54
unsigned long cbPciLength
Protocol Control Inf Length.
Definition: pcsclite.h:82
#define SCARD_LEAVE_CARD
Do nothing on close.
Definition: pcsclite.h:252
This handles protocol defaults, PTS, etc.
This handles abstract system level calls.
int slot
Current Reader Slot.
#define SCARD_E_NO_SMARTCARD
The operation requires a Smart Card, but no Smart Card is currently in the device.
Definition: pcsclite.h:131
This wraps the dynamic ifdhandler functions.
#define SCARD_W_UNRESPONSIVE_CARD
The smart card is not responding to a reset.
Definition: pcsclite.h:212
#define SCARD_E_NOT_TRANSACTED
An attempt was made to end a non-existent transaction.
Definition: pcsclite.h:151
#define SCARD_PROTOCOL_T1
T=1 active protocol.
Definition: pcsclite.h:242
#define SCARD_SCOPE_TERMINAL
Scope in terminal.
Definition: pcsclite.h:235
#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_PROTOCOL_ANY_OLD
used for backward compatibility
Definition: winscard.c:186
#define SCARD_PRESENT
Card is present.
Definition: pcsclite.h:259
int SYS_USleep(int)
Makes the current process sleep for some microseconds.
Definition: sys_unix.c:80
RESPONSECODE IFDGetCapabilities(READER_CONTEXT *rContext, DWORD dwTag, PDWORD pdwLength, PUCHAR pucValue)
Gets capabilities in the reader.
Definition: ifdwrapper.c:235
#define SCARD_NEGOTIABLE
Ready for PTS.
Definition: pcsclite.h:262
#define PCSCLITE_SHARING_EXCLUSIVE_CONTEXT
Reader used in exclusive mode.
Definition: eventhandler.h:79
_Atomic SCARDHANDLE hLockId
Lock Id.
#define PCSCLITE_LOCK_POLL_RATE
Lock polling rate.
Definition: pcscd.h:54
LONG SCARDCONTEXT
hContext returned by SCardEstablishContext()
Definition: pcsclite.h:52
This keeps track of smart card protocols, timing issues and Answer to Reset ATR handling.
#define SCARD_E_READER_UNAVAILABLE
The specified reader is not currently available for use.
Definition: pcsclite.h:153
#define SCARD_RESET
Card was reset.
Definition: pcscd.h:41
#define SCARD_SHARE_SHARED
Shared mode only.
Definition: pcsclite.h:249
LONG IFDTransmit(READER_CONTEXT *rContext, SCARD_IO_HEADER pioTxPci, PUCHAR pucTxBuffer, DWORD dwTxLength, PUCHAR pucRxBuffer, PDWORD pdwRxLength, PSCARD_IO_HEADER pioRxPci)
Transmit an APDU to the ICC.
Definition: ifdwrapper.c:502
unsigned long dwProtocol
Protocol identifier.
Definition: pcsclite.h:81
#define IFD_POWER_DOWN
power down the card
Definition: ifdhandler.h:344
int version
IFD Handler version number.
#define SCARD_PROTOCOL_T0
T=0 active protocol.
Definition: pcsclite.h:241
pthread_mutex_t * mMutex
Mutex for this connection.
card is used
Definition: pcscd.h:66
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
short ATRDecodeAtr(int *availableProtocols, int *currentProtocol, PUCHAR pucAtr, DWORD dwLength)
parse an ATR
Definition: atrhandler.c:66
This handles card insertion/removal events, updates ATR, protocol, and status information.
#define SCARD_UNPOWER_CARD
Power down on close.
Definition: pcsclite.h:254
RESPONSECODE IFDPowerICC(READER_CONTEXT *rContext, DWORD dwAction, PUCHAR pucAtr, PDWORD pdwAtrLen)
Power up/down or reset's an ICC located in the IFD.
Definition: ifdwrapper.c:265
#define SCARD_SWALLOWED
Card not powered.
Definition: pcsclite.h:260
#define SCARD_W_REMOVED_CARD
The smart card has been removed, so further communication is not possible.
Definition: pcsclite.h:218
int powerState
auto power off state
#define SCARD_PROTOCOL_UNDEFINED
protocol not set
Definition: pcsclite.h:239
#define SCARD_RESET_CARD
Reset on close.
Definition: pcsclite.h:253
UCHAR cardAtr[MAX_ATR_SIZE]
ATR.
Definition: eventhandler.h:59
LONG SCARDHANDLE
hCard returned by SCardConnect()
Definition: pcsclite.h:55
#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_SHARE_EXCLUSIVE
Exclusive mode only.
Definition: pcsclite.h:248
#define SCARD_POWERED
Card is powered.
Definition: pcsclite.h:261
_Atomic int32_t readerSharing
PCSCLITE_SHARING_* sharing status.
Definition: eventhandler.h:57
card was in use
Definition: pcscd.h:65
DWORD PHSetProtocol(struct ReaderContext *rContext, DWORD dwPreferred, UCHAR ucAvailable, UCHAR ucDefault)
Determine which protocol to use.
Definition: prothandler.c:60
This keeps a list of defines for pcsc-lite.
#define SCARD_PROTOCOL_RAW
Raw active protocol.
Definition: pcsclite.h:243
_Atomic int32_t contexts
Number of open contexts.
#define SCARD_EJECT_CARD
Eject on close.
Definition: pcsclite.h:255
Protocol Control Information (PCI)
Definition: pcsclite.h:79
#define SCARD_ABSENT
Card is absent.
Definition: pcsclite.h:258
uint32_t cardProtocol
SCARD_PROTOCOL_* value.
Definition: eventhandler.h:61
auto power off
Definition: pcscd.h:63
#define SCARD_E_SHARING_VIOLATION
The smart card cannot be accessed because of other connections outstanding.
Definition: pcsclite.h:129
This keeps track of a list of currently available reader structures.
#define MAX_ATR_SIZE
Maximum ATR size.
Definition: pcsclite.h:59
#define IFD_ERROR_INSUFFICIENT_BUFFER
buffer is too small
Definition: ifdhandler.h:373
uint32_t readerState
SCARD_* bit field.
Definition: eventhandler.h:56
#define SCARD_F_INTERNAL_ERROR
An internal consistency check failed.
Definition: pcsclite.h:109
#define SCARD_SHARE_DIRECT
Raw mode only.
Definition: pcsclite.h:250
#define PCSCLITE_SHARING_LAST_CONTEXT
One application is using the reader.
Definition: eventhandler.h:75
RESPONSECODE IFDSetCapabilities(READER_CONTEXT *rContext, DWORD dwTag, DWORD dwLength, PUCHAR pucValue)
Set capabilities in the reader.
Definition: ifdwrapper.c:204
pthread_mutex_t powerState_lock
powerState mutex
#define SCARD_E_UNSUPPORTED_FEATURE
This smart card does not support the requested feature.
Definition: pcsclite.h:171
Use by SCardTransmit()
Definition: ifdhandler.h:310
#define SCARD_E_INVALID_HANDLE
The supplied handle was invalid.
Definition: pcsclite.h:113
#define IFD_RESET
warm reset
Definition: ifdhandler.h:345
int SYS_RandomInt(void)
Generate a pseudo random number.
Definition: sys_unix.c:108
#define SCARD_SCOPE_SYSTEM
Scope in system.
Definition: pcsclite.h:236
This handles smart card reader communications.
#define IFD_POWER_UP
power up the card
Definition: ifdhandler.h:343
This handles debugging.
#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, biometric.
Definition: ifdwrapper.c:442
#define SCARD_W_UNPOWERED_CARD
Power has been removed from the smart card, so that further communication is not possible.
Definition: pcsclite.h:214