/[pcsclite]/trunk/Drivers/ccid/src/ifdhandler.c
ViewVC logotype

Diff of /trunk/Drivers/ccid/src/ifdhandler.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1477 by rousseau, Wed Apr 27 14:08:35 2005 UTC revision 2197 by rousseau, Wed Nov 15 10:04:18 2006 UTC
# Line 22  Line 22 
22  #include <stdio.h>  #include <stdio.h>
23  #include <string.h>  #include <string.h>
24  #include <stdlib.h>  #include <stdlib.h>
25  #include <PCSC/pcsclite.h>  #include <arpa/inet.h>
26  #include <PCSC/ifdhandler.h>  #include "misc.h"
27    #include <pcsclite.h>
28    #include <ifdhandler.h>
29    #include <reader.h>
30    
31  #include "ccid.h"  #include "ccid.h"
32  #include "defs.h"  #include "defs.h"
# Line 50  static pthread_mutex_t ifdh_context_mute Line 53  static pthread_mutex_t ifdh_context_mute
53    
54  int LogLevel = DEBUG_LEVEL_CRITICAL | DEBUG_LEVEL_INFO;  int LogLevel = DEBUG_LEVEL_CRITICAL | DEBUG_LEVEL_INFO;
55  int DriverOptions = 0;  int DriverOptions = 0;
56    int PowerOnVoltage = VOLTAGE_5V;
57  static int DebugInitialized = FALSE;  static int DebugInitialized = FALSE;
58    
59  /* local functions */  /* local functions */
60  static void init_driver(void);  static void init_driver(void);
61  static void extra_egt(ATR_t *atr, _ccid_descriptor *ccid_desc, DWORD Protocol);  static void extra_egt(ATR_t *atr, _ccid_descriptor *ccid_desc, DWORD Protocol);
62  static char find_baud_rate(unsigned int baudrate, unsigned int *list);  static char find_baud_rate(unsigned int baudrate, unsigned int *list);
63  static unsigned int T0_card_timeout(double f, int TC2, int clock_frequency);  static unsigned int T0_card_timeout(double f, double d, int TC1, int TC2,
 static unsigned int T1_card_timeout(double f, double d, int BWI,  
64          int clock_frequency);          int clock_frequency);
65    static unsigned int T1_card_timeout(double f, double d, int TC1, int BWI,
66            int CWI, int clock_frequency);
67    
68    
69  RESPONSECODE IFDHCreateChannelByName(DWORD Lun, LPTSTR lpcDevice)  EXTERNAL RESPONSECODE IFDHCreateChannelByName(DWORD Lun, LPSTR lpcDevice)
70  {  {
71          RESPONSECODE return_value = IFD_SUCCESS;          RESPONSECODE return_value = IFD_SUCCESS;
72          int reader_index;          int reader_index;
# Line 94  RESPONSECODE IFDHCreateChannelByName(DWO Line 99  RESPONSECODE IFDHCreateChannelByName(DWO
99                  ReleaseReaderIndex(reader_index);                  ReleaseReaderIndex(reader_index);
100          }          }
101          else          else
102            {
103                  /* Maybe we have a special treatment for this reader */                  /* Maybe we have a special treatment for this reader */
104                  ccid_open_hack(reader_index);                  ccid_open_hack(reader_index);
105    
106                    /* Try to access the reader */
107                    /* This "warm up" sequence is sometimes needed when pcscd is
108                     * restarted with the reader already connected. We get some
109                     * "usb_bulk_read: Resource temporarily unavailable" on the first
110                     * few tries. It is an empirical hack */
111                    if ((IFD_COMMUNICATION_ERROR == IFDHICCPresence(Lun))
112                            && (IFD_COMMUNICATION_ERROR == IFDHICCPresence(Lun))
113                            && (IFD_COMMUNICATION_ERROR == IFDHICCPresence(Lun)))
114                    {
115                            DEBUG_CRITICAL("failed");
116                            return_value = IFD_COMMUNICATION_ERROR;
117    
118                            /* release the allocated reader_index */
119                            ReleaseReaderIndex(reader_index);
120                    }
121            }
122    
123  #ifdef HAVE_PTHREAD  #ifdef HAVE_PTHREAD
124          pthread_mutex_unlock(&ifdh_context_mutex);          pthread_mutex_unlock(&ifdh_context_mutex);
125  #endif  #endif
# Line 105  RESPONSECODE IFDHCreateChannelByName(DWO Line 128  RESPONSECODE IFDHCreateChannelByName(DWO
128  } /* IFDHCreateChannelByName */  } /* IFDHCreateChannelByName */
129    
130    
131  RESPONSECODE IFDHCreateChannel(DWORD Lun, DWORD Channel)  EXTERNAL RESPONSECODE IFDHCreateChannel(DWORD Lun, DWORD Channel)
132  {  {
133          /*          /*
134           * Lun - Logical Unit Number, use this for multiple card slots or           * Lun - Logical Unit Number, use this for multiple card slots or
# Line 182  RESPONSECODE IFDHCreateChannel(DWORD Lun Line 205  RESPONSECODE IFDHCreateChannel(DWORD Lun
205  } /* IFDHCreateChannel */  } /* IFDHCreateChannel */
206    
207    
208  RESPONSECODE IFDHCloseChannel(DWORD Lun)  EXTERNAL RESPONSECODE IFDHCloseChannel(DWORD Lun)
209  {  {
210          /*          /*
211           * This function should close the reader communication channel for the           * This function should close the reader communication channel for the
# Line 223  RESPONSECODE IFDHCloseChannel(DWORD Lun) Line 246  RESPONSECODE IFDHCloseChannel(DWORD Lun)
246  } /* IFDHCloseChannel */  } /* IFDHCloseChannel */
247    
248    
249  RESPONSECODE IFDHGetCapabilities(DWORD Lun, DWORD Tag,  EXTERNAL RESPONSECODE IFDHGetCapabilities(DWORD Lun, DWORD Tag,
250          PDWORD Length, PUCHAR Value)          PDWORD Length, PUCHAR Value)
251  {  {
252          /*          /*
# Line 287  RESPONSECODE IFDHGetCapabilities(DWORD L Line 310  RESPONSECODE IFDHGetCapabilities(DWORD L
310                          {                          {
311                                  *Length = 1;                                  *Length = 1;
312                                  *Value = 1 + get_ccid_descriptor(reader_index) -> bMaxSlotIndex;                                  *Value = 1 + get_ccid_descriptor(reader_index) -> bMaxSlotIndex;
313                                  DEBUG_COMM2("Reader supports %d slots", *Value);                                  DEBUG_INFO2("Reader supports %d slots", *Value);
314                          }                          }
315                          break;                          break;
316    
# Line 299  RESPONSECODE IFDHGetCapabilities(DWORD L Line 322  RESPONSECODE IFDHGetCapabilities(DWORD L
322                          }                          }
323                          break;                          break;
324    
325                  case IOCTL_SMARTCARD_VENDOR_VERIFY_PIN:                  case SCARD_ATTR_VENDOR_IFD_VERSION:
326                          if (*Length >= 1)                          /* Vendor-supplied interface device version (DWORD in the form
327                          {                           * 0xMMmmbbbb where MM = major version, mm = minor version, and
328                                  *Length = 1;                           * bbbb = build number). */
329                                  *Value = get_ccid_descriptor(reader_index) -> bPINSupport & CCID_CLASS_PIN_VERIFY;                          *Length = sizeof(DWORD);
330                          }                          if (Value)
331                                    *(DWORD *)Value = CCID_VERSION;
332                            break;
333    
334                    case SCARD_ATTR_VENDOR_NAME:
335    #define VENDOR_NAME "Ludovic Rousseau"
336                            *Length = sizeof(VENDOR_NAME);
337                            if (Value)
338                                    memcpy(Value, VENDOR_NAME, sizeof(VENDOR_NAME));
339                            break;
340    
341                    case SCARD_ATTR_MAXINPUT:
342                            *Length = sizeof(uint32_t);
343                            if (Value)
344                                    *(uint32_t *)Value = get_ccid_descriptor(reader_index) -> dwMaxCCIDMessageLength -10;
345                          break;                          break;
346    
347                  default:                  default:
# Line 315  RESPONSECODE IFDHGetCapabilities(DWORD L Line 352  RESPONSECODE IFDHGetCapabilities(DWORD L
352  } /* IFDHGetCapabilities */  } /* IFDHGetCapabilities */
353    
354    
355  RESPONSECODE IFDHSetCapabilities(DWORD Lun, DWORD Tag,  EXTERNAL RESPONSECODE IFDHSetCapabilities(DWORD Lun, DWORD Tag,
356          /*@unused@*/ DWORD Length, /*@unused@*/ PUCHAR Value)          /*@unused@*/ DWORD Length, /*@unused@*/ PUCHAR Value)
357  {  {
358          /*          /*
# Line 346  RESPONSECODE IFDHSetCapabilities(DWORD L Line 383  RESPONSECODE IFDHSetCapabilities(DWORD L
383  } /* IFDHSetCapabilities */  } /* IFDHSetCapabilities */
384    
385    
386  RESPONSECODE IFDHSetProtocolParameters(DWORD Lun, DWORD Protocol,  EXTERNAL RESPONSECODE IFDHSetProtocolParameters(DWORD Lun, DWORD Protocol,
387          UCHAR Flags, UCHAR PTS1, UCHAR PTS2, UCHAR PTS3)          UCHAR Flags, UCHAR PTS1, UCHAR PTS2, UCHAR PTS3)
388  {  {
389          /*          /*
# Line 472  RESPONSECODE IFDHSetProtocolParameters(D Line 509  RESPONSECODE IFDHSetProtocolParameters(D
509                          ATR_GetParameter(&atr, ATR_PARAMETER_D, &d);                          ATR_GetParameter(&atr, ATR_PARAMETER_D, &d);
510                          ATR_GetParameter(&atr, ATR_PARAMETER_F, &f);                          ATR_GetParameter(&atr, ATR_PARAMETER_F, &f);
511    
512                            /* may happen with non ISO cards */
513                            if ((0 == f) || (0 == d))
514                            {
515                                    /* values for TA1=11 */
516                                    f = 372;
517                                    d = 1;
518                            }
519    
520                          /* Baudrate = f x D/F */                          /* Baudrate = f x D/F */
521                          card_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock                          card_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock
522                                  * d / f);                                  * d / f);
# Line 480  RESPONSECODE IFDHSetProtocolParameters(D Line 525  RESPONSECODE IFDHSetProtocolParameters(D
525                                  * ATR_DEFAULT_D / ATR_DEFAULT_F);                                  * ATR_DEFAULT_D / ATR_DEFAULT_F);
526    
527                          /* if the card does not try to lower the default speed */                          /* if the card does not try to lower the default speed */
528                          if (card_baudrate > default_baudrate)                          if ((card_baudrate > default_baudrate)
529                                    /* and the reader is fast enough */
530                                    && (card_baudrate <= ccid_desc->dwMaxDataRate))
531                          {                          {
532                                  if (find_baud_rate(card_baudrate,                                  /* the reader has no baud rates table */
533                                          ccid_desc->arrayOfSupportedDataRates))                                  if ((NULL == ccid_desc->arrayOfSupportedDataRates)
534                                            /* or explicitely support it */
535                                            || find_baud_rate(card_baudrate,
536                                                    ccid_desc->arrayOfSupportedDataRates))
537                                  {                                  {
538                                          pps[1] |= 0x10; /* PTS1 presence */                                          pps[1] |= 0x10; /* PTS1 presence */
539                                          pps[2] = atr.ib[0][ATR_INTERFACE_BYTE_TA].value;                                          pps[2] = atr.ib[0][ATR_INTERFACE_BYTE_TA].value;
# Line 491  RESPONSECODE IFDHSetProtocolParameters(D Line 541  RESPONSECODE IFDHSetProtocolParameters(D
541                                          DEBUG_COMM2("Set speed to %d bauds", card_baudrate);                                          DEBUG_COMM2("Set speed to %d bauds", card_baudrate);
542                                  }                                  }
543                                  else                                  else
544                                    {
545                                          DEBUG_COMM2("Reader does not support %d bauds",                                          DEBUG_COMM2("Reader does not support %d bauds",
546                                                  card_baudrate);                                                  card_baudrate);
547    
548                                            /* TA2 present -> specific mode: the card is supporting
549                                             * only the baud rate specified in TA1 but reader does not
550                                             * support this value. Reject the card. */
551                                            if (atr.ib[1][ATR_INTERFACE_BYTE_TA].present)
552                                                    return IFD_COMMUNICATION_ERROR;
553                                    }
554                            }
555                            else
556                            {
557                                    /* the card is too fast for the reader */
558                                    if ((card_baudrate > ccid_desc->dwMaxDataRate +2)
559                                            /* but TA1 <= 97 */
560                                            && (atr.ib[0][ATR_INTERFACE_BYTE_TA].value <= 0x97)
561                                            /* and the reader has a baud rate table */
562                                            && ccid_desc->arrayOfSupportedDataRates)
563                                    {
564                                            unsigned char old_TA1;
565    
566                                            old_TA1 = atr.ib[0][ATR_INTERFACE_BYTE_TA].value;
567                                            while (atr.ib[0][ATR_INTERFACE_BYTE_TA].value > 0x94)
568                                            {
569                                                    /* use a lower TA1 */
570                                                    atr.ib[0][ATR_INTERFACE_BYTE_TA].value--;
571    
572                                                    ATR_GetParameter(&atr, ATR_PARAMETER_D, &d);
573                                                    ATR_GetParameter(&atr, ATR_PARAMETER_F, &f);
574    
575                                                    /* Baudrate = f x D/F */
576                                                    card_baudrate = (unsigned int) (1000 *
577                                                            ccid_desc->dwDefaultClock * d / f);
578    
579                                                    if (find_baud_rate(card_baudrate,
580                                                            ccid_desc->arrayOfSupportedDataRates))
581                                                    {
582                                                            pps[1] |= 0x10; /* PTS1 presence */
583                                                            pps[2] = atr.ib[0][ATR_INTERFACE_BYTE_TA].value;
584    
585                                                            DEBUG_COMM2("Set adapted speed to %d bauds",
586                                                                    card_baudrate);
587    
588                                                            break;
589                                                    }
590                                            }
591    
592                                            /* restore original TA1 value */
593                                            atr.ib[0][ATR_INTERFACE_BYTE_TA].value = old_TA1;
594                                    }
595                          }                          }
596                  }                  }
597          }          }
# Line 558  RESPONSECODE IFDHSetProtocolParameters(D Line 657  RESPONSECODE IFDHSetProtocolParameters(D
657                  int i;                  int i;
658                  t1_state_t *t1 = &(ccid_slot -> t1);                  t1_state_t *t1 = &(ccid_slot -> t1);
659                  RESPONSECODE ret;                  RESPONSECODE ret;
660                  double f;                  double f, d;
                 double d;  
                 int BWI;  
661    
662                  /* TA1 is not default */                  /* TA1 is not default */
663                  if (PPS_HAS_PPS1(pps))                  if (PPS_HAS_PPS1(pps))
# Line 593  RESPONSECODE IFDHSetProtocolParameters(D Line 690  RESPONSECODE IFDHSetProtocolParameters(D
690                  /* compute communication timeout */                  /* compute communication timeout */
691                  ATR_GetParameter(&atr, ATR_PARAMETER_F, &f);                  ATR_GetParameter(&atr, ATR_PARAMETER_F, &f);
692                  ATR_GetParameter(&atr, ATR_PARAMETER_D, &d);                  ATR_GetParameter(&atr, ATR_PARAMETER_D, &d);
693                  BWI = (param[3] & 0xF0) >> 4;                  ccid_desc->readTimeout = T1_card_timeout(f, d, param[2],
694                  ccid_desc->readTimeout = T1_card_timeout(f, d, BWI /* BWI */,                          (param[3] & 0xF0) >> 4 /* BWI */, param[3] & 0x0F /* CWI */,
695                          ccid_desc->dwDefaultClock);                          ccid_desc->dwDefaultClock);
696    
697                  DEBUG_COMM2("Timeout: %d seconds", ccid_desc->readTimeout);                  DEBUG_COMM2("Timeout: %d seconds", ccid_desc->readTimeout);
# Line 614  RESPONSECODE IFDHSetProtocolParameters(D Line 711  RESPONSECODE IFDHSetProtocolParameters(D
711                          0x00    /* ClockStop            */                          0x00    /* ClockStop            */
712                  };                  };
713                  RESPONSECODE ret;                  RESPONSECODE ret;
714                  double f;                  double f, d;
715    
716                  /* TA1 is not default */                  /* TA1 is not default */
717                  if (PPS_HAS_PPS1(pps))                  if (PPS_HAS_PPS1(pps))
# Line 633  RESPONSECODE IFDHSetProtocolParameters(D Line 730  RESPONSECODE IFDHSetProtocolParameters(D
730    
731                  /* compute communication timeout */                  /* compute communication timeout */
732                  ATR_GetParameter(&atr, ATR_PARAMETER_F, &f);                  ATR_GetParameter(&atr, ATR_PARAMETER_F, &f);
733                  ccid_desc->readTimeout = T0_card_timeout(f, param[3] /* TC2 */,                  ATR_GetParameter(&atr, ATR_PARAMETER_D, &d);
734                          ccid_desc->dwDefaultClock);  
735                    ccid_desc->readTimeout = T0_card_timeout(f, d, param[2] /* TC1 */,
736                            param[3] /* TC2 */, ccid_desc->dwDefaultClock);
737    
738                  DEBUG_COMM2("Communication timeout %d seconds",                  DEBUG_COMM2("Communication timeout: %d seconds",
739                          ccid_desc->readTimeout);                          ccid_desc->readTimeout);
740    
741                  ret = SetParameters(reader_index, 0, sizeof(param), param);                  ret = SetParameters(reader_index, 0, sizeof(param), param);
# Line 675  RESPONSECODE IFDHSetProtocolParameters(D Line 774  RESPONSECODE IFDHSetProtocolParameters(D
774                  DEBUG_COMM3("T=1: IFSC=%d, IFSD=%d", t1->ifsc, t1->ifsd);                  DEBUG_COMM3("T=1: IFSC=%d, IFSD=%d", t1->ifsc, t1->ifsd);
775          }          }
776    
777            /* store used protocol for use by the secure commands (verify/change PIN) */
778            ccid_desc->cardProtocol = Protocol;
779    
780          return IFD_SUCCESS;          return IFD_SUCCESS;
781  } /* IFDHSetProtocolParameters */  } /* IFDHSetProtocolParameters */
782    
783    
784  RESPONSECODE IFDHPowerICC(DWORD Lun, DWORD Action,  EXTERNAL RESPONSECODE IFDHPowerICC(DWORD Lun, DWORD Action,
785          PUCHAR Atr, PDWORD AtrLength)          PUCHAR Atr, PDWORD AtrLength)
786  {  {
787          /*          /*
# Line 722  RESPONSECODE IFDHPowerICC(DWORD Lun, DWO Line 824  RESPONSECODE IFDHPowerICC(DWORD Lun, DWO
824          RESPONSECODE return_value = IFD_SUCCESS;          RESPONSECODE return_value = IFD_SUCCESS;
825          unsigned char pcbuffer[RESP_BUF_SIZE];          unsigned char pcbuffer[RESP_BUF_SIZE];
826          int reader_index;          int reader_index;
827            char *actions[] = { "PowerUp", "PowerDown", "Reset" };
828    
829          DEBUG_INFO2("lun: %X", Lun);          DEBUG_INFO3("lun: %X, action: %s", Lun, actions[Action-IFD_POWER_UP]);
830    
831          /* By default, assume it won't work :) */          /* By default, assume it won't work :) */
832          *AtrLength = 0;          *AtrLength = 0;
# Line 756  RESPONSECODE IFDHPowerICC(DWORD Lun, DWO Line 859  RESPONSECODE IFDHPowerICC(DWORD Lun, DWO
859                  case IFD_POWER_UP:                  case IFD_POWER_UP:
860                  case IFD_RESET:                  case IFD_RESET:
861                          nlength = sizeof(pcbuffer);                          nlength = sizeof(pcbuffer);
862                          if (CmdPowerOn(reader_index, &nlength, pcbuffer) != IFD_SUCCESS)                          if (CmdPowerOn(reader_index, &nlength, pcbuffer, PowerOnVoltage)
863                                    != IFD_SUCCESS)
864                          {                          {
865                                  DEBUG_CRITICAL("PowerUp failed");                                  DEBUG_CRITICAL("PowerUp failed");
866                                  return_value = IFD_ERROR_POWER_ACTION;                                  return_value = IFD_ERROR_POWER_ACTION;
# Line 787  end: Line 891  end:
891  } /* IFDHPowerICC */  } /* IFDHPowerICC */
892    
893    
894  RESPONSECODE IFDHTransmitToICC(DWORD Lun, SCARD_IO_HEADER SendPci,  EXTERNAL RESPONSECODE IFDHTransmitToICC(DWORD Lun, SCARD_IO_HEADER SendPci,
895          PUCHAR TxBuffer, DWORD TxLength,          PUCHAR TxBuffer, DWORD TxLength,
896          PUCHAR RxBuffer, PDWORD RxLength, /*@unused@*/ PSCARD_IO_HEADER RecvPci)          PUCHAR RxBuffer, PDWORD RxLength, /*@unused@*/ PSCARD_IO_HEADER RecvPci)
897  {  {
# Line 843  RESPONSECODE IFDHTransmitToICC(DWORD Lun Line 947  RESPONSECODE IFDHTransmitToICC(DWORD Lun
947  } /* IFDHTransmitToICC */  } /* IFDHTransmitToICC */
948    
949    
950  RESPONSECODE IFDHControl(DWORD Lun, DWORD dwControlCode, PUCHAR TxBuffer,  EXTERNAL RESPONSECODE IFDHControl(DWORD Lun, DWORD dwControlCode,
951          DWORD TxLength, PUCHAR RxBuffer, DWORD RxLength, PDWORD pdwBytesReturned)          PUCHAR TxBuffer, DWORD TxLength, PUCHAR RxBuffer, DWORD RxLength,
952            PDWORD pdwBytesReturned)
953  {  {
954          /*          /*
955           * This function performs a data exchange with the reader (not the           * This function performs a data exchange with the reader (not the
# Line 866  RESPONSECODE IFDHControl(DWORD Lun, DWOR Line 971  RESPONSECODE IFDHControl(DWORD Lun, DWOR
971          DEBUG_INFO3("lun: %X, ControlCode: 0x%X", Lun, dwControlCode);          DEBUG_INFO3("lun: %X, ControlCode: 0x%X", Lun, dwControlCode);
972    
973          reader_index = LunToReaderIndex(Lun);          reader_index = LunToReaderIndex(Lun);
974          if ((-1 == reader_index) || (NULL == pdwBytesReturned)          if ((-1 == reader_index) || (NULL == pdwBytesReturned))
                 || (NULL == RxBuffer))  
975                  return return_value;                  return return_value;
976    
977          /* Set the return length to 0 to avoid problems */          /* Set the return length to 0 to avoid problems */
# Line 891  RESPONSECODE IFDHControl(DWORD Lun, DWOR Line 995  RESPONSECODE IFDHControl(DWORD Lun, DWOR
995                  }                  }
996          }          }
997    
998          if (IOCTL_SMARTCARD_VENDOR_VERIFY_PIN == dwControlCode)          /* Implement the PC/SC v2.1.2 Part 10 IOCTL mechanism */
999    
1000            /* Query for features */
1001            if (CM_IOCTL_GET_FEATURE_REQUEST == dwControlCode)
1002            {
1003                    unsigned int iBytesReturned = 0;
1004                    PCSC_TLV_STRUCTURE *pcsc_tlv = (PCSC_TLV_STRUCTURE *)RxBuffer;
1005    
1006                    /* we need room for two records */
1007                    if (RxLength < 2 * sizeof(PCSC_TLV_STRUCTURE))
1008                            return IFD_COMMUNICATION_ERROR;
1009    
1010                    /* We can only support direct verify and/or modify currently */
1011                    if (get_ccid_descriptor(reader_index) -> bPINSupport
1012                            & CCID_CLASS_PIN_VERIFY)
1013                    {
1014                            pcsc_tlv -> tag = FEATURE_VERIFY_PIN_DIRECT;
1015                            pcsc_tlv -> length = 0x04; /* always 0x04 */
1016                            pcsc_tlv -> value = htonl(IOCTL_FEATURE_VERIFY_PIN_DIRECT);
1017    
1018                            pcsc_tlv++;
1019                            iBytesReturned += sizeof(PCSC_TLV_STRUCTURE);
1020                    }
1021    
1022                    if (get_ccid_descriptor(reader_index) -> bPINSupport
1023                            & CCID_CLASS_PIN_MODIFY)
1024                    {
1025                            pcsc_tlv -> tag = FEATURE_MODIFY_PIN_DIRECT;
1026                            pcsc_tlv -> length = 0x04; /* always 0x04 */
1027                            pcsc_tlv -> value = htonl(IOCTL_FEATURE_MODIFY_PIN_DIRECT);
1028    
1029                            pcsc_tlv++;
1030                            iBytesReturned += sizeof(PCSC_TLV_STRUCTURE);
1031                    }
1032                    *pdwBytesReturned = iBytesReturned;
1033                    return_value = IFD_SUCCESS;
1034            }
1035    
1036            /* Verify a PIN, plain CCID */
1037            if (IOCTL_FEATURE_VERIFY_PIN_DIRECT == dwControlCode)
1038          {          {
1039                  unsigned int iBytesReturned;                  unsigned int iBytesReturned;
1040    
1041                  iBytesReturned = RxLength;                  iBytesReturned = RxLength;
1042                  return_value = SecurePIN(reader_index, TxBuffer, TxLength, RxBuffer,                  return_value = SecurePINVerify(reader_index, TxBuffer, TxLength,
1043                          &iBytesReturned);                          RxBuffer, &iBytesReturned);
1044                    *pdwBytesReturned = iBytesReturned;
1045            }
1046    
1047            /* Modify a PIN, plain CCID */
1048            if (IOCTL_FEATURE_MODIFY_PIN_DIRECT == dwControlCode)
1049            {
1050                    unsigned int iBytesReturned;
1051    
1052                    iBytesReturned = RxLength;
1053                    return_value = SecurePINModify(reader_index, TxBuffer, TxLength,
1054                            RxBuffer, &iBytesReturned);
1055                  *pdwBytesReturned = iBytesReturned;                  *pdwBytesReturned = iBytesReturned;
1056          }          }
1057    
# Line 905  RESPONSECODE IFDHControl(DWORD Lun, DWOR Line 1059  RESPONSECODE IFDHControl(DWORD Lun, DWOR
1059  } /* IFDHControl */  } /* IFDHControl */
1060    
1061    
1062  RESPONSECODE IFDHICCPresence(DWORD Lun)  EXTERNAL RESPONSECODE IFDHICCPresence(DWORD Lun)
1063  {  {
1064          /*          /*
1065           * This function returns the status of the card inserted in the           * This function returns the status of the card inserted in the
# Line 955  RESPONSECODE IFDHICCPresence(DWORD Lun) Line 1109  RESPONSECODE IFDHICCPresence(DWORD Lun)
1109          switch (pcbuffer[7] & CCID_ICC_STATUS_MASK)     /* bStatus */          switch (pcbuffer[7] & CCID_ICC_STATUS_MASK)     /* bStatus */
1110          {          {
1111                  case CCID_ICC_PRESENT_ACTIVE:                  case CCID_ICC_PRESENT_ACTIVE:
                 case CCID_ICC_PRESENT_INACTIVE:  
1112                          return_value = IFD_ICC_PRESENT;                          return_value = IFD_ICC_PRESENT;
1113                          /* use default slot */                          /* use default slot */
1114                          break;                          break;
1115    
1116                    case CCID_ICC_PRESENT_INACTIVE:
1117                            if ((CcidSlots[reader_index].bPowerFlags == POWERFLAGS_RAZ)
1118                                    || (CcidSlots[reader_index].bPowerFlags & MASK_POWERFLAGS_PDWN))
1119                                    /* the card was previously absent */
1120                                    return_value = IFD_ICC_PRESENT;
1121                            else
1122                            {
1123                                    /* the card was previously present but has been
1124                                     * removed and inserted between two consecutive
1125                                     * IFDHICCPresence() calls */
1126                                    CcidSlots[reader_index].bPowerFlags = POWERFLAGS_RAZ;
1127                                    return_value = IFD_ICC_NOT_PRESENT;
1128                            }
1129                            break;
1130    
1131                  case CCID_ICC_ABSENT:                  case CCID_ICC_ABSENT:
1132                          /* Reset ATR buffer */                          /* Reset ATR buffer */
1133                          CcidSlots[reader_index].nATRLength = 0;                          CcidSlots[reader_index].nATRLength = 0;
# Line 973  RESPONSECODE IFDHICCPresence(DWORD Lun) Line 1141  RESPONSECODE IFDHICCPresence(DWORD Lun)
1141          }          }
1142    
1143          /* SCR331-DI contactless reader */          /* SCR331-DI contactless reader */
1144          if ((SCR331DI == ccid_descriptor->readerID)          if (((SCR331DI == ccid_descriptor->readerID)
1145                    || (SDI010 == ccid_descriptor->readerID)
1146                    || (SCR331DINTTCOM == ccid_descriptor->readerID))
1147                  && (ccid_descriptor->bCurrentSlotIndex > 0))                  && (ccid_descriptor->bCurrentSlotIndex > 0))
1148          {          {
1149                  unsigned char cmd[] = { 0x11 };                  unsigned char cmd[] = { 0x11 };
# Line 983  RESPONSECODE IFDHICCPresence(DWORD Lun) Line 1153  RESPONSECODE IFDHICCPresence(DWORD Lun)
1153    
1154                  unsigned char res[10];                  unsigned char res[10];
1155                  unsigned int length_res = sizeof(res);                  unsigned int length_res = sizeof(res);
1156                    RESPONSECODE ret;
1157    
1158                  /* if DEBUG_LEVEL_PERIODIC is not set we remove DEBUG_LEVEL_COMM */                  /* if DEBUG_LEVEL_PERIODIC is not set we remove DEBUG_LEVEL_COMM */
1159                  oldLogLevel = LogLevel;                  oldLogLevel = LogLevel;
1160                  if (! (LogLevel & DEBUG_LEVEL_PERIODIC))                  if (! (LogLevel & DEBUG_LEVEL_PERIODIC))
1161                          LogLevel &= ~DEBUG_LEVEL_COMM;                          LogLevel &= ~DEBUG_LEVEL_COMM;
1162    
1163                  CmdEscape(reader_index, cmd, sizeof(cmd), res, &length_res);                  ret = CmdEscape(reader_index, cmd, sizeof(cmd), res, &length_res);
1164    
1165                  /* set back the old LogLevel */                  /* set back the old LogLevel */
1166                  LogLevel = oldLogLevel;                  LogLevel = oldLogLevel;
1167    
1168                    if (ret != IFD_SUCCESS)
1169                    {
1170                            DEBUG_INFO("CmdEscape failed");
1171                            /* simulate a card absent */
1172                            res[0] = 0;
1173                    }
1174    
1175                  if (0x01 == res[0])                  if (0x01 == res[0])
1176                          return_value = IFD_ICC_PRESENT;                          return_value = IFD_ICC_PRESENT;
1177                  else                  else
# Line 1051  void init_driver(void) Line 1229  void init_driver(void)
1229                  DEBUG_INFO2("DriverOptions: 0x%.4X", DriverOptions);                  DEBUG_INFO2("DriverOptions: 0x%.4X", DriverOptions);
1230          }          }
1231    
1232            /* get the voltage parameter */
1233            switch ((DriverOptions >> 4) & 0x03)
1234            {
1235                    case 0:
1236                            PowerOnVoltage = VOLTAGE_5V;
1237                            break;
1238    
1239                    case 1:
1240                            PowerOnVoltage = VOLTAGE_3V;
1241                            break;
1242    
1243                    case 2:
1244                            PowerOnVoltage = VOLTAGE_1_8V;
1245                            break;
1246    
1247                    case 3:
1248                            PowerOnVoltage = VOLTAGE_AUTO;
1249                            break;
1250            }
1251    
1252          /* initialise the Lun to reader_index mapping */          /* initialise the Lun to reader_index mapping */
1253          InitReaderIndex();          InitReaderIndex();
1254    
# Line 1084  void extra_egt(ATR_t *atr, _ccid_descrip Line 1282  void extra_egt(ATR_t *atr, _ccid_descrip
1282          ATR_GetParameter(atr, ATR_PARAMETER_D, &d);          ATR_GetParameter(atr, ATR_PARAMETER_D, &d);
1283          ATR_GetParameter(atr, ATR_PARAMETER_F, &f);          ATR_GetParameter(atr, ATR_PARAMETER_F, &f);
1284    
1285            /* may happen with non ISO cards */
1286            if ((0 == f) || (0 == d))
1287                    return;
1288    
1289          /* Baudrate = f x D/F */          /* Baudrate = f x D/F */
1290          card_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock * d / f);          card_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock * d / f);
1291    
# Line 1113  void extra_egt(ATR_t *atr, _ccid_descrip Line 1315  void extra_egt(ATR_t *atr, _ccid_descrip
1315                          for (i=2; i<ATR_MAX_PROTOCOLS; i++)                          for (i=2; i<ATR_MAX_PROTOCOLS; i++)
1316                          {                          {
1317                                  /* CWI >= 2 ? */                                  /* CWI >= 2 ? */
1318                                  if (atr->ib[i][ATR_INTERFACE_BYTE_TB].present &&                                  if (atr->ib[i][ATR_INTERFACE_BYTE_TB].present &&
1319                                          ((atr->ib[i][ATR_INTERFACE_BYTE_TB].value & 0x0F) >= 2))                                          ((atr->ib[i][ATR_INTERFACE_BYTE_TB].value & 0x0F) >= 2))
1320                                  {                                  {
1321                                          /* Init TC1 */                                          /* Init TC1 */
# Line 1136  static char find_baud_rate(unsigned int Line 1338  static char find_baud_rate(unsigned int
1338    
1339          DEBUG_COMM2("Card baud rate: %d", baudrate);          DEBUG_COMM2("Card baud rate: %d", baudrate);
1340    
1341          /* Does the reader support the annonced smart card data speed? */          /* Does the reader support the announced smart card data speed? */
1342          for (i=0;; i++)          for (i=0;; i++)
1343          {          {
1344                  /* end of array marker */                  /* end of array marker */
# Line 1156  static char find_baud_rate(unsigned int Line 1358  static char find_baud_rate(unsigned int
1358  } /* find_baud_rate */  } /* find_baud_rate */
1359    
1360    
1361  static unsigned int T0_card_timeout(double f, int TC2, int clock_frequency)  static unsigned int T0_card_timeout(double f, double d, int TC1, int TC2,
1362            int clock_frequency)
1363  {  {
1364          unsigned int timeout = DEFAULT_COM_READ_TIMEOUT;          unsigned int timeout = DEFAULT_COM_READ_TIMEOUT;
1365            double EGT, WWT;
1366          unsigned int t;          unsigned int t;
1367    
1368            /* Timeout applied on ISO_IN or ISO_OUT card exchange
1369             * we choose the maximum computed value.
1370             *
1371             * ISO_IN timeout is the sum of:
1372             * Terminal:                                    Smart card:
1373             * 5 bytes header cmd  ->
1374             *                    <-                Procedure byte
1375             * 256 data bytes          ->
1376             *                                        <-            SW1-SW2
1377             * = 261 EGT       + 3 WWT     + 3 WWT
1378             *
1379             * ISO_OUT Timeout is the sum of:
1380             * Terminal:                    Smart card:
1381             * 5 bytes header cmd  ->
1382             *                                        <-        Procedure byte + 256 data bytes + SW1-SW2
1383             * = 5 EGT          + 1 WWT     + 259 WWT
1384             */
1385    
1386            /* clock_frequency is in kHz so the times are in milliseconds and not
1387             * in seconds */
1388    
1389            /* may happen with non ISO cards */
1390            if ((0 == f) || (0 == d) || (0 == clock_frequency))
1391                    return 60;      /* 60 seconds */
1392    
1393            /* EGT */
1394            /* see ch. 6.5.3 Extra Guard Time, page 12 of ISO 7816-3 */
1395            EGT = 12 * f / d / clock_frequency + (f / d) * TC1 / clock_frequency;
1396    
1397          /* card WWT */          /* card WWT */
1398          /* see ch. 8.2 Character level, page 15 of ISO 7816-3 */          /* see ch. 8.2 Character level, page 15 of ISO 7816-3 */
1399          t = 960 * TC2 * f / (clock_frequency * 1000);          WWT = 960 * TC2 * f / clock_frequency;
1400    
1401          /* use the bigest one */          /* ISO in */
1402          if (t > timeout)          t  = 261 * EGT + (3 + 3) * WWT;
1403            /* Convert from milliseonds to seconds rouned to the upper value
1404             * use +1 instead of ceil() to round up to the nearest interger
1405             * so we can avoid a dependency on the math library */
1406            t = t/1000 +1;
1407            if (timeout < t)
1408                  timeout = t;                  timeout = t;
1409    
1410          /* default WWT (TC2=0x0A) */          /* ISO out */
1411          t = 960 * 0x0A * f / (clock_frequency * 1000);          t = 5 * EGT + (1 + 259) * WWT;
1412            t = t/1000 +1;
1413          /* use the bigest one */          if (timeout < t)
         if (t > timeout)  
1414                  timeout = t;                  timeout = t;
1415    
1416          return timeout;          return timeout;
1417  } /* T0_card_timeout  */  } /* T0_card_timeout  */
1418    
1419    
1420  static unsigned int T1_card_timeout(double f, double d, int BWI,  static unsigned int T1_card_timeout(double f, double d, int TC1,
1421          int clock_frequency)          int BWI, int CWI, int clock_frequency)
1422  {  {
1423          unsigned int timeout = DEFAULT_COM_READ_TIMEOUT;          double EGT, BWT, CWT, etu;
1424          unsigned int t;          unsigned int timeout;
1425    
1426          /* card BWT */          /* Timeout applied on ISO in + ISO out card exchange
1427          /* see ch. 9.5.3.2 Block waiting time, page 20 of ISO 7816-3 */           *
1428          t = 11 * f / d / (clock_frequency * 1000) + (1<<BWI) * 960 * 372 / (clock_frequency * 1000);    /* seconds  */       * Timeout is the sum of:
1429             * - ISO in delay between leading edge of the first character sent by the
1430             *   interface device and the last one (NAD PCB LN APDU CKS) = 260 EGT,
1431             * - delay between ISO in and ISO out = BWT,
1432             * - ISO out delay between leading edge of the first character sent by the
1433             *   card and the last one (NAD PCB LN DATAS CKS) = 260 CWT.
1434             */
1435    
1436          /* use the bigest one */          /* clock_frequency is in kHz so the times are in milliseconds and not
1437          if (t > timeout)           * in seconds */
                 timeout = t;  
1438    
1439          /* default BWT (BWI=0x04) */          /* may happen with non ISO cards */
1440          t = 11 * f / d / (clock_frequency * 1000) + (1<<4) * 960 * 372 / (clock_frequency * 1000);      /* seconds  */          if ((0 == f) || (0 == d) || (0 == clock_frequency))
1441                    return 60;      /* 60 seconds */
1442    
1443            /* see ch. 6.5.2 Transmission factors F and D, page 12 of ISO 7816-3 */
1444            etu = f / d / clock_frequency;
1445    
1446            /* EGT */
1447            /* see ch. 6.5.3 Extra Guard Time, page 12 of ISO 7816-3 */
1448            EGT = 12 * etu + (f / d) * TC1 / clock_frequency;
1449    
1450          /* use the bigest one */          /* card BWT */
1451          if (t > timeout)          /* see ch. 9.5.3.2 Block Waiting Time, page 20 of ISO 7816-3 */
1452                  timeout = t;          BWT = 11 * etu + (1<<BWI) * 960 * 372 / clock_frequency;
1453    
1454            /* card CWT */
1455            /* see ch. 9.5.3.1 Caracter Waiting Time, page 20 of ISO 7816-3 */
1456            CWT = (11 + (1<<CWI)) * etu;
1457    
1458            timeout = 260*EGT + BWT + 260*CWT;
1459    
1460            /* Convert from milliseonds to seconds rounded to the upper value
1461             * we use +1 instead of ceil() to round up to the nearest greater interger
1462             * so we can avoid a dependency on the math library */
1463            timeout = timeout/1000 +1;
1464    
1465          return timeout;          return timeout;
1466  } /* T1_card_timeout  */  } /* T1_card_timeout  */

Legend:
Removed from v.1477  
changed lines
  Added in v.2197

  ViewVC Help
Powered by ViewVC 1.1.5