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