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