/[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 1448 by rousseau, Tue Apr 26 13:46:07 2005 UTC revision 2168 by rousseau, Wed Sep 20 14:01:14 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, double d, int TC1, int TC2,
64            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 91  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 102  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 179  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 198  RESPONSECODE IFDHCloseChannel(DWORD Lun) Line 224  RESPONSECODE IFDHCloseChannel(DWORD Lun)
224          if (-1 == (reader_index = LunToReaderIndex(Lun)))          if (-1 == (reader_index = LunToReaderIndex(Lun)))
225                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
226    
227            /* Restore the default timeout
228             * No need to wait too long if the reader disapeared */
229            get_ccid_descriptor(reader_index)->readTimeout = DEFAULT_COM_READ_TIMEOUT;
230    
231          (void)CmdPowerOff(reader_index);          (void)CmdPowerOff(reader_index);
232          /* No reader status check, if it failed, what can you do ? :) */          /* No reader status check, if it failed, what can you do ? :) */
233    
# Line 216  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 280  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 292  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;                          break;
340    
341                  default:                  default:
# Line 308  RESPONSECODE IFDHGetCapabilities(DWORD L Line 346  RESPONSECODE IFDHGetCapabilities(DWORD L
346  } /* IFDHGetCapabilities */  } /* IFDHGetCapabilities */
347    
348    
349  RESPONSECODE IFDHSetCapabilities(DWORD Lun, DWORD Tag,  EXTERNAL RESPONSECODE IFDHSetCapabilities(DWORD Lun, DWORD Tag,
350          /*@unused@*/ DWORD Length, /*@unused@*/ PUCHAR Value)          /*@unused@*/ DWORD Length, /*@unused@*/ PUCHAR Value)
351  {  {
352          /*          /*
# Line 339  RESPONSECODE IFDHSetCapabilities(DWORD L Line 377  RESPONSECODE IFDHSetCapabilities(DWORD L
377  } /* IFDHSetCapabilities */  } /* IFDHSetCapabilities */
378    
379    
380  RESPONSECODE IFDHSetProtocolParameters(DWORD Lun, DWORD Protocol,  EXTERNAL RESPONSECODE IFDHSetProtocolParameters(DWORD Lun, DWORD Protocol,
381          UCHAR Flags, UCHAR PTS1, UCHAR PTS2, UCHAR PTS3)          UCHAR Flags, UCHAR PTS1, UCHAR PTS2, UCHAR PTS3)
382  {  {
383          /*          /*
# Line 465  RESPONSECODE IFDHSetProtocolParameters(D Line 503  RESPONSECODE IFDHSetProtocolParameters(D
503                          ATR_GetParameter(&atr, ATR_PARAMETER_D, &d);                          ATR_GetParameter(&atr, ATR_PARAMETER_D, &d);
504                          ATR_GetParameter(&atr, ATR_PARAMETER_F, &f);                          ATR_GetParameter(&atr, ATR_PARAMETER_F, &f);
505    
506                            /* may happen with non ISO cards */
507                            if ((0 == f) || (0 == d))
508                            {
509                                    /* values for TA1=11 */
510                                    f = 372;
511                                    d = 1;
512                            }
513    
514                          /* Baudrate = f x D/F */                          /* Baudrate = f x D/F */
515                          card_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock                          card_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock
516                                  * d / f);                                  * d / f);
# Line 472  RESPONSECODE IFDHSetProtocolParameters(D Line 518  RESPONSECODE IFDHSetProtocolParameters(D
518                          default_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock                          default_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock
519                                  * ATR_DEFAULT_D / ATR_DEFAULT_F);                                  * ATR_DEFAULT_D / ATR_DEFAULT_F);
520    
521                          /* if the reader is fast enough */                          /* if the card does not try to lower the default speed */
522                          if ((card_baudrate <= ccid_desc->dwMaxDataRate)                          if ((card_baudrate > default_baudrate)
523                                  /* and the card does not try to lower the default speed */                                  /* and the reader is fast enough */
524                                  && (card_baudrate > default_baudrate ))                                  && (card_baudrate <= ccid_desc->dwMaxDataRate))
525                          {                          {
526                                  if (find_baud_rate(card_baudrate,                                  /* the reader has no baud rates table */
527                                          ccid_desc->arrayOfSupportedDataRates))                                  if ((NULL == ccid_desc->arrayOfSupportedDataRates)
528                                            /* or explicitely support it */
529                                            || find_baud_rate(card_baudrate,
530                                                    ccid_desc->arrayOfSupportedDataRates))
531                                  {                                  {
532                                          pps[1] |= 0x10; /* PTS1 presence */                                          pps[1] |= 0x10; /* PTS1 presence */
533                                          pps[2] = atr.ib[0][ATR_INTERFACE_BYTE_TA].value;                                          pps[2] = atr.ib[0][ATR_INTERFACE_BYTE_TA].value;
# Line 486  RESPONSECODE IFDHSetProtocolParameters(D Line 535  RESPONSECODE IFDHSetProtocolParameters(D
535                                          DEBUG_COMM2("Set speed to %d bauds", card_baudrate);                                          DEBUG_COMM2("Set speed to %d bauds", card_baudrate);
536                                  }                                  }
537                                  else                                  else
538                                    {
539                                          DEBUG_COMM2("Reader does not support %d bauds",                                          DEBUG_COMM2("Reader does not support %d bauds",
540                                                  card_baudrate);                                                  card_baudrate);
541    
542                                            /* TA2 present -> specific mode: the card is supporting
543                                             * only the baud rate specified in TA1 but reader does not
544                                             * support this value. Reject the card. */
545                                            if (atr.ib[1][ATR_INTERFACE_BYTE_TA].present)
546                                                    return IFD_COMMUNICATION_ERROR;
547                                    }
548                            }
549                            else
550                            {
551                                    /* the card is too fast for the reader */
552                                    if ((card_baudrate > ccid_desc->dwMaxDataRate +2)
553                                            /* but TA1 <= 97 */
554                                            && (atr.ib[0][ATR_INTERFACE_BYTE_TA].value <= 0x97)
555                                            /* and the reader has a baud rate table */
556                                            && ccid_desc->arrayOfSupportedDataRates)
557                                    {
558                                            unsigned char old_TA1;
559    
560                                            old_TA1 = atr.ib[0][ATR_INTERFACE_BYTE_TA].value;
561                                            while (atr.ib[0][ATR_INTERFACE_BYTE_TA].value > 0x94)
562                                            {
563                                                    /* use a lower TA1 */
564                                                    atr.ib[0][ATR_INTERFACE_BYTE_TA].value--;
565    
566                                                    ATR_GetParameter(&atr, ATR_PARAMETER_D, &d);
567                                                    ATR_GetParameter(&atr, ATR_PARAMETER_F, &f);
568    
569                                                    /* Baudrate = f x D/F */
570                                                    card_baudrate = (unsigned int) (1000 *
571                                                            ccid_desc->dwDefaultClock * d / f);
572    
573                                                    if (find_baud_rate(card_baudrate,
574                                                            ccid_desc->arrayOfSupportedDataRates))
575                                                    {
576                                                            pps[1] |= 0x10; /* PTS1 presence */
577                                                            pps[2] = atr.ib[0][ATR_INTERFACE_BYTE_TA].value;
578    
579                                                            DEBUG_COMM2("Set adapted speed to %d bauds",
580                                                                    card_baudrate);
581    
582                                                            break;
583                                                    }
584                                            }
585    
586                                            /* restore original TA1 value */
587                                            atr.ib[0][ATR_INTERFACE_BYTE_TA].value = old_TA1;
588                                    }
589                          }                          }
590                  }                  }
591          }          }
# Line 553  RESPONSECODE IFDHSetProtocolParameters(D Line 651  RESPONSECODE IFDHSetProtocolParameters(D
651                  int i;                  int i;
652                  t1_state_t *t1 = &(ccid_slot -> t1);                  t1_state_t *t1 = &(ccid_slot -> t1);
653                  RESPONSECODE ret;                  RESPONSECODE ret;
654                    double f, d;
655    
656                  /* TA1 is not default */                  /* TA1 is not default */
657                  if (PPS_HAS_PPS1(pps))                  if (PPS_HAS_PPS1(pps))
# Line 582  RESPONSECODE IFDHSetProtocolParameters(D Line 681  RESPONSECODE IFDHSetProtocolParameters(D
681                                  break;                                  break;
682                          }                          }
683    
684                    /* compute communication timeout */
685                    ATR_GetParameter(&atr, ATR_PARAMETER_F, &f);
686                    ATR_GetParameter(&atr, ATR_PARAMETER_D, &d);
687                    ccid_desc->readTimeout = T1_card_timeout(f, d, param[2],
688                            (param[3] & 0xF0) >> 4 /* BWI */, param[3] & 0x0F /* CWI */,
689                            ccid_desc->dwDefaultClock);
690    
691                    DEBUG_COMM2("Timeout: %d seconds", ccid_desc->readTimeout);
692    
693                  ret = SetParameters(reader_index, 1, sizeof(param), param);                  ret = SetParameters(reader_index, 1, sizeof(param), param);
694                  if (IFD_SUCCESS != ret)                  if (IFD_SUCCESS != ret)
695                          return ret;                          return ret;
# Line 597  RESPONSECODE IFDHSetProtocolParameters(D Line 705  RESPONSECODE IFDHSetProtocolParameters(D
705                          0x00    /* ClockStop            */                          0x00    /* ClockStop            */
706                  };                  };
707                  RESPONSECODE ret;                  RESPONSECODE ret;
708                    double f, d;
709    
710                  /* TA1 is not default */                  /* TA1 is not default */
711                  if (PPS_HAS_PPS1(pps))                  if (PPS_HAS_PPS1(pps))
# Line 613  RESPONSECODE IFDHSetProtocolParameters(D Line 722  RESPONSECODE IFDHSetProtocolParameters(D
722                  if (atr.ib[1][ATR_INTERFACE_BYTE_TC].present)                  if (atr.ib[1][ATR_INTERFACE_BYTE_TC].present)
723                          param[3] = atr.ib[1][ATR_INTERFACE_BYTE_TC].value;                          param[3] = atr.ib[1][ATR_INTERFACE_BYTE_TC].value;
724    
725                    /* compute communication timeout */
726                    ATR_GetParameter(&atr, ATR_PARAMETER_F, &f);
727                    ATR_GetParameter(&atr, ATR_PARAMETER_D, &d);
728    
729                    ccid_desc->readTimeout = T0_card_timeout(f, d, param[2] /* TC1 */,
730                            param[3] /* TC2 */, ccid_desc->dwDefaultClock);
731    
732                    DEBUG_COMM2("Communication timeout: %d seconds",
733                            ccid_desc->readTimeout);
734    
735                  ret = SetParameters(reader_index, 0, sizeof(param), param);                  ret = SetParameters(reader_index, 0, sizeof(param), param);
736                  if (IFD_SUCCESS != ret)                  if (IFD_SUCCESS != ret)
737                          return ret;                          return ret;
# Line 649  RESPONSECODE IFDHSetProtocolParameters(D Line 768  RESPONSECODE IFDHSetProtocolParameters(D
768                  DEBUG_COMM3("T=1: IFSC=%d, IFSD=%d", t1->ifsc, t1->ifsd);                  DEBUG_COMM3("T=1: IFSC=%d, IFSD=%d", t1->ifsc, t1->ifsd);
769          }          }
770    
771            /* store used protocol for use by the secure commands (verify/change PIN) */
772            ccid_desc->cardProtocol = Protocol;
773    
774          return IFD_SUCCESS;          return IFD_SUCCESS;
775  } /* IFDHSetProtocolParameters */  } /* IFDHSetProtocolParameters */
776    
777    
778  RESPONSECODE IFDHPowerICC(DWORD Lun, DWORD Action,  EXTERNAL RESPONSECODE IFDHPowerICC(DWORD Lun, DWORD Action,
779          PUCHAR Atr, PDWORD AtrLength)          PUCHAR Atr, PDWORD AtrLength)
780  {  {
781          /*          /*
# Line 730  RESPONSECODE IFDHPowerICC(DWORD Lun, DWO Line 852  RESPONSECODE IFDHPowerICC(DWORD Lun, DWO
852                  case IFD_POWER_UP:                  case IFD_POWER_UP:
853                  case IFD_RESET:                  case IFD_RESET:
854                          nlength = sizeof(pcbuffer);                          nlength = sizeof(pcbuffer);
855                          if (CmdPowerOn(reader_index, &nlength, pcbuffer) != IFD_SUCCESS)                          if (CmdPowerOn(reader_index, &nlength, pcbuffer, PowerOnVoltage)
856                                    != IFD_SUCCESS)
857                          {                          {
858                                  DEBUG_CRITICAL("PowerUp failed");                                  DEBUG_CRITICAL("PowerUp failed");
859                                  return_value = IFD_ERROR_POWER_ACTION;                                  return_value = IFD_ERROR_POWER_ACTION;
# Line 761  end: Line 884  end:
884  } /* IFDHPowerICC */  } /* IFDHPowerICC */
885    
886    
887  RESPONSECODE IFDHTransmitToICC(DWORD Lun, SCARD_IO_HEADER SendPci,  EXTERNAL RESPONSECODE IFDHTransmitToICC(DWORD Lun, SCARD_IO_HEADER SendPci,
888          PUCHAR TxBuffer, DWORD TxLength,          PUCHAR TxBuffer, DWORD TxLength,
889          PUCHAR RxBuffer, PDWORD RxLength, /*@unused@*/ PSCARD_IO_HEADER RecvPci)          PUCHAR RxBuffer, PDWORD RxLength, /*@unused@*/ PSCARD_IO_HEADER RecvPci)
890  {  {
# Line 817  RESPONSECODE IFDHTransmitToICC(DWORD Lun Line 940  RESPONSECODE IFDHTransmitToICC(DWORD Lun
940  } /* IFDHTransmitToICC */  } /* IFDHTransmitToICC */
941    
942    
943  RESPONSECODE IFDHControl(DWORD Lun, DWORD dwControlCode, PUCHAR TxBuffer,  EXTERNAL RESPONSECODE IFDHControl(DWORD Lun, DWORD dwControlCode,
944          DWORD TxLength, PUCHAR RxBuffer, DWORD RxLength, PDWORD pdwBytesReturned)          PUCHAR TxBuffer, DWORD TxLength, PUCHAR RxBuffer, DWORD RxLength,
945            PDWORD pdwBytesReturned)
946  {  {
947          /*          /*
948           * This function performs a data exchange with the reader (not the           * This function performs a data exchange with the reader (not the
# Line 840  RESPONSECODE IFDHControl(DWORD Lun, DWOR Line 964  RESPONSECODE IFDHControl(DWORD Lun, DWOR
964          DEBUG_INFO3("lun: %X, ControlCode: 0x%X", Lun, dwControlCode);          DEBUG_INFO3("lun: %X, ControlCode: 0x%X", Lun, dwControlCode);
965    
966          reader_index = LunToReaderIndex(Lun);          reader_index = LunToReaderIndex(Lun);
967          if ((-1 == reader_index) || (NULL == pdwBytesReturned)          if ((-1 == reader_index) || (NULL == pdwBytesReturned))
                 || (NULL == RxBuffer))  
968                  return return_value;                  return return_value;
969    
970          /* Set the return length to 0 to avoid problems */          /* Set the return length to 0 to avoid problems */
# Line 865  RESPONSECODE IFDHControl(DWORD Lun, DWOR Line 988  RESPONSECODE IFDHControl(DWORD Lun, DWOR
988                  }                  }
989          }          }
990    
991          if (IOCTL_SMARTCARD_VENDOR_VERIFY_PIN == dwControlCode)          /* Implement the PC/SC v2.1.2 Part 10 IOCTL mechanism */
992    
993            /* Query for features */
994            if (CM_IOCTL_GET_FEATURE_REQUEST == dwControlCode)
995            {
996                    unsigned int iBytesReturned = 0;
997                    PCSC_TLV_STRUCTURE *pcsc_tlv = (PCSC_TLV_STRUCTURE *)RxBuffer;
998    
999                    /* we need room for two records */
1000                    if (RxLength < 2 * sizeof(PCSC_TLV_STRUCTURE))
1001                            return IFD_COMMUNICATION_ERROR;
1002    
1003                    /* We can only support direct verify and/or modify currently */
1004                    if (get_ccid_descriptor(reader_index) -> bPINSupport
1005                            & CCID_CLASS_PIN_VERIFY)
1006                    {
1007                            pcsc_tlv -> tag = FEATURE_VERIFY_PIN_DIRECT;
1008                            pcsc_tlv -> length = 0x04; /* always 0x04 */
1009                            pcsc_tlv -> value = htonl(IOCTL_FEATURE_VERIFY_PIN_DIRECT);
1010    
1011                            pcsc_tlv++;
1012                            iBytesReturned += sizeof(PCSC_TLV_STRUCTURE);
1013                    }
1014    
1015                    if (get_ccid_descriptor(reader_index) -> bPINSupport
1016                            & CCID_CLASS_PIN_MODIFY)
1017                    {
1018                            pcsc_tlv -> tag = FEATURE_MODIFY_PIN_DIRECT;
1019                            pcsc_tlv -> length = 0x04; /* always 0x04 */
1020                            pcsc_tlv -> value = htonl(IOCTL_FEATURE_MODIFY_PIN_DIRECT);
1021    
1022                            pcsc_tlv++;
1023                            iBytesReturned += sizeof(PCSC_TLV_STRUCTURE);
1024                    }
1025                    *pdwBytesReturned = iBytesReturned;
1026                    return_value = IFD_SUCCESS;
1027            }
1028    
1029            /* Verify a PIN, plain CCID */
1030            if (IOCTL_FEATURE_VERIFY_PIN_DIRECT == dwControlCode)
1031            {
1032                    unsigned int iBytesReturned;
1033    
1034                    iBytesReturned = RxLength;
1035                    return_value = SecurePINVerify(reader_index, TxBuffer, TxLength,
1036                            RxBuffer, &iBytesReturned);
1037                    *pdwBytesReturned = iBytesReturned;
1038            }
1039    
1040            /* Modify a PIN, plain CCID */
1041            if (IOCTL_FEATURE_MODIFY_PIN_DIRECT == dwControlCode)
1042          {          {
1043                  unsigned int iBytesReturned;                  unsigned int iBytesReturned;
1044    
1045                  iBytesReturned = RxLength;                  iBytesReturned = RxLength;
1046                  return_value = SecurePIN(reader_index, TxBuffer, TxLength, RxBuffer,                  return_value = SecurePINModify(reader_index, TxBuffer, TxLength,
1047                          &iBytesReturned);                          RxBuffer, &iBytesReturned);
1048                  *pdwBytesReturned = iBytesReturned;                  *pdwBytesReturned = iBytesReturned;
1049          }          }
1050    
# Line 879  RESPONSECODE IFDHControl(DWORD Lun, DWOR Line 1052  RESPONSECODE IFDHControl(DWORD Lun, DWOR
1052  } /* IFDHControl */  } /* IFDHControl */
1053    
1054    
1055  RESPONSECODE IFDHICCPresence(DWORD Lun)  EXTERNAL RESPONSECODE IFDHICCPresence(DWORD Lun)
1056  {  {
1057          /*          /*
1058           * This function returns the status of the card inserted in the           * This function returns the status of the card inserted in the
# Line 894  RESPONSECODE IFDHICCPresence(DWORD Lun) Line 1067  RESPONSECODE IFDHICCPresence(DWORD Lun)
1067          int oldLogLevel;          int oldLogLevel;
1068          int reader_index;          int reader_index;
1069          _ccid_descriptor *ccid_descriptor;          _ccid_descriptor *ccid_descriptor;
1070            unsigned int oldReadTimeout;
1071    
1072          DEBUG_PERIODIC2("lun: %X", Lun);          DEBUG_PERIODIC2("lun: %X", Lun);
1073    
# Line 902  RESPONSECODE IFDHICCPresence(DWORD Lun) Line 1076  RESPONSECODE IFDHICCPresence(DWORD Lun)
1076    
1077          ccid_descriptor = get_ccid_descriptor(reader_index);          ccid_descriptor = get_ccid_descriptor(reader_index);
1078    
1079            /* save the current read timeout computed from card capabilities */
1080            oldReadTimeout = ccid_descriptor->readTimeout;
1081    
1082            /* use default timeout since the reader may not be present anymore */
1083            ccid_descriptor->readTimeout = DEFAULT_COM_READ_TIMEOUT;
1084    
1085          /* if DEBUG_LEVEL_PERIODIC is not set we remove DEBUG_LEVEL_COMM */          /* if DEBUG_LEVEL_PERIODIC is not set we remove DEBUG_LEVEL_COMM */
1086          oldLogLevel = LogLevel;          oldLogLevel = LogLevel;
1087          if (! (LogLevel & DEBUG_LEVEL_PERIODIC))          if (! (LogLevel & DEBUG_LEVEL_PERIODIC))
# Line 909  RESPONSECODE IFDHICCPresence(DWORD Lun) Line 1089  RESPONSECODE IFDHICCPresence(DWORD Lun)
1089    
1090          return_value = CmdGetSlotStatus(reader_index, pcbuffer);          return_value = CmdGetSlotStatus(reader_index, pcbuffer);
1091    
1092            /* set back the old timeout */
1093            ccid_descriptor->readTimeout = oldReadTimeout;
1094    
1095          /* set back the old LogLevel */          /* set back the old LogLevel */
1096          LogLevel = oldLogLevel;          LogLevel = oldLogLevel;
1097    
# Line 919  RESPONSECODE IFDHICCPresence(DWORD Lun) Line 1102  RESPONSECODE IFDHICCPresence(DWORD Lun)
1102          switch (pcbuffer[7] & CCID_ICC_STATUS_MASK)     /* bStatus */          switch (pcbuffer[7] & CCID_ICC_STATUS_MASK)     /* bStatus */
1103          {          {
1104                  case CCID_ICC_PRESENT_ACTIVE:                  case CCID_ICC_PRESENT_ACTIVE:
                 case CCID_ICC_PRESENT_INACTIVE:  
1105                          return_value = IFD_ICC_PRESENT;                          return_value = IFD_ICC_PRESENT;
1106                          /* use default slot */                          /* use default slot */
1107                          break;                          break;
1108    
1109                    case CCID_ICC_PRESENT_INACTIVE:
1110                            if (CcidSlots[reader_index].bPowerFlags == POWERFLAGS_RAZ)
1111                                    /* the card was previously absent */
1112                                    return_value = IFD_ICC_PRESENT;
1113                            else
1114                            {
1115                                    /* the card was previously present but has been
1116                                     * removed and inserted between two consecutive
1117                                     * IFDHICCPresence() calls */
1118                                    CcidSlots[reader_index].bPowerFlags = POWERFLAGS_RAZ;
1119                                    return_value = IFD_ICC_NOT_PRESENT;
1120                            }
1121                            break;
1122    
1123                  case CCID_ICC_ABSENT:                  case CCID_ICC_ABSENT:
1124                          /* Reset ATR buffer */                          /* Reset ATR buffer */
1125                          CcidSlots[reader_index].nATRLength = 0;                          CcidSlots[reader_index].nATRLength = 0;
# Line 937  RESPONSECODE IFDHICCPresence(DWORD Lun) Line 1133  RESPONSECODE IFDHICCPresence(DWORD Lun)
1133          }          }
1134    
1135          /* SCR331-DI contactless reader */          /* SCR331-DI contactless reader */
1136          if ((SCR331DI == ccid_descriptor->readerID)          if (((SCR331DI == ccid_descriptor->readerID)
1137                    || (SDI010 == ccid_descriptor->readerID)
1138                    || (SCR331DINTTCOM == ccid_descriptor->readerID))
1139                  && (ccid_descriptor->bCurrentSlotIndex > 0))                  && (ccid_descriptor->bCurrentSlotIndex > 0))
1140          {          {
1141                  unsigned char cmd[] = { 0x11 };                  unsigned char cmd[] = { 0x11 };
# Line 947  RESPONSECODE IFDHICCPresence(DWORD Lun) Line 1145  RESPONSECODE IFDHICCPresence(DWORD Lun)
1145    
1146                  unsigned char res[10];                  unsigned char res[10];
1147                  unsigned int length_res = sizeof(res);                  unsigned int length_res = sizeof(res);
1148                    RESPONSECODE ret;
1149    
1150                  /* if DEBUG_LEVEL_PERIODIC is not set we remove DEBUG_LEVEL_COMM */                  /* if DEBUG_LEVEL_PERIODIC is not set we remove DEBUG_LEVEL_COMM */
1151                  oldLogLevel = LogLevel;                  oldLogLevel = LogLevel;
1152                  if (! (LogLevel & DEBUG_LEVEL_PERIODIC))                  if (! (LogLevel & DEBUG_LEVEL_PERIODIC))
1153                          LogLevel &= ~DEBUG_LEVEL_COMM;                          LogLevel &= ~DEBUG_LEVEL_COMM;
1154    
1155                  CmdEscape(reader_index, cmd, sizeof(cmd), res, &length_res);                  ret = CmdEscape(reader_index, cmd, sizeof(cmd), res, &length_res);
1156    
1157                  /* set back the old LogLevel */                  /* set back the old LogLevel */
1158                  LogLevel = oldLogLevel;                  LogLevel = oldLogLevel;
1159    
1160                    if (ret != IFD_SUCCESS)
1161                    {
1162                            DEBUG_INFO("CmdEscape failed");
1163                            /* simulate a card absent */
1164                            res[0] = 0;
1165                    }
1166    
1167                  if (0x01 == res[0])                  if (0x01 == res[0])
1168                          return_value = IFD_ICC_PRESENT;                          return_value = IFD_ICC_PRESENT;
1169                  else                  else
# Line 1015  void init_driver(void) Line 1221  void init_driver(void)
1221                  DEBUG_INFO2("DriverOptions: 0x%.4X", DriverOptions);                  DEBUG_INFO2("DriverOptions: 0x%.4X", DriverOptions);
1222          }          }
1223    
1224            /* get the voltage parameter */
1225            switch ((DriverOptions >> 4) & 0x03)
1226            {
1227                    case 0:
1228                            PowerOnVoltage = VOLTAGE_5V;
1229                            break;
1230    
1231                    case 1:
1232                            PowerOnVoltage = VOLTAGE_3V;
1233                            break;
1234    
1235                    case 2:
1236                            PowerOnVoltage = VOLTAGE_1_8V;
1237                            break;
1238    
1239                    case 3:
1240                            PowerOnVoltage = VOLTAGE_AUTO;
1241                            break;
1242            }
1243    
1244          /* initialise the Lun to reader_index mapping */          /* initialise the Lun to reader_index mapping */
1245          InitReaderIndex();          InitReaderIndex();
1246    
# Line 1048  void extra_egt(ATR_t *atr, _ccid_descrip Line 1274  void extra_egt(ATR_t *atr, _ccid_descrip
1274          ATR_GetParameter(atr, ATR_PARAMETER_D, &d);          ATR_GetParameter(atr, ATR_PARAMETER_D, &d);
1275          ATR_GetParameter(atr, ATR_PARAMETER_F, &f);          ATR_GetParameter(atr, ATR_PARAMETER_F, &f);
1276    
1277            /* may happen with non ISO cards */
1278            if ((0 == f) || (0 == d))
1279                    return;
1280    
1281          /* Baudrate = f x D/F */          /* Baudrate = f x D/F */
1282          card_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock * d / f);          card_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock * d / f);
1283    
# Line 1077  void extra_egt(ATR_t *atr, _ccid_descrip Line 1307  void extra_egt(ATR_t *atr, _ccid_descrip
1307                          for (i=2; i<ATR_MAX_PROTOCOLS; i++)                          for (i=2; i<ATR_MAX_PROTOCOLS; i++)
1308                          {                          {
1309                                  /* CWI >= 2 ? */                                  /* CWI >= 2 ? */
1310                                  if (atr->ib[i][ATR_INTERFACE_BYTE_TB].present &&                                  if (atr->ib[i][ATR_INTERFACE_BYTE_TB].present &&
1311                                          ((atr->ib[i][ATR_INTERFACE_BYTE_TB].value & 0x0F) >= 2))                                          ((atr->ib[i][ATR_INTERFACE_BYTE_TB].value & 0x0F) >= 2))
1312                                  {                                  {
1313                                          /* Init TC1 */                                          /* Init TC1 */
# Line 1100  static char find_baud_rate(unsigned int Line 1330  static char find_baud_rate(unsigned int
1330    
1331          DEBUG_COMM2("Card baud rate: %d", baudrate);          DEBUG_COMM2("Card baud rate: %d", baudrate);
1332    
1333          /* Does the reader support the annonced smart card data speed? */          /* Does the reader support the announced smart card data speed? */
1334          for (i=0;; i++)          for (i=0;; i++)
1335          {          {
1336                  /* end of array marker */                  /* end of array marker */
# Line 1119  static char find_baud_rate(unsigned int Line 1349  static char find_baud_rate(unsigned int
1349          return FALSE;          return FALSE;
1350  } /* find_baud_rate */  } /* find_baud_rate */
1351    
1352    
1353    static unsigned int T0_card_timeout(double f, double d, int TC1, int TC2,
1354            int clock_frequency)
1355    {
1356            unsigned int timeout = DEFAULT_COM_READ_TIMEOUT;
1357            double EGT, WWT;
1358            unsigned int t;
1359    
1360            /* Timeout applied on ISO_IN or ISO_OUT card exchange
1361             * we choose the maximum computed value.
1362             *
1363             * ISO_IN timeout is the sum of:
1364             * Terminal:                                    Smart card:
1365             * 5 bytes header cmd  ->
1366             *                    <-                Procedure byte
1367             * 256 data bytes          ->
1368             *                                        <-            SW1-SW2
1369             * = 261 EGT       + 3 WWT     + 3 WWT
1370             *
1371             * ISO_OUT Timeout is the sum of:
1372             * Terminal:                    Smart card:
1373             * 5 bytes header cmd  ->
1374             *                                        <-        Procedure byte + 256 data bytes + SW1-SW2
1375             * = 5 EGT          + 1 WWT     + 259 WWT
1376             */
1377    
1378            /* clock_frequency is in kHz so the times are in milliseconds and not
1379             * in seconds */
1380    
1381            /* may happen with non ISO cards */
1382            if ((0 == f) || (0 == d) || (0 == clock_frequency))
1383                    return 60;      /* 60 seconds */
1384    
1385            /* EGT */
1386            /* see ch. 6.5.3 Extra Guard Time, page 12 of ISO 7816-3 */
1387            EGT = 12 * f / d / clock_frequency + (f / d) * TC1 / clock_frequency;
1388    
1389            /* card WWT */
1390            /* see ch. 8.2 Character level, page 15 of ISO 7816-3 */
1391            WWT = 960 * TC2 * f / clock_frequency;
1392    
1393            /* ISO in */
1394            t  = 261 * EGT + (3 + 3) * WWT;
1395            /* Convert from milliseonds to seconds rouned to the upper value
1396             * use +1 instead of ceil() to round up to the nearest interger
1397             * so we can avoid a dependency on the math library */
1398            t = t/1000 +1;
1399            if (timeout < t)
1400                    timeout = t;
1401    
1402            /* ISO out */
1403            t = 5 * EGT + (1 + 259) * WWT;
1404            t = t/1000 +1;
1405            if (timeout < t)
1406                    timeout = t;
1407    
1408            return timeout;
1409    } /* T0_card_timeout  */
1410    
1411    
1412    static unsigned int T1_card_timeout(double f, double d, int TC1,
1413            int BWI, int CWI, int clock_frequency)
1414    {
1415            double EGT, BWT, CWT, etu;
1416            unsigned int timeout;
1417    
1418            /* Timeout applied on ISO in + ISO out card exchange
1419             *
1420         * Timeout is the sum of:
1421             * - ISO in delay between leading edge of the first character sent by the
1422             *   interface device and the last one (NAD PCB LN APDU CKS) = 260 EGT,
1423             * - delay between ISO in and ISO out = BWT,
1424             * - ISO out delay between leading edge of the first character sent by the
1425             *   card and the last one (NAD PCB LN DATAS CKS) = 260 CWT.
1426             */
1427    
1428            /* clock_frequency is in kHz so the times are in milliseconds and not
1429             * in seconds */
1430    
1431            /* may happen with non ISO cards */
1432            if ((0 == f) || (0 == d) || (0 == clock_frequency))
1433                    return 60;      /* 60 seconds */
1434    
1435            /* see ch. 6.5.2 Transmission factors F and D, page 12 of ISO 7816-3 */
1436            etu = f / d / clock_frequency;
1437    
1438            /* EGT */
1439            /* see ch. 6.5.3 Extra Guard Time, page 12 of ISO 7816-3 */
1440            EGT = 12 * etu + (f / d) * TC1 / clock_frequency;
1441    
1442            /* card BWT */
1443            /* see ch. 9.5.3.2 Block Waiting Time, page 20 of ISO 7816-3 */
1444            BWT = 11 * etu + (1<<BWI) * 960 * 372 / clock_frequency;
1445    
1446            /* card CWT */
1447            /* see ch. 9.5.3.1 Caracter Waiting Time, page 20 of ISO 7816-3 */
1448            CWT = (11 + (1<<CWI)) * etu;
1449    
1450            timeout = 260*EGT + BWT + 260*CWT;
1451    
1452            /* Convert from milliseonds to seconds rounded to the upper value
1453             * we use +1 instead of ceil() to round up to the nearest greater interger
1454             * so we can avoid a dependency on the math library */
1455            timeout = timeout/1000 +1;
1456    
1457            return timeout;
1458    } /* T1_card_timeout  */
1459    

Legend:
Removed from v.1448  
changed lines
  Added in v.2168

  ViewVC Help
Powered by ViewVC 1.1.5