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