/[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 1078 by rousseau, Fri Jul 16 07:06:14 2004 UTC revision 2168 by rousseau, Wed Sep 20 14:01:14 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;
73    
74          if (! DebugInitialized)          if (! DebugInitialized)
75                  init_driver();                  init_driver();
76    
77          DEBUG_INFO3("lun: %X, device: %s", Lun, lpcDevice);          DEBUG_INFO3("lun: %X, device: %s", Lun, lpcDevice);
78    
79          if (CheckLun(Lun))          if (-1 == (reader_index = GetNewReaderIndex(Lun)))
80                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
81    
82          /* Reset ATR buffer */          /* Reset ATR buffer */
83          CcidSlots[LunToReaderIndex(Lun)].nATRLength = 0;          CcidSlots[reader_index].nATRLength = 0;
84          *CcidSlots[LunToReaderIndex(Lun)].pcATRBuffer = '\0';          *CcidSlots[reader_index].pcATRBuffer = '\0';
85    
86          /* Reset PowerFlags */          /* Reset PowerFlags */
87          CcidSlots[LunToReaderIndex(Lun)].bPowerFlags = POWERFLAGS_RAZ;          CcidSlots[reader_index].bPowerFlags = POWERFLAGS_RAZ;
88    
89  #ifdef HAVE_PTHREAD  #ifdef HAVE_PTHREAD
90          pthread_mutex_lock(&ifdh_context_mutex);          pthread_mutex_lock(&ifdh_context_mutex);
91  #endif  #endif
92    
93          if (OpenPortByName(Lun, lpcDevice) != STATUS_SUCCESS)          if (OpenPortByName(reader_index, lpcDevice) != STATUS_SUCCESS)
94          {          {
95                  DEBUG_CRITICAL("failed");                  DEBUG_CRITICAL("failed");
96                  return_value = IFD_COMMUNICATION_ERROR;                  return_value = IFD_COMMUNICATION_ERROR;
97    
98                    /* release the allocated reader_index */
99                    ReleaseReaderIndex(reader_index);
100          }          }
101            else
102            {
103                    /* Maybe we have a special treatment for this reader */
104                    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          /* Maybe we have a special treatment for this reader */                          /* release the allocated reader_index */
119          ccid_open_hack(Lun);                          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);
# Line 96  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 132  RESPONSECODE IFDHCreateChannel(DWORD Lun Line 164  RESPONSECODE IFDHCreateChannel(DWORD Lun
164           * IFD_SUCCESS IFD_COMMUNICATION_ERROR           * IFD_SUCCESS IFD_COMMUNICATION_ERROR
165           */           */
166          RESPONSECODE return_value = IFD_SUCCESS;          RESPONSECODE return_value = IFD_SUCCESS;
167            int reader_index;
168    
169          if (! DebugInitialized)          if (! DebugInitialized)
170                  init_driver();                  init_driver();
171    
172          DEBUG_INFO2("lun: %X", Lun);          DEBUG_INFO2("lun: %X", Lun);
173    
174          if (CheckLun(Lun))          if (-1 == (reader_index = GetNewReaderIndex(Lun)))
175                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
176    
177          /* Reset ATR buffer */          /* Reset ATR buffer */
178          CcidSlots[LunToReaderIndex(Lun)].nATRLength = 0;          CcidSlots[reader_index].nATRLength = 0;
179          *CcidSlots[LunToReaderIndex(Lun)].pcATRBuffer = '\0';          *CcidSlots[reader_index].pcATRBuffer = '\0';
180    
181          /* Reset PowerFlags */          /* Reset PowerFlags */
182          CcidSlots[LunToReaderIndex(Lun)].bPowerFlags = POWERFLAGS_RAZ;          CcidSlots[reader_index].bPowerFlags = POWERFLAGS_RAZ;
183    
184  #ifdef HAVE_PTHREAD  #ifdef HAVE_PTHREAD
185          pthread_mutex_lock(&ifdh_context_mutex);          pthread_mutex_lock(&ifdh_context_mutex);
186  #endif  #endif
187    
188          if (OpenPort(Lun, Channel) != STATUS_SUCCESS)          if (OpenPort(reader_index, Channel) != STATUS_SUCCESS)
189          {          {
190                  DEBUG_CRITICAL("failed");                  DEBUG_CRITICAL("failed");
191                  return_value = IFD_COMMUNICATION_ERROR;                  return_value = IFD_COMMUNICATION_ERROR;
         }  
192    
193          /* Maybe we have a special treatment for this reader */                  /* release the allocated reader_index */
194          ccid_open_hack(Lun);                  ReleaseReaderIndex(reader_index);
195            }
196            else
197                    /* Maybe we have a special treatment for this reader */
198                    ccid_open_hack(reader_index);
199    
200  #ifdef HAVE_PTHREAD  #ifdef HAVE_PTHREAD
201          pthread_mutex_unlock(&ifdh_context_mutex);          pthread_mutex_unlock(&ifdh_context_mutex);
# Line 169  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 181  RESPONSECODE IFDHCloseChannel(DWORD Lun) Line 217  RESPONSECODE IFDHCloseChannel(DWORD Lun)
217           *           *
218           * IFD_SUCCESS IFD_COMMUNICATION_ERROR           * IFD_SUCCESS IFD_COMMUNICATION_ERROR
219           */           */
220            int reader_index;
221    
222          DEBUG_INFO2("lun: %X", Lun);          DEBUG_INFO2("lun: %X", Lun);
223    
224          if (CheckLun(Lun))          if (-1 == (reader_index = LunToReaderIndex(Lun)))
225                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
226    
227          (void)CmdPowerOff(Lun);          /* 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);
232          /* No reader status check, if it failed, what can you do ? :) */          /* No reader status check, if it failed, what can you do ? :) */
233    
234  #ifdef HAVE_PTHREAD  #ifdef HAVE_PTHREAD
235          pthread_mutex_lock(&ifdh_context_mutex);          pthread_mutex_lock(&ifdh_context_mutex);
236  #endif  #endif
237    
238          (void)ClosePort(Lun);          (void)ClosePort(reader_index);
239            ReleaseReaderIndex(reader_index);
240    
241  #ifdef HAVE_PTHREAD  #ifdef HAVE_PTHREAD
242          pthread_mutex_unlock(&ifdh_context_mutex);          pthread_mutex_unlock(&ifdh_context_mutex);
# Line 204  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 224  RESPONSECODE IFDHGetCapabilities(DWORD L Line 266  RESPONSECODE IFDHGetCapabilities(DWORD L
266           *           *
267           * IFD_SUCCESS IFD_ERROR_TAG           * IFD_SUCCESS IFD_ERROR_TAG
268           */           */
269            int reader_index;
270    
271          DEBUG_INFO3("lun: %X, tag: 0x%X", Lun, Tag);          DEBUG_INFO3("lun: %X, tag: 0x%X", Lun, Tag);
272    
273          if (CheckLun(Lun))          if (-1 == (reader_index = LunToReaderIndex(Lun)))
274                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
275    
276          switch (Tag)          switch (Tag)
# Line 237  RESPONSECODE IFDHGetCapabilities(DWORD L Line 280  RESPONSECODE IFDHGetCapabilities(DWORD L
280                          /* If Length is not zero, powerICC has been performed.                          /* If Length is not zero, powerICC has been performed.
281                           * Otherwise, return NULL pointer                           * Otherwise, return NULL pointer
282                           * Buffer size is stored in *Length */                           * Buffer size is stored in *Length */
283                          *Length = (*Length < CcidSlots[LunToReaderIndex(Lun)].nATRLength) ?                          *Length = (*Length < CcidSlots[reader_index].nATRLength) ?
284                                  *Length : CcidSlots[LunToReaderIndex(Lun)].nATRLength;                                  *Length : CcidSlots[reader_index].nATRLength;
285    
286                          if (*Length)                          if (*Length)
287                                  memcpy(Value, CcidSlots[LunToReaderIndex(Lun)]                                  memcpy(Value, CcidSlots[reader_index].pcATRBuffer, *Length);
                                         .pcATRBuffer, *Length);  
288                          break;                          break;
289    
290  #ifdef HAVE_PTHREAD  #ifdef HAVE_PTHREAD
# Line 267  RESPONSECODE IFDHGetCapabilities(DWORD L Line 309  RESPONSECODE IFDHGetCapabilities(DWORD L
309                          if (*Length >= 1)                          if (*Length >= 1)
310                          {                          {
311                                  *Length = 1;                                  *Length = 1;
312                                  *Value = 1; /* One slot only */                                  *Value = 1 + get_ccid_descriptor(reader_index) -> bMaxSlotIndex;
313                                    DEBUG_INFO2("Reader supports %d slots", *Value);
314                          }                          }
315                          break;                          break;
316    
317                  case IOCTL_SMARTCARD_VENDOR_VERIFY_PIN:                  case TAG_IFD_SLOT_THREAD_SAFE:
318                          if (*Length >= 1)                          if (*Length >= 1)
319                          {                          {
320                                  *Length = 1;                                  *Length = 1;
321                                  *Value = get_ccid_descriptor(Lun) -> bPINSupport & CCID_CLASS_PIN_VERIFY;                                  *Value = 0; /* Can NOT talk to multiple slots at the same time */
322                          }                          }
323                          break;                          break;
324    
325                    case SCARD_ATTR_VENDOR_IFD_VERSION:
326                            /* Vendor-supplied interface device version (DWORD in the form
327                             * 0xMMmmbbbb where MM = major version, mm = minor version, and
328                             * bbbb = build number). */
329                            *Length = sizeof(DWORD);
330                            if (Value)
331                                    *(DWORD *)Value = CCID_VERSION;
332                            break;
333    
334                    case SCARD_ATTR_VENDOR_NAME:
335    #define VENDOR_NAME "Ludovic Rousseau"
336                            *Length = sizeof(VENDOR_NAME);
337                            if (Value)
338                                    memcpy(Value, VENDOR_NAME, sizeof(VENDOR_NAME));
339                            break;
340    
341                  default:                  default:
342                          return IFD_ERROR_TAG;                          return IFD_ERROR_TAG;
343          }          }
# Line 287  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 318  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 341  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;
407    
408          /* Set ccid desc params */          /* Set ccid desc params */
409          CcidDesc *ccid_slot;          CcidDesc *ccid_slot;
# Line 351  RESPONSECODE IFDHSetProtocolParameters(D Line 411  RESPONSECODE IFDHSetProtocolParameters(D
411    
412          DEBUG_INFO3("lun: %X, protocol T=%d", Lun, Protocol-1);          DEBUG_INFO3("lun: %X, protocol T=%d", Lun, Protocol-1);
413    
414          if (CheckLun(Lun))          if (-1 == (reader_index = LunToReaderIndex(Lun)))
415                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
416    
417          /* Set to zero buffer */          /* Set to zero buffer */
# Line 359  RESPONSECODE IFDHSetProtocolParameters(D Line 419  RESPONSECODE IFDHSetProtocolParameters(D
419          memset(&atr, 0, sizeof(atr));          memset(&atr, 0, sizeof(atr));
420    
421          /* Get ccid params */          /* Get ccid params */
422          ccid_slot = get_ccid_slot(Lun);          ccid_slot = get_ccid_slot(reader_index);
423          ccid_desc = get_ccid_descriptor(Lun);          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 425  RESPONSECODE IFDHSetProtocolParameters(D Line 493  RESPONSECODE IFDHSetProtocolParameters(D
493          }          }
494          else          else
495          {          {
496                  /* PPS not negociated by reader, and TA1 present */                  /* TA1 present */
497                  if (atr.ib[0][ATR_INTERFACE_BYTE_TA].present &&                  if (atr.ib[0][ATR_INTERFACE_BYTE_TA].present)
                         ! (ccid_desc->dwFeatures & CCID_CLASS_AUTO_PPS_CUR))  
498                  {                  {
499                          unsigned int card_baudrate;                          unsigned int card_baudrate;
500                          unsigned int default_baudrate;                          unsigned int default_baudrate;
# Line 436  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 443  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                                    /* the reader has no baud rates table */
527                                    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);
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                                  pps[1] |= 0x10; /* PTS1 presence */                                  /* the card is too fast for the reader */
552                                  pps[2] = atr.ib[0][ATR_INTERFACE_BYTE_TA].value;                                  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 speed to %d bauds", card_baudrate);                                                          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 486  RESPONSECODE IFDHSetProtocolParameters(D Line 620  RESPONSECODE IFDHSetProtocolParameters(D
620                  /* if the requested protocol is not the default one                  /* if the requested protocol is not the default one
621                   * or a TA1/PPS1 is present */                   * or a TA1/PPS1 is present */
622                  if (((pps[1] & 0x0F) != default_protocol) || (PPS_HAS_PPS1(pps)))                  if (((pps[1] & 0x0F) != default_protocol) || (PPS_HAS_PPS1(pps)))
623                          if (PPS_Exchange(Lun, pps, &len, &pps[2]) != PPS_OK)                          if (PPS_Exchange(reader_index, pps, &len, &pps[2]) != PPS_OK)
624                          {                          {
625                                  DEBUG_INFO("PPS_Exchange Failed");                                  DEBUG_INFO("PPS_Exchange Failed");
626    
# Line 509  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             */
650                  };                  };
651                  int i;                  int i;
652                    t1_state_t *t1 = &(ccid_slot -> t1);
653                    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? */
661                    if (2 == t1->rc_bytes)
662                            param[1] |= 0x01;
663    
664                    /* the CCID should ignore this bit */
665                  if (ATR_CONVENTION_INVERSE == convention)                  if (ATR_CONVENTION_INVERSE == convention)
666                          param[1] &= 0x02;                          param[1] |= 0x02;
667    
668                  /* get TC1 Extra guard time */                  /* get TC1 Extra guard time */
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 539  RESPONSECODE IFDHSetProtocolParameters(D Line 681  RESPONSECODE IFDHSetProtocolParameters(D
681                                  break;                                  break;
682                          }                          }
683    
684                  if (IFD_SUCCESS != SetParameters(Lun, 1, sizeof(param), param))                  /* compute communication timeout */
685                          return IFD_COMMUNICATION_ERROR;                  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);
694                    if (IFD_SUCCESS != ret)
695                            return ret;
696          }          }
697          else          else
698          /* T=0 */          /* T=0 */
# Line 552  RESPONSECODE IFDHSetProtocolParameters(D Line 704  RESPONSECODE IFDHSetProtocolParameters(D
704                          0x0A,   /* WaitingInteger       */                          0x0A,   /* WaitingInteger       */
705                          0x00    /* ClockStop            */                          0x00    /* ClockStop            */
706                  };                  };
707                    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))
712                          param[0] = pps[2];                          param[0] = pps[2];
713    
714                  if (ATR_CONVENTION_INVERSE == convention)                  if (ATR_CONVENTION_INVERSE == convention)
715                          param[1] &= 0x02;                          param[1] |= 0x02;
716    
717                  /* get TC1 Extra guard time */                  /* get TC1 Extra guard time */
718                  if (atr.ib[0][ATR_INTERFACE_BYTE_TC].present)                  if (atr.ib[0][ATR_INTERFACE_BYTE_TC].present)
# Line 568  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                  if (IFD_SUCCESS != SetParameters(Lun, 0, sizeof(param), param))                  /* compute communication timeout */
726                          return IFD_COMMUNICATION_ERROR;                  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);
736                    if (IFD_SUCCESS != ret)
737                            return ret;
738          }          }
739    
740          /* set IFSC & IFSD in T=1 */          /* set IFSC & IFSD in T=1 */
# Line 594  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 603  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 649  RESPONSECODE IFDHPowerICC(DWORD Lun, DWO Line 817  RESPONSECODE IFDHPowerICC(DWORD Lun, DWO
817          unsigned int nlength;          unsigned int nlength;
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;
821    
822          DEBUG_INFO2("lun: %X", Lun);          DEBUG_INFO2("lun: %X", Lun);
823    
824          /* By default, assume it won't work :) */          /* By default, assume it won't work :) */
825          *AtrLength = 0;          *AtrLength = 0;
826    
827          if (CheckLun(Lun))          if (-1 == (reader_index = LunToReaderIndex(Lun)))
828                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
829    
830          switch (Action)          switch (Action)
831          {          {
832                  case IFD_POWER_DOWN:                  case IFD_POWER_DOWN:
833                          /* Clear ATR buffer */                          /* Clear ATR buffer */
834                          CcidSlots[LunToReaderIndex(Lun)].nATRLength = 0;                          CcidSlots[reader_index].nATRLength = 0;
835                          *CcidSlots[LunToReaderIndex(Lun)].pcATRBuffer = '\0';                          *CcidSlots[reader_index].pcATRBuffer = '\0';
836    
837                          /* Memorise the request */                          /* Memorise the request */
838                          CcidSlots[LunToReaderIndex(Lun)].bPowerFlags |=                          CcidSlots[reader_index].bPowerFlags |= MASK_POWERFLAGS_PDWN;
                                 MASK_POWERFLAGS_PDWN;  
839    
840                          /* send the command */                          /* send the command */
841                          if (IFD_SUCCESS != CmdPowerOff(Lun))                          if (IFD_SUCCESS != CmdPowerOff(reader_index))
842                          {                          {
843                                  DEBUG_CRITICAL("PowerDown failed");                                  DEBUG_CRITICAL("PowerDown failed");
844                                  return_value = IFD_ERROR_POWER_ACTION;                                  return_value = IFD_ERROR_POWER_ACTION;
# Line 678  RESPONSECODE IFDHPowerICC(DWORD Lun, DWO Line 846  RESPONSECODE IFDHPowerICC(DWORD Lun, DWO
846                          }                          }
847    
848                          /* clear T=1 context */                          /* clear T=1 context */
849                          t1_release(&(get_ccid_slot(Lun) -> t1));                          t1_release(&(get_ccid_slot(reader_index) -> t1));
850                          break;                          break;
851    
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(Lun, &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 692  RESPONSECODE IFDHPowerICC(DWORD Lun, DWO Line 861  RESPONSECODE IFDHPowerICC(DWORD Lun, DWO
861                          }                          }
862    
863                          /* Power up successful, set state variable to memorise it */                          /* Power up successful, set state variable to memorise it */
864                          CcidSlots[LunToReaderIndex(Lun)].bPowerFlags |=                          CcidSlots[reader_index].bPowerFlags |= MASK_POWERFLAGS_PUP;
865                                  MASK_POWERFLAGS_PUP;                          CcidSlots[reader_index].bPowerFlags &= ~MASK_POWERFLAGS_PDWN;
                         CcidSlots[LunToReaderIndex(Lun)].bPowerFlags &=  
                                 ~MASK_POWERFLAGS_PDWN;  
866    
867                          /* Reset is returned, even if TCK is wrong */                          /* Reset is returned, even if TCK is wrong */
868                          CcidSlots[LunToReaderIndex(Lun)].nATRLength = *AtrLength =                          CcidSlots[reader_index].nATRLength = *AtrLength =
869                                  (nlength < MAX_ATR_SIZE) ? nlength : MAX_ATR_SIZE;                                  (nlength < MAX_ATR_SIZE) ? nlength : MAX_ATR_SIZE;
870                          memcpy(Atr, pcbuffer, *AtrLength);                          memcpy(Atr, pcbuffer, *AtrLength);
871                          memcpy(CcidSlots[LunToReaderIndex(Lun)].pcATRBuffer,                          memcpy(CcidSlots[reader_index].pcATRBuffer, pcbuffer, *AtrLength);
                                 pcbuffer, *AtrLength);  
872    
873                          /* initialise T=1 context */                          /* initialise T=1 context */
874                          t1_init(&(get_ccid_slot(Lun) -> t1));                          t1_init(&(get_ccid_slot(reader_index) -> t1), reader_index);
875                          break;                          break;
876    
877                  default:                  default:
# Line 718  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 758  RESPONSECODE IFDHTransmitToICC(DWORD Lun Line 924  RESPONSECODE IFDHTransmitToICC(DWORD Lun
924    
925          RESPONSECODE return_value;          RESPONSECODE return_value;
926          unsigned int rx_length;          unsigned int rx_length;
927            int reader_index;
928    
929          DEBUG_INFO2("lun: %X", Lun);          DEBUG_INFO2("lun: %X", Lun);
930    
931          if (CheckLun(Lun))          if (-1 == (reader_index = LunToReaderIndex(Lun)))
932                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
933    
934          rx_length = *RxLength;          rx_length = *RxLength;
935          return_value = CmdXfrBlock(Lun, TxLength, TxBuffer, &rx_length, RxBuffer,          return_value = CmdXfrBlock(reader_index, TxLength, TxBuffer, &rx_length,
936                  SendPci.Protocol);                  RxBuffer, SendPci.Protocol);
937          *RxLength = rx_length;          *RxLength = rx_length;
938    
939          return return_value;          return return_value;
940  } /* IFDHTransmitToICC */  } /* IFDHTransmitToICC */
941    
942    
943  RESPONSECODE IFDHControl(DWORD Lun, DWORD dwControlCode, LPCVOID TxBuffer,  EXTERNAL RESPONSECODE IFDHControl(DWORD Lun, DWORD dwControlCode,
944          DWORD TxLength, LPVOID 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 791  RESPONSECODE IFDHControl(DWORD Lun, DWOR Line 959  RESPONSECODE IFDHControl(DWORD Lun, DWOR
959           * Notes: RxLength should be zero on error.           * Notes: RxLength should be zero on error.
960           */           */
961          RESPONSECODE return_value = IFD_COMMUNICATION_ERROR;          RESPONSECODE return_value = IFD_COMMUNICATION_ERROR;
962            int reader_index;
963    
964          DEBUG_INFO3("lun: %X, ControlCode: 0x%X", Lun, dwControlCode);          DEBUG_INFO3("lun: %X, ControlCode: 0x%X", Lun, dwControlCode);
965    
966          if (CheckLun(Lun) || (NULL == pdwBytesReturned) || (NULL == RxBuffer))          reader_index = LunToReaderIndex(Lun);
967            if ((-1 == reader_index) || (NULL == pdwBytesReturned))
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 812  RESPONSECODE IFDHControl(DWORD Lun, DWOR Line 982  RESPONSECODE IFDHControl(DWORD Lun, DWOR
982                          unsigned int iBytesReturned;                          unsigned int iBytesReturned;
983    
984                          iBytesReturned = RxLength;                          iBytesReturned = RxLength;
985                          return_value = CmdEscape(Lun, TxBuffer, TxLength, RxBuffer,                          return_value = CmdEscape(reader_index, TxBuffer, TxLength, RxBuffer,
986                                  &iBytesReturned);                                  &iBytesReturned);
987                          *pdwBytesReturned = iBytesReturned;                          *pdwBytesReturned = iBytesReturned;
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;                  unsigned int iBytesReturned;
1033    
1034                  iBytesReturned = RxLength;                  iBytesReturned = RxLength;
1035                  return_value = SecurePIN(Lun, TxBuffer, TxLength, RxBuffer,                  return_value = SecurePINVerify(reader_index, TxBuffer, TxLength,
1036                          &iBytesReturned);                          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;
1044    
1045                    iBytesReturned = RxLength;
1046                    return_value = SecurePINModify(reader_index, TxBuffer, TxLength,
1047                            RxBuffer, &iBytesReturned);
1048                  *pdwBytesReturned = iBytesReturned;                  *pdwBytesReturned = iBytesReturned;
1049          }          }
1050    
# Line 832  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 845  RESPONSECODE IFDHICCPresence(DWORD Lun) Line 1065  RESPONSECODE IFDHICCPresence(DWORD Lun)
1065          unsigned char pcbuffer[SIZE_GET_SLOT_STATUS];          unsigned char pcbuffer[SIZE_GET_SLOT_STATUS];
1066          RESPONSECODE return_value = IFD_COMMUNICATION_ERROR;          RESPONSECODE return_value = IFD_COMMUNICATION_ERROR;
1067          int oldLogLevel;          int oldLogLevel;
1068            int reader_index;
1069            _ccid_descriptor *ccid_descriptor;
1070            unsigned int oldReadTimeout;
1071    
1072          DEBUG_PERIODIC2("lun: %X", Lun);          DEBUG_PERIODIC2("lun: %X", Lun);
1073    
1074          if (CheckLun(Lun))          if (-1 == (reader_index = LunToReaderIndex(Lun)))
1075                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
1076    
1077            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))
1088                  LogLevel &= ~DEBUG_LEVEL_COMM;                  LogLevel &= ~DEBUG_LEVEL_COMM;
1089    
1090          return_value = CmdGetSlotStatus(Lun, 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;
# Line 865  RESPONSECODE IFDHICCPresence(DWORD Lun) Line 1099  RESPONSECODE IFDHICCPresence(DWORD Lun)
1099                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
1100    
1101          return_value = IFD_COMMUNICATION_ERROR;          return_value = IFD_COMMUNICATION_ERROR;
1102          switch (pcbuffer[7])    /* bStatus */          switch (pcbuffer[7] & CCID_ICC_STATUS_MASK)     /* bStatus */
1103          {          {
1104                  case 0x00:                  case CCID_ICC_PRESENT_ACTIVE:
                 case 0x01:  
1105                          return_value = IFD_ICC_PRESENT;                          return_value = IFD_ICC_PRESENT;
1106                            /* use default slot */
1107                          break;                          break;
1108    
1109                  case 0x02:                  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:
1124                          /* Reset ATR buffer */                          /* Reset ATR buffer */
1125                          CcidSlots[LunToReaderIndex(Lun)].nATRLength = 0;                          CcidSlots[reader_index].nATRLength = 0;
1126                          *CcidSlots[LunToReaderIndex(Lun)].pcATRBuffer = '\0';                          *CcidSlots[reader_index].pcATRBuffer = '\0';
1127    
1128                          /* Reset PowerFlags */                          /* Reset PowerFlags */
1129                          CcidSlots[LunToReaderIndex(Lun)].bPowerFlags = POWERFLAGS_RAZ;                          CcidSlots[reader_index].bPowerFlags = POWERFLAGS_RAZ;
1130    
1131                          return_value = IFD_ICC_NOT_PRESENT;                          return_value = IFD_ICC_NOT_PRESENT;
1132                          break;                          break;
1133          }          }
1134    
1135            /* SCR331-DI contactless reader */
1136            if (((SCR331DI == ccid_descriptor->readerID)
1137                    || (SDI010 == ccid_descriptor->readerID)
1138                    || (SCR331DINTTCOM == ccid_descriptor->readerID))
1139                    && (ccid_descriptor->bCurrentSlotIndex > 0))
1140            {
1141                    unsigned char cmd[] = { 0x11 };
1142                    /*  command: 11 ??
1143                     * response: 00 11 01 ?? no card
1144                     *           01 04 00 ?? card present */
1145    
1146                    unsigned char res[10];
1147                    unsigned int length_res = sizeof(res);
1148                    RESPONSECODE ret;
1149    
1150                    /* if DEBUG_LEVEL_PERIODIC is not set we remove DEBUG_LEVEL_COMM */
1151                    oldLogLevel = LogLevel;
1152                    if (! (LogLevel & DEBUG_LEVEL_PERIODIC))
1153                            LogLevel &= ~DEBUG_LEVEL_COMM;
1154    
1155                    ret = CmdEscape(reader_index, cmd, sizeof(cmd), res, &length_res);
1156    
1157                    /* set back the old LogLevel */
1158                    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])
1168                            return_value = IFD_ICC_PRESENT;
1169                    else
1170                    {
1171                            /* Reset ATR buffer */
1172                            CcidSlots[reader_index].nATRLength = 0;
1173                            *CcidSlots[reader_index].pcATRBuffer = '\0';
1174    
1175                            /* Reset PowerFlags */
1176                            CcidSlots[reader_index].bPowerFlags = POWERFLAGS_RAZ;
1177    
1178                            return_value = IFD_ICC_NOT_PRESENT;
1179                    }
1180            }
1181    
1182            DEBUG_PERIODIC2("Card %s",
1183                    IFD_ICC_PRESENT == return_value ? "present" : "absent");
1184    
1185          return return_value;          return return_value;
1186  } /* IFDHICCPresence */  } /* IFDHICCPresence */
1187    
1188    
1189  CcidDesc *get_ccid_slot(unsigned int lun)  CcidDesc *get_ccid_slot(unsigned int reader_index)
1190  {  {
1191          return &CcidSlots[LunToReaderIndex(lun)];          return &CcidSlots[reader_index];
1192  } /* get_ccid_slot */  } /* get_ccid_slot */
1193    
1194    
# Line 910  void init_driver(void) Line 1208  void init_driver(void)
1208                  LogLevel = strtoul(keyValue, NULL, 0);                  LogLevel = strtoul(keyValue, NULL, 0);
1209    
1210                  /* print the log level used */                  /* print the log level used */
1211                  debug_msg("%s:%d:%s LogLevel: 0x%.4X", __FILE__, __LINE__, __FUNCTION__,                  DEBUG_INFO2("LogLevel: 0x%.4X", LogLevel);
                         LogLevel);  
1212          }          }
1213    
1214          /* Driver options */          /* Driver options */
# Line 921  void init_driver(void) Line 1218  void init_driver(void)
1218                  DriverOptions = strtoul(keyValue, NULL, 0);                  DriverOptions = strtoul(keyValue, NULL, 0);
1219    
1220                  /* print the log level used */                  /* print the log level used */
1221                  debug_msg("%s:%d:%s DriverOptions: 0x%.4X", __FILE__, __LINE__,                  DEBUG_INFO2("DriverOptions: 0x%.4X", DriverOptions);
                         __FUNCTION__, 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 */
1245            InitReaderIndex();
1246    
1247          DebugInitialized = TRUE;          DebugInitialized = TRUE;
1248  } /* init_driver */  } /* init_driver */
1249    
1250    
1251    void extra_egt(ATR_t *atr, _ccid_descriptor *ccid_desc, DWORD Protocol)
1252    {
1253            /* This function use an EGT value for cards who comply with followings
1254             * criterias:
1255             * - TA1 > 11
1256             * - current EGT = 0x00 or 0xFF
1257             * - T=0 or (T=1 and CWI >= 2)
1258             *
1259             * Without this larger EGT some non ISO 7816-3 smart cards may not
1260             * communicate with the reader.
1261             *
1262             * This modification is harmless, the reader will just be less restrictive
1263             */
1264    
1265            unsigned int card_baudrate;
1266            unsigned int default_baudrate;
1267            double f, d;
1268            int i;
1269    
1270            /* if TA1 not present */
1271            if (! atr->ib[0][ATR_INTERFACE_BYTE_TA].present)
1272                    return;
1273    
1274            ATR_GetParameter(atr, ATR_PARAMETER_D, &d);
1275            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 */
1282            card_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock * d / f);
1283    
1284            default_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock
1285                    * ATR_DEFAULT_D / ATR_DEFAULT_F);
1286    
1287            /* TA1 > 11? */
1288            if (card_baudrate <= default_baudrate)
1289                    return;
1290    
1291            /* Current EGT = 0 or FF? */
1292            if (atr->ib[0][ATR_INTERFACE_BYTE_TC].present &&
1293                    ((0x00 == atr->ib[0][ATR_INTERFACE_BYTE_TC].value) ||
1294                    (0xFF == atr->ib[0][ATR_INTERFACE_BYTE_TC].value)))
1295            {
1296                    if (SCARD_PROTOCOL_T0 == Protocol)
1297                    {
1298                            /* Init TC1 */
1299                            atr->ib[0][ATR_INTERFACE_BYTE_TC].present = TRUE;
1300                            atr->ib[0][ATR_INTERFACE_BYTE_TC].value = 2;
1301                            DEBUG_INFO("Extra EGT patch applied");
1302                    }
1303    
1304                    if (SCARD_PROTOCOL_T1 == Protocol)
1305                    {
1306                            /* TBi (i>2) present? BWI/CWI */
1307                            for (i=2; i<ATR_MAX_PROTOCOLS; i++)
1308                            {
1309                                    /* CWI >= 2 ? */
1310                                    if (atr->ib[i][ATR_INTERFACE_BYTE_TB].present &&
1311                                            ((atr->ib[i][ATR_INTERFACE_BYTE_TB].value & 0x0F) >= 2))
1312                                    {
1313                                            /* Init TC1 */
1314                                            atr->ib[0][ATR_INTERFACE_BYTE_TC].present = TRUE;
1315                                            atr->ib[0][ATR_INTERFACE_BYTE_TC].value = 2;
1316                                            DEBUG_INFO("Extra EGT patch applied");
1317    
1318                                            /* only the first TBi (i>2) must be used */
1319                                            break;
1320                                    }
1321                            }
1322                    }
1323            }
1324    } /* extra_egt */
1325    
1326    
1327    static char find_baud_rate(unsigned int baudrate, unsigned int *list)
1328    {
1329            int i;
1330    
1331            DEBUG_COMM2("Card baud rate: %d", baudrate);
1332    
1333            /* Does the reader support the announced smart card data speed? */
1334            for (i=0;; i++)
1335            {
1336                    /* end of array marker */
1337                    if (0 == list[i])
1338                            break;
1339    
1340                    DEBUG_COMM2("Reader can do: %d", list[i]);
1341    
1342                    /* We must take into account that the card_baudrate integral value
1343                     * is an approximative result, computed from the d/f float result.
1344                     */
1345                    if ((baudrate < list[i] + 2) && (baudrate > list[i] - 2))
1346                            return TRUE;
1347            }
1348    
1349            return FALSE;
1350    } /* 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.1078  
changed lines
  Added in v.2168

  ViewVC Help
Powered by ViewVC 1.1.5