/[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 1352 by rousseau, Fri Feb 25 17:19:00 2005 UTC revision 2175 by rousseau, Tue Sep 26 13:29:57 2006 UTC
# Line 1  Line 1 
1  /*  /*
2      ifdhandler.c: IFDH API      ifdhandler.c: IFDH API
3      Copyright (C) 2003   Ludovic Rousseau      Copyright (C) 2003-2005   Ludovic Rousseau
4    
5      This program is free software; you can redistribute it and/or modify      This library is free software; you can redistribute it and/or
6      it under the terms of the GNU General Public License as published by      modify it under the terms of the GNU Lesser General Public
7      the Free Software Foundation; either version 2 of the License, or      License as published by the Free Software Foundation; either
8      (at your option) any later version.      version 2.1 of the License, or (at your option) any later version.
9    
10      This program is distributed in the hope that it will be useful,      This library is distributed in the hope that it will be useful,
11      but WITHOUT ANY WARRANTY; without even the implied warranty of      but WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      GNU General Public License for more details.      Lesser General Public License for more details.
14    
15      You should have received a copy of the GNU General Public License      You should have received a copy of the GNU Lesser General Public
16      along with this program; if not, write to the Free Software      License along with this library; if not, write to the Free Software
17      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
18  */  */
19    
20  /* $Id$ */  /* $Id$ */
# 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);
62    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 89  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 100  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 177  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 196  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 214  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 252  RESPONSECODE IFDHGetCapabilities(DWORD L Line 284  RESPONSECODE IFDHGetCapabilities(DWORD L
284                                  *Length : CcidSlots[reader_index].nATRLength;                                  *Length : CcidSlots[reader_index].nATRLength;
285    
286                          if (*Length)                          if (*Length)
287                                  memcpy(Value, CcidSlots[reader_index]                                  memcpy(Value, CcidSlots[reader_index].pcATRBuffer, *Length);
                                         .pcATRBuffer, *Length);  
288                          break;                          break;
289    
290  #ifdef HAVE_PTHREAD  #ifdef HAVE_PTHREAD
# Line 279  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 291  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 307  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 338  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 361  RESPONSECODE IFDHSetProtocolParameters(D Line 400  RESPONSECODE IFDHSetProtocolParameters(D
400           */           */
401    
402          BYTE pps[PPS_MAX_LENGTH];          BYTE pps[PPS_MAX_LENGTH];
403          ATR atr;          ATR_t atr;
404          unsigned int len;          unsigned int len;
405          int convention;          int convention;
406          int reader_index;          int reader_index;
# Line 383  RESPONSECODE IFDHSetProtocolParameters(D Line 422  RESPONSECODE IFDHSetProtocolParameters(D
422          ccid_slot = get_ccid_slot(reader_index);          ccid_slot = get_ccid_slot(reader_index);
423          ccid_desc = get_ccid_descriptor(reader_index);          ccid_desc = get_ccid_descriptor(reader_index);
424    
425            /* Do not send CCID command SetParameters or PPS to the CCID
426             * The CCID will do this himself */
427            if (ccid_desc->dwFeatures & CCID_CLASS_AUTO_PPS_PROP)
428                    return IFD_SUCCESS;
429    
430          /* Get ATR of the card */          /* Get ATR of the card */
431          ATR_InitFromArray(&atr, ccid_slot->pcATRBuffer, ccid_slot->nATRLength);          ATR_InitFromArray(&atr, ccid_slot->pcATRBuffer, ccid_slot->nATRLength);
432    
433            /* Apply Extra EGT patch for bogus cards */
434            extra_egt(&atr, ccid_desc, Protocol);
435    
436          if (SCARD_PROTOCOL_T0 == Protocol)          if (SCARD_PROTOCOL_T0 == Protocol)
437                  pps[1] |= ATR_PROTOCOL_TYPE_T0;                  pps[1] |= ATR_PROTOCOL_TYPE_T0;
438          else          else
# Line 456  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 463  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                                  pps[1] |= 0x10; /* PTS1 presence */                                  /* the reader has no baud rates table */
527                                  pps[2] = atr.ib[0][ATR_INTERFACE_BYTE_TA].value;                                  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 */
533                                            pps[2] = atr.ib[0][ATR_INTERFACE_BYTE_TA].value;
534    
535                                  DEBUG_COMM2("Set speed to %d bauds", card_baudrate);                                          DEBUG_COMM2("Set speed to %d bauds", card_baudrate);
536                                    }
537                                    else
538                                    {
539                                            DEBUG_COMM2("Reader does not support %d bauds",
540                                                    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 529  RESPONSECODE IFDHSetProtocolParameters(D Line 643  RESPONSECODE IFDHSetProtocolParameters(D
643                          0x11,   /* Fi/Di                */                          0x11,   /* Fi/Di                */
644                          0x10,   /* TCCKS                */                          0x10,   /* TCCKS                */
645                          0x00,   /* GuardTime    */                          0x00,   /* GuardTime    */
646                          0x4D,   /* BWI/BCI              */                          0x4D,   /* BWI/CWI              */
647                          0x00,   /* ClockStop    */                          0x00,   /* ClockStop    */
648                          0x20,   /* IFSC                 */                          0x20,   /* IFSC                 */
649                          0x00    /* NADValue             */                          0x00    /* NADValue             */
# Line 537  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))
658                          param[0] = pps[2];                          param[0] = pps[2];
659    
660                  /* CRC checksum? */                  /* CRC checksum? */
661                  if (2 == t1->rc_bytes)                  if (2 == t1->rc_bytes)
662                          param[1] |= 0x01;                          param[1] |= 0x01;
# Line 554  RESPONSECODE IFDHSetProtocolParameters(D Line 669  RESPONSECODE IFDHSetProtocolParameters(D
669                  if (atr.ib[0][ATR_INTERFACE_BYTE_TC].present)                  if (atr.ib[0][ATR_INTERFACE_BYTE_TC].present)
670                          param[2] = atr.ib[0][ATR_INTERFACE_BYTE_TC].value;                          param[2] = atr.ib[0][ATR_INTERFACE_BYTE_TC].value;
671    
672                  /* TBi (i>2) present? BWI/BCI */                  /* TBi (i>2) present? BWI/CWI */
673                  for (i=2; i<ATR_MAX_PROTOCOLS; i++)                  for (i=2; i<ATR_MAX_PROTOCOLS; i++)
674                          if (atr.ib[i][ATR_INTERFACE_BYTE_TB].present)                          if (atr.ib[i][ATR_INTERFACE_BYTE_TB].present)
675                          {                          {
676                                  DEBUG_COMM3("BWI/BCI (TB%d) present: %d", i+1,                                  DEBUG_COMM3("BWI/CWI (TB%d) present: 0x%02X", i+1,
677                                          atr.ib[i][ATR_INTERFACE_BYTE_TB].value);                                          atr.ib[i][ATR_INTERFACE_BYTE_TB].value);
678                                  param[3] = atr.ib[i][ATR_INTERFACE_BYTE_TB].value;                                  param[3] = atr.ib[i][ATR_INTERFACE_BYTE_TB].value;
679    
# Line 566  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 581  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 597  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 624  RESPONSECODE IFDHSetProtocolParameters(D Line 759  RESPONSECODE IFDHSetProtocolParameters(D
759                  /* IFSD not negociated by the reader? */                  /* IFSD not negociated by the reader? */
760                  if (! (ccid_desc->dwFeatures & CCID_CLASS_AUTO_IFSD))                  if (! (ccid_desc->dwFeatures & CCID_CLASS_AUTO_IFSD))
761                  {                  {
762                          DEBUG_COMM2("Negociate IFSD at %d",  ccid_desc -> dwMaxIFSD);                          DEBUG_COMM2("Negociate IFSD at %d", ccid_desc -> dwMaxIFSD);
763                          if (t1_negociate_ifsd(t1, 0, ccid_desc -> dwMaxIFSD) < 0)                          if (t1_negociate_ifsd(t1, 0, ccid_desc -> dwMaxIFSD) < 0)
764                                  return IFD_COMMUNICATION_ERROR;                                  return IFD_COMMUNICATION_ERROR;
765                  }                  }
# Line 633  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 680  RESPONSECODE IFDHPowerICC(DWORD Lun, DWO Line 818  RESPONSECODE IFDHPowerICC(DWORD Lun, DWO
818          RESPONSECODE return_value = IFD_SUCCESS;          RESPONSECODE return_value = IFD_SUCCESS;
819          unsigned char pcbuffer[RESP_BUF_SIZE];          unsigned char pcbuffer[RESP_BUF_SIZE];
820          int reader_index;          int reader_index;
821            char *actions[] = { "PowerUp", "PowerDown", "Reset" };
822    
823          DEBUG_INFO2("lun: %X", Lun);          DEBUG_INFO3("lun: %X, action: %s", Lun, actions[Action-IFD_POWER_UP]);
824    
825          /* By default, assume it won't work :) */          /* By default, assume it won't work :) */
826          *AtrLength = 0;          *AtrLength = 0;
# Line 697  RESPONSECODE IFDHPowerICC(DWORD Lun, DWO Line 836  RESPONSECODE IFDHPowerICC(DWORD Lun, DWO
836                          *CcidSlots[reader_index].pcATRBuffer = '\0';                          *CcidSlots[reader_index].pcATRBuffer = '\0';
837    
838                          /* Memorise the request */                          /* Memorise the request */
839                          CcidSlots[reader_index].bPowerFlags |=                          CcidSlots[reader_index].bPowerFlags |= MASK_POWERFLAGS_PDWN;
                                 MASK_POWERFLAGS_PDWN;  
840    
841                          /* send the command */                          /* send the command */
842                          if (IFD_SUCCESS != CmdPowerOff(reader_index))                          if (IFD_SUCCESS != CmdPowerOff(reader_index))
# Line 715  RESPONSECODE IFDHPowerICC(DWORD Lun, DWO Line 853  RESPONSECODE IFDHPowerICC(DWORD Lun, DWO
853                  case IFD_POWER_UP:                  case IFD_POWER_UP:
854                  case IFD_RESET:                  case IFD_RESET:
855                          nlength = sizeof(pcbuffer);                          nlength = sizeof(pcbuffer);
856                          if (CmdPowerOn(reader_index, &nlength, pcbuffer) != IFD_SUCCESS)                          if (CmdPowerOn(reader_index, &nlength, pcbuffer, PowerOnVoltage)
857                                    != IFD_SUCCESS)
858                          {                          {
859                                  DEBUG_CRITICAL("PowerUp failed");                                  DEBUG_CRITICAL("PowerUp failed");
860                                  return_value = IFD_ERROR_POWER_ACTION;                                  return_value = IFD_ERROR_POWER_ACTION;
# Line 723  RESPONSECODE IFDHPowerICC(DWORD Lun, DWO Line 862  RESPONSECODE IFDHPowerICC(DWORD Lun, DWO
862                          }                          }
863    
864                          /* Power up successful, set state variable to memorise it */                          /* Power up successful, set state variable to memorise it */
865                          CcidSlots[reader_index].bPowerFlags |=                          CcidSlots[reader_index].bPowerFlags |= MASK_POWERFLAGS_PUP;
866                                  MASK_POWERFLAGS_PUP;                          CcidSlots[reader_index].bPowerFlags &= ~MASK_POWERFLAGS_PDWN;
                         CcidSlots[reader_index].bPowerFlags &=  
                                 ~MASK_POWERFLAGS_PDWN;  
867    
868                          /* Reset is returned, even if TCK is wrong */                          /* Reset is returned, even if TCK is wrong */
869                          CcidSlots[reader_index].nATRLength = *AtrLength =                          CcidSlots[reader_index].nATRLength = *AtrLength =
870                                  (nlength < MAX_ATR_SIZE) ? nlength : MAX_ATR_SIZE;                                  (nlength < MAX_ATR_SIZE) ? nlength : MAX_ATR_SIZE;
871                          memcpy(Atr, pcbuffer, *AtrLength);                          memcpy(Atr, pcbuffer, *AtrLength);
872                          memcpy(CcidSlots[reader_index].pcATRBuffer,                          memcpy(CcidSlots[reader_index].pcATRBuffer, pcbuffer, *AtrLength);
                                 pcbuffer, *AtrLength);  
873    
874                          /* initialise T=1 context */                          /* initialise T=1 context */
875                          t1_init(&(get_ccid_slot(reader_index) -> t1), reader_index);                          t1_init(&(get_ccid_slot(reader_index) -> t1), reader_index);
# Line 749  end: Line 885  end:
885  } /* IFDHPowerICC */  } /* IFDHPowerICC */
886    
887    
888  RESPONSECODE IFDHTransmitToICC(DWORD Lun, SCARD_IO_HEADER SendPci,  EXTERNAL RESPONSECODE IFDHTransmitToICC(DWORD Lun, SCARD_IO_HEADER SendPci,
889          PUCHAR TxBuffer, DWORD TxLength,          PUCHAR TxBuffer, DWORD TxLength,
890          PUCHAR RxBuffer, PDWORD RxLength, /*@unused@*/ PSCARD_IO_HEADER RecvPci)          PUCHAR RxBuffer, PDWORD RxLength, /*@unused@*/ PSCARD_IO_HEADER RecvPci)
891  {  {
# Line 805  RESPONSECODE IFDHTransmitToICC(DWORD Lun Line 941  RESPONSECODE IFDHTransmitToICC(DWORD Lun
941  } /* IFDHTransmitToICC */  } /* IFDHTransmitToICC */
942    
943    
944  RESPONSECODE IFDHControl(DWORD Lun, DWORD dwControlCode, PUCHAR TxBuffer,  EXTERNAL RESPONSECODE IFDHControl(DWORD Lun, DWORD dwControlCode,
945          DWORD TxLength, PUCHAR RxBuffer, DWORD RxLength, PDWORD pdwBytesReturned)          PUCHAR TxBuffer, DWORD TxLength, PUCHAR RxBuffer, DWORD RxLength,
946            PDWORD pdwBytesReturned)
947  {  {
948          /*          /*
949           * This function performs a data exchange with the reader (not the           * This function performs a data exchange with the reader (not the
# Line 828  RESPONSECODE IFDHControl(DWORD Lun, DWOR Line 965  RESPONSECODE IFDHControl(DWORD Lun, DWOR
965          DEBUG_INFO3("lun: %X, ControlCode: 0x%X", Lun, dwControlCode);          DEBUG_INFO3("lun: %X, ControlCode: 0x%X", Lun, dwControlCode);
966    
967          reader_index = LunToReaderIndex(Lun);          reader_index = LunToReaderIndex(Lun);
968          if ((-1 == reader_index) || (NULL == pdwBytesReturned)          if ((-1 == reader_index) || (NULL == pdwBytesReturned))
                 || (NULL == RxBuffer))  
969                  return return_value;                  return return_value;
970    
971          /* Set the return length to 0 to avoid problems */          /* Set the return length to 0 to avoid problems */
# Line 853  RESPONSECODE IFDHControl(DWORD Lun, DWOR Line 989  RESPONSECODE IFDHControl(DWORD Lun, DWOR
989                  }                  }
990          }          }
991    
992          if (IOCTL_SMARTCARD_VENDOR_VERIFY_PIN == dwControlCode)          /* Implement the PC/SC v2.1.2 Part 10 IOCTL mechanism */
993    
994            /* Query for features */
995            if (CM_IOCTL_GET_FEATURE_REQUEST == dwControlCode)
996            {
997                    unsigned int iBytesReturned = 0;
998                    PCSC_TLV_STRUCTURE *pcsc_tlv = (PCSC_TLV_STRUCTURE *)RxBuffer;
999    
1000                    /* we need room for two records */
1001                    if (RxLength < 2 * sizeof(PCSC_TLV_STRUCTURE))
1002                            return IFD_COMMUNICATION_ERROR;
1003    
1004                    /* We can only support direct verify and/or modify currently */
1005                    if (get_ccid_descriptor(reader_index) -> bPINSupport
1006                            & CCID_CLASS_PIN_VERIFY)
1007                    {
1008                            pcsc_tlv -> tag = FEATURE_VERIFY_PIN_DIRECT;
1009                            pcsc_tlv -> length = 0x04; /* always 0x04 */
1010                            pcsc_tlv -> value = htonl(IOCTL_FEATURE_VERIFY_PIN_DIRECT);
1011    
1012                            pcsc_tlv++;
1013                            iBytesReturned += sizeof(PCSC_TLV_STRUCTURE);
1014                    }
1015    
1016                    if (get_ccid_descriptor(reader_index) -> bPINSupport
1017                            & CCID_CLASS_PIN_MODIFY)
1018                    {
1019                            pcsc_tlv -> tag = FEATURE_MODIFY_PIN_DIRECT;
1020                            pcsc_tlv -> length = 0x04; /* always 0x04 */
1021                            pcsc_tlv -> value = htonl(IOCTL_FEATURE_MODIFY_PIN_DIRECT);
1022    
1023                            pcsc_tlv++;
1024                            iBytesReturned += sizeof(PCSC_TLV_STRUCTURE);
1025                    }
1026                    *pdwBytesReturned = iBytesReturned;
1027                    return_value = IFD_SUCCESS;
1028            }
1029    
1030            /* Verify a PIN, plain CCID */
1031            if (IOCTL_FEATURE_VERIFY_PIN_DIRECT == dwControlCode)
1032          {          {
1033                  unsigned int iBytesReturned;                  unsigned int iBytesReturned;
1034    
1035                  iBytesReturned = RxLength;                  iBytesReturned = RxLength;
1036                  return_value = SecurePIN(reader_index, TxBuffer, TxLength, RxBuffer,                  return_value = SecurePINVerify(reader_index, TxBuffer, TxLength,
1037                          &iBytesReturned);                          RxBuffer, &iBytesReturned);
1038                    *pdwBytesReturned = iBytesReturned;
1039            }
1040    
1041            /* Modify a PIN, plain CCID */
1042            if (IOCTL_FEATURE_MODIFY_PIN_DIRECT == dwControlCode)
1043            {
1044                    unsigned int iBytesReturned;
1045    
1046                    iBytesReturned = RxLength;
1047                    return_value = SecurePINModify(reader_index, TxBuffer, TxLength,
1048                            RxBuffer, &iBytesReturned);
1049                  *pdwBytesReturned = iBytesReturned;                  *pdwBytesReturned = iBytesReturned;
1050          }          }
1051    
# Line 867  RESPONSECODE IFDHControl(DWORD Lun, DWOR Line 1053  RESPONSECODE IFDHControl(DWORD Lun, DWOR
1053  } /* IFDHControl */  } /* IFDHControl */
1054    
1055    
1056  RESPONSECODE IFDHICCPresence(DWORD Lun)  EXTERNAL RESPONSECODE IFDHICCPresence(DWORD Lun)
1057  {  {
1058          /*          /*
1059           * This function returns the status of the card inserted in the           * This function returns the status of the card inserted in the
# Line 882  RESPONSECODE IFDHICCPresence(DWORD Lun) Line 1068  RESPONSECODE IFDHICCPresence(DWORD Lun)
1068          int oldLogLevel;          int oldLogLevel;
1069          int reader_index;          int reader_index;
1070          _ccid_descriptor *ccid_descriptor;          _ccid_descriptor *ccid_descriptor;
1071            unsigned int oldReadTimeout;
1072    
1073          DEBUG_PERIODIC2("lun: %X", Lun);          DEBUG_PERIODIC2("lun: %X", Lun);
1074    
# Line 890  RESPONSECODE IFDHICCPresence(DWORD Lun) Line 1077  RESPONSECODE IFDHICCPresence(DWORD Lun)
1077    
1078          ccid_descriptor = get_ccid_descriptor(reader_index);          ccid_descriptor = get_ccid_descriptor(reader_index);
1079    
1080            /* save the current read timeout computed from card capabilities */
1081            oldReadTimeout = ccid_descriptor->readTimeout;
1082    
1083            /* use default timeout since the reader may not be present anymore */
1084            ccid_descriptor->readTimeout = DEFAULT_COM_READ_TIMEOUT;
1085    
1086          /* if DEBUG_LEVEL_PERIODIC is not set we remove DEBUG_LEVEL_COMM */          /* if DEBUG_LEVEL_PERIODIC is not set we remove DEBUG_LEVEL_COMM */
1087          oldLogLevel = LogLevel;          oldLogLevel = LogLevel;
1088          if (! (LogLevel & DEBUG_LEVEL_PERIODIC))          if (! (LogLevel & DEBUG_LEVEL_PERIODIC))
# Line 897  RESPONSECODE IFDHICCPresence(DWORD Lun) Line 1090  RESPONSECODE IFDHICCPresence(DWORD Lun)
1090    
1091          return_value = CmdGetSlotStatus(reader_index, pcbuffer);          return_value = CmdGetSlotStatus(reader_index, pcbuffer);
1092    
1093            /* set back the old timeout */
1094            ccid_descriptor->readTimeout = oldReadTimeout;
1095    
1096          /* set back the old LogLevel */          /* set back the old LogLevel */
1097          LogLevel = oldLogLevel;          LogLevel = oldLogLevel;
1098    
# Line 907  RESPONSECODE IFDHICCPresence(DWORD Lun) Line 1103  RESPONSECODE IFDHICCPresence(DWORD Lun)
1103          switch (pcbuffer[7] & CCID_ICC_STATUS_MASK)     /* bStatus */          switch (pcbuffer[7] & CCID_ICC_STATUS_MASK)     /* bStatus */
1104          {          {
1105                  case CCID_ICC_PRESENT_ACTIVE:                  case CCID_ICC_PRESENT_ACTIVE:
                 case CCID_ICC_PRESENT_INACTIVE:  
1106                          return_value = IFD_ICC_PRESENT;                          return_value = IFD_ICC_PRESENT;
1107                          /* use default slot */                          /* use default slot */
1108                          break;                          break;
1109    
1110                    case CCID_ICC_PRESENT_INACTIVE:
1111                            if (CcidSlots[reader_index].bPowerFlags == POWERFLAGS_RAZ)
1112                                    /* the card was previously absent */
1113                                    return_value = IFD_ICC_PRESENT;
1114                            else
1115                            {
1116                                    /* the card was previously present but has been
1117                                     * removed and inserted between two consecutive
1118                                     * IFDHICCPresence() calls */
1119                                    CcidSlots[reader_index].bPowerFlags = POWERFLAGS_RAZ;
1120                                    return_value = IFD_ICC_NOT_PRESENT;
1121                            }
1122                            break;
1123    
1124                  case CCID_ICC_ABSENT:                  case CCID_ICC_ABSENT:
1125                          /* Reset ATR buffer */                          /* Reset ATR buffer */
1126                          CcidSlots[reader_index].nATRLength = 0;                          CcidSlots[reader_index].nATRLength = 0;
# Line 925  RESPONSECODE IFDHICCPresence(DWORD Lun) Line 1134  RESPONSECODE IFDHICCPresence(DWORD Lun)
1134          }          }
1135    
1136          /* SCR331-DI contactless reader */          /* SCR331-DI contactless reader */
1137          if ((SCR331DI == ccid_descriptor->readerID)          if (((SCR331DI == ccid_descriptor->readerID)
1138                    || (SDI010 == ccid_descriptor->readerID)
1139                    || (SCR331DINTTCOM == ccid_descriptor->readerID))
1140                  && (ccid_descriptor->bCurrentSlotIndex > 0))                  && (ccid_descriptor->bCurrentSlotIndex > 0))
1141          {          {
1142                  unsigned char cmd[] = { 0x11 };                  unsigned char cmd[] = { 0x11 };
# Line 935  RESPONSECODE IFDHICCPresence(DWORD Lun) Line 1146  RESPONSECODE IFDHICCPresence(DWORD Lun)
1146    
1147                  unsigned char res[10];                  unsigned char res[10];
1148                  unsigned int length_res = sizeof(res);                  unsigned int length_res = sizeof(res);
1149                    RESPONSECODE ret;
1150    
1151                  /* if DEBUG_LEVEL_PERIODIC is not set we remove DEBUG_LEVEL_COMM */                  /* if DEBUG_LEVEL_PERIODIC is not set we remove DEBUG_LEVEL_COMM */
1152                  oldLogLevel = LogLevel;                  oldLogLevel = LogLevel;
1153                  if (! (LogLevel & DEBUG_LEVEL_PERIODIC))                  if (! (LogLevel & DEBUG_LEVEL_PERIODIC))
1154                          LogLevel &= ~DEBUG_LEVEL_COMM;                          LogLevel &= ~DEBUG_LEVEL_COMM;
1155    
1156                  CmdEscape(reader_index, cmd, sizeof(cmd), res, &length_res);                  ret = CmdEscape(reader_index, cmd, sizeof(cmd), res, &length_res);
1157    
1158                  /* set back the old LogLevel */                  /* set back the old LogLevel */
1159                  LogLevel = oldLogLevel;                  LogLevel = oldLogLevel;
1160    
1161                    if (ret != IFD_SUCCESS)
1162                    {
1163                            DEBUG_INFO("CmdEscape failed");
1164                            /* simulate a card absent */
1165                            res[0] = 0;
1166                    }
1167    
1168                  if (0x01 == res[0])                  if (0x01 == res[0])
1169                          return_value = IFD_ICC_PRESENT;                          return_value = IFD_ICC_PRESENT;
1170                  else                  else
# Line 990  void init_driver(void) Line 1209  void init_driver(void)
1209                  LogLevel = strtoul(keyValue, NULL, 0);                  LogLevel = strtoul(keyValue, NULL, 0);
1210    
1211                  /* print the log level used */                  /* print the log level used */
1212                  debug_msg("%s:%d:%s LogLevel: 0x%.4X", __FILE__, __LINE__, __FUNCTION__,                  DEBUG_INFO2("LogLevel: 0x%.4X", LogLevel);
                         LogLevel);  
1213          }          }
1214    
1215          /* Driver options */          /* Driver options */
# Line 1001  void init_driver(void) Line 1219  void init_driver(void)
1219                  DriverOptions = strtoul(keyValue, NULL, 0);                  DriverOptions = strtoul(keyValue, NULL, 0);
1220    
1221                  /* print the log level used */                  /* print the log level used */
1222                  debug_msg("%s:%d:%s DriverOptions: 0x%.4X", __FILE__, __LINE__,                  DEBUG_INFO2("DriverOptions: 0x%.4X", DriverOptions);
1223                          __FUNCTION__, DriverOptions);          }
1224    
1225            /* get the voltage parameter */
1226            switch ((DriverOptions >> 4) & 0x03)
1227            {
1228                    case 0:
1229                            PowerOnVoltage = VOLTAGE_5V;
1230                            break;
1231    
1232                    case 1:
1233                            PowerOnVoltage = VOLTAGE_3V;
1234                            break;
1235    
1236                    case 2:
1237                            PowerOnVoltage = VOLTAGE_1_8V;
1238                            break;
1239    
1240                    case 3:
1241                            PowerOnVoltage = VOLTAGE_AUTO;
1242                            break;
1243          }          }
1244    
1245          /* initialise the Lun to reader_index mapping */          /* initialise the Lun to reader_index mapping */
# Line 1011  void init_driver(void) Line 1248  void init_driver(void)
1248          DebugInitialized = TRUE;          DebugInitialized = TRUE;
1249  } /* init_driver */  } /* init_driver */
1250    
1251    
1252    void extra_egt(ATR_t *atr, _ccid_descriptor *ccid_desc, DWORD Protocol)
1253    {
1254            /* This function use an EGT value for cards who comply with followings
1255             * criterias:
1256             * - TA1 > 11
1257             * - current EGT = 0x00 or 0xFF
1258             * - T=0 or (T=1 and CWI >= 2)
1259             *
1260             * Without this larger EGT some non ISO 7816-3 smart cards may not
1261             * communicate with the reader.
1262             *
1263             * This modification is harmless, the reader will just be less restrictive
1264             */
1265    
1266            unsigned int card_baudrate;
1267            unsigned int default_baudrate;
1268            double f, d;
1269            int i;
1270    
1271            /* if TA1 not present */
1272            if (! atr->ib[0][ATR_INTERFACE_BYTE_TA].present)
1273                    return;
1274    
1275            ATR_GetParameter(atr, ATR_PARAMETER_D, &d);
1276            ATR_GetParameter(atr, ATR_PARAMETER_F, &f);
1277    
1278            /* may happen with non ISO cards */
1279            if ((0 == f) || (0 == d))
1280                    return;
1281    
1282            /* Baudrate = f x D/F */
1283            card_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock * d / f);
1284    
1285            default_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock
1286                    * ATR_DEFAULT_D / ATR_DEFAULT_F);
1287    
1288            /* TA1 > 11? */
1289            if (card_baudrate <= default_baudrate)
1290                    return;
1291    
1292            /* Current EGT = 0 or FF? */
1293            if (atr->ib[0][ATR_INTERFACE_BYTE_TC].present &&
1294                    ((0x00 == atr->ib[0][ATR_INTERFACE_BYTE_TC].value) ||
1295                    (0xFF == atr->ib[0][ATR_INTERFACE_BYTE_TC].value)))
1296            {
1297                    if (SCARD_PROTOCOL_T0 == Protocol)
1298                    {
1299                            /* Init TC1 */
1300                            atr->ib[0][ATR_INTERFACE_BYTE_TC].present = TRUE;
1301                            atr->ib[0][ATR_INTERFACE_BYTE_TC].value = 2;
1302                            DEBUG_INFO("Extra EGT patch applied");
1303                    }
1304    
1305                    if (SCARD_PROTOCOL_T1 == Protocol)
1306                    {
1307                            /* TBi (i>2) present? BWI/CWI */
1308                            for (i=2; i<ATR_MAX_PROTOCOLS; i++)
1309                            {
1310                                    /* CWI >= 2 ? */
1311                                    if (atr->ib[i][ATR_INTERFACE_BYTE_TB].present &&
1312                                            ((atr->ib[i][ATR_INTERFACE_BYTE_TB].value & 0x0F) >= 2))
1313                                    {
1314                                            /* Init TC1 */
1315                                            atr->ib[0][ATR_INTERFACE_BYTE_TC].present = TRUE;
1316                                            atr->ib[0][ATR_INTERFACE_BYTE_TC].value = 2;
1317                                            DEBUG_INFO("Extra EGT patch applied");
1318    
1319                                            /* only the first TBi (i>2) must be used */
1320                                            break;
1321                                    }
1322                            }
1323                    }
1324            }
1325    } /* extra_egt */
1326    
1327    
1328    static char find_baud_rate(unsigned int baudrate, unsigned int *list)
1329    {
1330            int i;
1331    
1332            DEBUG_COMM2("Card baud rate: %d", baudrate);
1333    
1334            /* Does the reader support the announced smart card data speed? */
1335            for (i=0;; i++)
1336            {
1337                    /* end of array marker */
1338                    if (0 == list[i])
1339                            break;
1340    
1341                    DEBUG_COMM2("Reader can do: %d", list[i]);
1342    
1343                    /* We must take into account that the card_baudrate integral value
1344                     * is an approximative result, computed from the d/f float result.
1345                     */
1346                    if ((baudrate < list[i] + 2) && (baudrate > list[i] - 2))
1347                            return TRUE;
1348            }
1349    
1350            return FALSE;
1351    } /* find_baud_rate */
1352    
1353    
1354    static unsigned int T0_card_timeout(double f, double d, int TC1, int TC2,
1355            int clock_frequency)
1356    {
1357            unsigned int timeout = DEFAULT_COM_READ_TIMEOUT;
1358            double EGT, WWT;
1359            unsigned int t;
1360    
1361            /* Timeout applied on ISO_IN or ISO_OUT card exchange
1362             * we choose the maximum computed value.
1363             *
1364             * ISO_IN timeout is the sum of:
1365             * Terminal:                                    Smart card:
1366             * 5 bytes header cmd  ->
1367             *                    <-                Procedure byte
1368             * 256 data bytes          ->
1369             *                                        <-            SW1-SW2
1370             * = 261 EGT       + 3 WWT     + 3 WWT
1371             *
1372             * ISO_OUT Timeout is the sum of:
1373             * Terminal:                    Smart card:
1374             * 5 bytes header cmd  ->
1375             *                                        <-        Procedure byte + 256 data bytes + SW1-SW2
1376             * = 5 EGT          + 1 WWT     + 259 WWT
1377             */
1378    
1379            /* clock_frequency is in kHz so the times are in milliseconds and not
1380             * in seconds */
1381    
1382            /* may happen with non ISO cards */
1383            if ((0 == f) || (0 == d) || (0 == clock_frequency))
1384                    return 60;      /* 60 seconds */
1385    
1386            /* EGT */
1387            /* see ch. 6.5.3 Extra Guard Time, page 12 of ISO 7816-3 */
1388            EGT = 12 * f / d / clock_frequency + (f / d) * TC1 / clock_frequency;
1389    
1390            /* card WWT */
1391            /* see ch. 8.2 Character level, page 15 of ISO 7816-3 */
1392            WWT = 960 * TC2 * f / clock_frequency;
1393    
1394            /* ISO in */
1395            t  = 261 * EGT + (3 + 3) * WWT;
1396            /* Convert from milliseonds to seconds rouned to the upper value
1397             * use +1 instead of ceil() to round up to the nearest interger
1398             * so we can avoid a dependency on the math library */
1399            t = t/1000 +1;
1400            if (timeout < t)
1401                    timeout = t;
1402    
1403            /* ISO out */
1404            t = 5 * EGT + (1 + 259) * WWT;
1405            t = t/1000 +1;
1406            if (timeout < t)
1407                    timeout = t;
1408    
1409            return timeout;
1410    } /* T0_card_timeout  */
1411    
1412    
1413    static unsigned int T1_card_timeout(double f, double d, int TC1,
1414            int BWI, int CWI, int clock_frequency)
1415    {
1416            double EGT, BWT, CWT, etu;
1417            unsigned int timeout;
1418    
1419            /* Timeout applied on ISO in + ISO out card exchange
1420             *
1421         * Timeout is the sum of:
1422             * - ISO in delay between leading edge of the first character sent by the
1423             *   interface device and the last one (NAD PCB LN APDU CKS) = 260 EGT,
1424             * - delay between ISO in and ISO out = BWT,
1425             * - ISO out delay between leading edge of the first character sent by the
1426             *   card and the last one (NAD PCB LN DATAS CKS) = 260 CWT.
1427             */
1428    
1429            /* clock_frequency is in kHz so the times are in milliseconds and not
1430             * in seconds */
1431    
1432            /* may happen with non ISO cards */
1433            if ((0 == f) || (0 == d) || (0 == clock_frequency))
1434                    return 60;      /* 60 seconds */
1435    
1436            /* see ch. 6.5.2 Transmission factors F and D, page 12 of ISO 7816-3 */
1437            etu = f / d / clock_frequency;
1438    
1439            /* EGT */
1440            /* see ch. 6.5.3 Extra Guard Time, page 12 of ISO 7816-3 */
1441            EGT = 12 * etu + (f / d) * TC1 / clock_frequency;
1442    
1443            /* card BWT */
1444            /* see ch. 9.5.3.2 Block Waiting Time, page 20 of ISO 7816-3 */
1445            BWT = 11 * etu + (1<<BWI) * 960 * 372 / clock_frequency;
1446    
1447            /* card CWT */
1448            /* see ch. 9.5.3.1 Caracter Waiting Time, page 20 of ISO 7816-3 */
1449            CWT = (11 + (1<<CWI)) * etu;
1450    
1451            timeout = 260*EGT + BWT + 260*CWT;
1452    
1453            /* Convert from milliseonds to seconds rounded to the upper value
1454             * we use +1 instead of ceil() to round up to the nearest greater interger
1455             * so we can avoid a dependency on the math library */
1456            timeout = timeout/1000 +1;
1457    
1458            return timeout;
1459    } /* T1_card_timeout  */
1460    

Legend:
Removed from v.1352  
changed lines
  Added in v.2175

  ViewVC Help
Powered by ViewVC 1.1.5