/[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 892 by rousseau, Mon May 24 12:58:43 2004 UTC revision 2130 by rousseau, Wed Aug 9 07:17:31 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 <arpa/inet.h>
26    #include "misc.h"
27  #include <pcsclite.h>  #include <pcsclite.h>
28  #include <ifdhandler.h>  #include <ifdhandler.h>
29    #include <reader.h>
30    
31  #include "ccid.h"  #include "ccid.h"
32  #include "defs.h"  #include "defs.h"
# Line 32  Line 35 
35  #include "debug.h"  #include "debug.h"
36  #include "utils.h"  #include "utils.h"
37  #include "commands.h"  #include "commands.h"
38  #include "protocol_t1/atr.h"  #include "towitoko/atr.h"
39  #include "protocol_t1/pps.h"  #include "towitoko/pps.h"
 #include "protocol_t1/protocol_t1.h"  
40  #include "parser.h"  #include "parser.h"
41    
42  #ifdef HAVE_PTHREAD  #ifdef HAVE_PTHREAD
# Line 42  Line 44 
44  #endif  #endif
45    
46  /* Array of structures to hold the ATR and other state value of each slot */  /* Array of structures to hold the ATR and other state value of each slot */
47  static CcidDesc CcidSlots[PCSCLITE_MAX_READERS];  static CcidDesc CcidSlots[CCID_DRIVER_MAX_READERS];
48    
49  /* global mutex */  /* global mutex */
50  #ifdef HAVE_PTHREAD  #ifdef HAVE_PTHREAD
# Line 51  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 RESPONSECODE CardUp(int lun);  static void extra_egt(ATR_t *atr, _ccid_descriptor *ccid_desc, DWORD Protocol);
62  static RESPONSECODE CardDown(int lun);  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, LPSTR 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 99  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 135  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 172  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 184  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          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          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 207  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 227  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 240  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 253  RESPONSECODE IFDHGetCapabilities(DWORD L Line 292  RESPONSECODE IFDHGetCapabilities(DWORD L
292                          if (*Length >= 1)                          if (*Length >= 1)
293                          {                          {
294                                  *Length = 1;                                  *Length = 1;
295                                  *Value = PCSCLITE_MAX_READERS;                                  *Value = CCID_DRIVER_MAX_READERS;
296                          }                          }
297                          break;                          break;
298    
# Line 270  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;
316    
317                    case TAG_IFD_SLOT_THREAD_SAFE:
318                            if (*Length >= 1)
319                            {
320                                    *Length = 1;
321                                    *Value = 0; /* Can NOT talk to multiple slots at the same time */
322                          }                          }
323                          break;                          break;
324    
# Line 282  RESPONSECODE IFDHGetCapabilities(DWORD L Line 330  RESPONSECODE IFDHGetCapabilities(DWORD L
330  } /* IFDHGetCapabilities */  } /* IFDHGetCapabilities */
331    
332    
333  RESPONSECODE IFDHSetCapabilities(DWORD Lun, DWORD Tag,  EXTERNAL RESPONSECODE IFDHSetCapabilities(DWORD Lun, DWORD Tag,
334          DWORD Length, PUCHAR Value)          /*@unused@*/ DWORD Length, /*@unused@*/ PUCHAR Value)
335  {  {
336          /*          /*
337           * This function should set the slot/card capabilities for a           * This function should set the slot/card capabilities for a
# Line 313  RESPONSECODE IFDHSetCapabilities(DWORD L Line 361  RESPONSECODE IFDHSetCapabilities(DWORD L
361  } /* IFDHSetCapabilities */  } /* IFDHSetCapabilities */
362    
363    
364  RESPONSECODE IFDHSetProtocolParameters(DWORD Lun, DWORD Protocol,  EXTERNAL RESPONSECODE IFDHSetProtocolParameters(DWORD Lun, DWORD Protocol,
365          UCHAR Flags, UCHAR PTS1, UCHAR PTS2, UCHAR PTS3)          UCHAR Flags, UCHAR PTS1, UCHAR PTS2, UCHAR PTS3)
366  {  {
367          /*          /*
368           * This function should set the PTS of a particular card/slot using           * This function should set the PTS of a particular card/slot using
369           * the three PTS parameters sent           * the three PTS parameters sent
370           *           *
371           * Protocol - 0 .... 14 T=0 .... T=14 Flags - Logical OR of possible           * Protocol - 0 .... 14 T=0 .... T=14
372           * values: IFD_NEGOTIATE_PTS1 IFD_NEGOTIATE_PTS2 IFD_NEGOTIATE_PTS3 to           * Flags - Logical OR of possible values:
373           * determine which PTS values to negotiate. PTS1,PTS2,PTS3 - PTS           *  IFD_NEGOTIATE_PTS1
374           * Values.           *  IFD_NEGOTIATE_PTS2
375             *  IFD_NEGOTIATE_PTS3
376             * to determine which PTS values to negotiate.
377             * PTS1,PTS2,PTS3 - PTS Values.
378           *           *
379           * returns:           * returns:
380           *           *  IFD_SUCCESS
381           * IFD_SUCCESS IFD_ERROR_PTS_FAILURE IFD_COMMUNICATION_ERROR           *  IFD_ERROR_PTS_FAILURE
382           * IFD_PROTOCOL_NOT_SUPPORTED           *  IFD_COMMUNICATION_ERROR
383             *  IFD_PROTOCOL_NOT_SUPPORTED
384           */           */
385    
386          DEBUG_INFO2("lun: %X", Lun);          BYTE pps[PPS_MAX_LENGTH];
387            ATR_t atr;
388            unsigned int len;
389            int convention;
390            int reader_index;
391    
392            /* Set ccid desc params */
393            CcidDesc *ccid_slot;
394            _ccid_descriptor *ccid_desc;
395    
396          /* if (CheckLun(Lun))          DEBUG_INFO3("lun: %X, protocol T=%d", Lun, Protocol-1);
                 return IFD_COMMUNICATION_ERROR; */  
397    
398          return IFD_NOT_SUPPORTED;          if (-1 == (reader_index = LunToReaderIndex(Lun)))
399                    return IFD_COMMUNICATION_ERROR;
400    
401            /* Set to zero buffer */
402            memset(pps, 0, sizeof(pps));
403            memset(&atr, 0, sizeof(atr));
404    
405            /* Get ccid params */
406            ccid_slot = get_ccid_slot(reader_index);
407            ccid_desc = get_ccid_descriptor(reader_index);
408    
409            /* Do not send CCID command SetParameters or PPS to the CCID
410             * The CCID will do this himself */
411            if (ccid_desc->dwFeatures & CCID_CLASS_AUTO_PPS_PROP)
412                    return IFD_SUCCESS;
413    
414            /* Get ATR of the card */
415            ATR_InitFromArray(&atr, ccid_slot->pcATRBuffer, ccid_slot->nATRLength);
416    
417            /* Apply Extra EGT patch for bogus cards */
418            extra_egt(&atr, ccid_desc, Protocol);
419    
420            if (SCARD_PROTOCOL_T0 == Protocol)
421                    pps[1] |= ATR_PROTOCOL_TYPE_T0;
422            else
423                    if (SCARD_PROTOCOL_T1 == Protocol)
424                            pps[1] |= ATR_PROTOCOL_TYPE_T1;
425                    else
426                            return IFD_PROTOCOL_NOT_SUPPORTED;
427    
428            /* TA2 present -> specific mode */
429            if (atr.ib[1][ATR_INTERFACE_BYTE_TA].present)
430            {
431                    if (pps[1] != (atr.ib[1][ATR_INTERFACE_BYTE_TA].value & 0x0F))
432                    {
433                            /* wrong protocol */
434                            DEBUG_COMM3("Specific mode in T=%d and T=%d requested",
435                                    atr.ib[1][ATR_INTERFACE_BYTE_TA].value & 0x0F, pps[1]);
436    
437                            return IFD_PROTOCOL_NOT_SUPPORTED;
438                    }
439            }
440    
441            /* TCi (i>2) indicates CRC instead of LRC */
442            if (SCARD_PROTOCOL_T1 == Protocol)
443            {
444                    t1_state_t *t1 = &(ccid_slot -> t1);
445                    int i;
446    
447                    /* TCi (i>2) present? */
448                    for (i=2; i<ATR_MAX_PROTOCOLS; i++)
449                            if (atr.ib[i][ATR_INTERFACE_BYTE_TC].present)
450                            {
451                                    if (0 == atr.ib[i][ATR_INTERFACE_BYTE_TC].value)
452                                    {
453                                            DEBUG_COMM("Use LRC");
454                                            t1_set_param(t1, IFD_PROTOCOL_T1_CHECKSUM_LRC, 0);
455                                    }
456                                    else
457                                            if (1 == atr.ib[i][ATR_INTERFACE_BYTE_TC].value)
458                                            {
459                                                    DEBUG_COMM("Use CRC");
460                                                    t1_set_param(t1, IFD_PROTOCOL_T1_CHECKSUM_CRC, 0);
461                                            }
462                                            else
463                                                    DEBUG_COMM2("Wrong value for TCi: %d",
464                                                            atr.ib[i][ATR_INTERFACE_BYTE_TC].value);
465    
466                                    /* only the first TCi (i>2) must be used */
467                                    break;
468                            }
469            }
470    
471            /* PTS1? */
472            if (Flags & IFD_NEGOTIATE_PTS1)
473            {
474                    /* just use the value passed in argument */
475                    pps[1] |= 0x10; /* PTS1 presence */
476                    pps[2] = PTS1;
477            }
478            else
479            {
480                    /* TA1 present */
481                    if (atr.ib[0][ATR_INTERFACE_BYTE_TA].present)
482                    {
483                            unsigned int card_baudrate;
484                            unsigned int default_baudrate;
485                            double f, d;
486    
487                            ATR_GetParameter(&atr, ATR_PARAMETER_D, &d);
488                            ATR_GetParameter(&atr, ATR_PARAMETER_F, &f);
489    
490                            /* may happen with non ISO cards */
491                            if ((0 == f) || (0 == d))
492                            {
493                                    /* values for TA1=11 */
494                                    f = 372;
495                                    d = 1;
496                            }
497    
498                            /* Baudrate = f x D/F */
499                            card_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock
500                                    * d / f);
501    
502                            default_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock
503                                    * ATR_DEFAULT_D / ATR_DEFAULT_F);
504    
505                            /* if the card does not try to lower the default speed */
506                            if ((card_baudrate > default_baudrate)
507                                    /* and the reader is fast enough */
508                                    && (card_baudrate <= ccid_desc->dwMaxDataRate))
509                            {
510                                    /* the reader has no baud rates table */
511                                    if ((NULL == ccid_desc->arrayOfSupportedDataRates)
512                                            /* or explicitely support it */
513                                            || find_baud_rate(card_baudrate,
514                                                    ccid_desc->arrayOfSupportedDataRates))
515                                    {
516                                            pps[1] |= 0x10; /* PTS1 presence */
517                                            pps[2] = atr.ib[0][ATR_INTERFACE_BYTE_TA].value;
518    
519                                            DEBUG_COMM2("Set speed to %d bauds", card_baudrate);
520                                    }
521                                    else
522                                    {
523                                            DEBUG_COMM2("Reader does not support %d bauds",
524                                                    card_baudrate);
525    
526                                            /* TA2 present -> specific mode: the card is supporting
527                                             * only the baud rate specified in TA1 but reader does not
528                                             * support this value. Reject the card. */
529                                            if (atr.ib[1][ATR_INTERFACE_BYTE_TA].present)
530                                                    return IFD_COMMUNICATION_ERROR;
531                                    }
532                            }
533                            else
534                            {
535                                    /* the card is too fast for the reader */
536                                    if ((card_baudrate > ccid_desc->dwMaxDataRate +2)
537                                            /* but TA1 <= 97 */
538                                            && (atr.ib[0][ATR_INTERFACE_BYTE_TA].value <= 0x97)
539                                            /* and the reader has a baud rate table */
540                                            && ccid_desc->arrayOfSupportedDataRates)
541                                    {
542                                            unsigned char old_TA1;
543    
544                                            old_TA1 = atr.ib[0][ATR_INTERFACE_BYTE_TA].value;
545                                            while (atr.ib[0][ATR_INTERFACE_BYTE_TA].value > 0x94)
546                                            {
547                                                    /* use a lower TA1 */
548                                                    atr.ib[0][ATR_INTERFACE_BYTE_TA].value--;
549    
550                                                    ATR_GetParameter(&atr, ATR_PARAMETER_D, &d);
551                                                    ATR_GetParameter(&atr, ATR_PARAMETER_F, &f);
552    
553                                                    /* Baudrate = f x D/F */
554                                                    card_baudrate = (unsigned int) (1000 *
555                                                            ccid_desc->dwDefaultClock * d / f);
556    
557                                                    if (find_baud_rate(card_baudrate,
558                                                            ccid_desc->arrayOfSupportedDataRates))
559                                                    {
560                                                            pps[1] |= 0x10; /* PTS1 presence */
561                                                            pps[2] = atr.ib[0][ATR_INTERFACE_BYTE_TA].value;
562    
563                                                            DEBUG_COMM2("Set adapted speed to %d bauds",
564                                                                    card_baudrate);
565    
566                                                            break;
567                                                    }
568                                            }
569    
570                                            /* restore original TA1 value */
571                                            atr.ib[0][ATR_INTERFACE_BYTE_TA].value = old_TA1;
572                                    }
573                            }
574                    }
575            }
576    
577            /* PTS2? */
578            if (Flags & IFD_NEGOTIATE_PTS2)
579            {
580                    pps[1] |= 0x20; /* PTS2 presence */
581                    pps[3] = PTS2;
582            }
583    
584            /* PTS3? */
585            if (Flags & IFD_NEGOTIATE_PTS3)
586            {
587                    pps[1] |= 0x40; /* PTS3 presence */
588                    pps[4] = PTS3;
589            }
590    
591            /* Generate PPS */
592            pps[0] = 0xFF;
593    
594            /* Automatic PPS made by the ICC? */
595            if ((! (ccid_desc->dwFeatures & CCID_CLASS_AUTO_PPS_CUR))
596                    /* TA2 absent: negociable mode */
597                    && (! atr.ib[1][ATR_INTERFACE_BYTE_TA].present))
598            {
599                    int default_protocol;
600    
601                    if (ATR_MALFORMED == ATR_GetDefaultProtocol(&atr, &default_protocol))
602                            return IFD_PROTOCOL_NOT_SUPPORTED;
603    
604                    /* if the requested protocol is not the default one
605                     * or a TA1/PPS1 is present */
606                    if (((pps[1] & 0x0F) != default_protocol) || (PPS_HAS_PPS1(pps)))
607                            if (PPS_Exchange(reader_index, pps, &len, &pps[2]) != PPS_OK)
608                            {
609                                    DEBUG_INFO("PPS_Exchange Failed");
610    
611                                    return IFD_ERROR_PTS_FAILURE;
612                            }
613            }
614    
615            /* Now we must set the reader parameters */
616            ATR_GetConvention(&atr, &convention);
617    
618            /* specific mode and implicit parameters? (b5 of TA2) */
619            if (atr.ib[1][ATR_INTERFACE_BYTE_TA].present
620                    && (atr.ib[1][ATR_INTERFACE_BYTE_TA].value & 0x10))
621                    return IFD_COMMUNICATION_ERROR;
622    
623            /* T=1 */
624            if (SCARD_PROTOCOL_T1 == Protocol)
625            {
626                    BYTE param[] = {
627                            0x11,   /* Fi/Di                */
628                            0x10,   /* TCCKS                */
629                            0x00,   /* GuardTime    */
630                            0x4D,   /* BWI/CWI              */
631                            0x00,   /* ClockStop    */
632                            0x20,   /* IFSC                 */
633                            0x00    /* NADValue             */
634                    };
635                    int i;
636                    t1_state_t *t1 = &(ccid_slot -> t1);
637                    RESPONSECODE ret;
638                    double f, d;
639    
640                    /* TA1 is not default */
641                    if (PPS_HAS_PPS1(pps))
642                            param[0] = pps[2];
643    
644                    /* CRC checksum? */
645                    if (2 == t1->rc_bytes)
646                            param[1] |= 0x01;
647    
648                    /* the CCID should ignore this bit */
649                    if (ATR_CONVENTION_INVERSE == convention)
650                            param[1] |= 0x02;
651    
652                    /* get TC1 Extra guard time */
653                    if (atr.ib[0][ATR_INTERFACE_BYTE_TC].present)
654                            param[2] = atr.ib[0][ATR_INTERFACE_BYTE_TC].value;
655    
656                    /* TBi (i>2) present? BWI/CWI */
657                    for (i=2; i<ATR_MAX_PROTOCOLS; i++)
658                            if (atr.ib[i][ATR_INTERFACE_BYTE_TB].present)
659                            {
660                                    DEBUG_COMM3("BWI/CWI (TB%d) present: 0x%02X", i+1,
661                                            atr.ib[i][ATR_INTERFACE_BYTE_TB].value);
662                                    param[3] = atr.ib[i][ATR_INTERFACE_BYTE_TB].value;
663    
664                                    /* only the first TBi (i>2) must be used */
665                                    break;
666                            }
667    
668                    /* compute communication timeout */
669                    ATR_GetParameter(&atr, ATR_PARAMETER_F, &f);
670                    ATR_GetParameter(&atr, ATR_PARAMETER_D, &d);
671                    ccid_desc->readTimeout = T1_card_timeout(f, d, param[2],
672                            (param[3] & 0xF0) >> 4 /* BWI */, param[3] & 0x0F /* CWI */,
673                            ccid_desc->dwDefaultClock);
674    
675                    DEBUG_COMM2("Timeout: %d seconds", ccid_desc->readTimeout);
676    
677                    ret = SetParameters(reader_index, 1, sizeof(param), param);
678                    if (IFD_SUCCESS != ret)
679                            return ret;
680            }
681            else
682            /* T=0 */
683            {
684                    BYTE param[] = {
685                            0x11,   /* Fi/Di                        */
686                            0x00,   /* TCCKS                        */
687                            0x00,   /* GuardTime            */
688                            0x0A,   /* WaitingInteger       */
689                            0x00    /* ClockStop            */
690                    };
691                    RESPONSECODE ret;
692                    double f, d;
693    
694                    /* TA1 is not default */
695                    if (PPS_HAS_PPS1(pps))
696                            param[0] = pps[2];
697    
698                    if (ATR_CONVENTION_INVERSE == convention)
699                            param[1] |= 0x02;
700    
701                    /* get TC1 Extra guard time */
702                    if (atr.ib[0][ATR_INTERFACE_BYTE_TC].present)
703                            param[2] = atr.ib[0][ATR_INTERFACE_BYTE_TC].value;
704    
705                    /* TC2 WWT */
706                    if (atr.ib[1][ATR_INTERFACE_BYTE_TC].present)
707                            param[3] = atr.ib[1][ATR_INTERFACE_BYTE_TC].value;
708    
709                    /* compute communication timeout */
710                    ATR_GetParameter(&atr, ATR_PARAMETER_F, &f);
711                    ATR_GetParameter(&atr, ATR_PARAMETER_D, &d);
712    
713                    ccid_desc->readTimeout = T0_card_timeout(f, d, param[2] /* TC1 */,
714                            param[3] /* TC2 */, ccid_desc->dwDefaultClock);
715    
716                    DEBUG_COMM2("Communication timeout: %d seconds",
717                            ccid_desc->readTimeout);
718    
719                    ret = SetParameters(reader_index, 0, sizeof(param), param);
720                    if (IFD_SUCCESS != ret)
721                            return ret;
722            }
723    
724            /* set IFSC & IFSD in T=1 */
725            if (SCARD_PROTOCOL_T1 == Protocol)
726            {
727                    t1_state_t *t1 = &(ccid_slot -> t1);
728                    int i;
729    
730                    /* TAi (i>2) present? */
731                    for (i=2; i<ATR_MAX_PROTOCOLS; i++)
732                            if (atr.ib[i][ATR_INTERFACE_BYTE_TA].present)
733                            {
734                                    DEBUG_COMM3("IFSC (TA%d) present: %d", i+1,
735                                            atr.ib[i][ATR_INTERFACE_BYTE_TA].value);
736                                    t1_set_param(t1, IFD_PROTOCOL_T1_IFSC,
737                                            atr.ib[i][ATR_INTERFACE_BYTE_TA].value);
738    
739                                    /* only the first TAi (i>2) must be used */
740                                    break;
741                            }
742    
743                    /* IFSD not negociated by the reader? */
744                    if (! (ccid_desc->dwFeatures & CCID_CLASS_AUTO_IFSD))
745                    {
746                            DEBUG_COMM2("Negociate IFSD at %d", ccid_desc -> dwMaxIFSD);
747                            if (t1_negociate_ifsd(t1, 0, ccid_desc -> dwMaxIFSD) < 0)
748                                    return IFD_COMMUNICATION_ERROR;
749                    }
750                    t1_set_param(t1, IFD_PROTOCOL_T1_IFSD, ccid_desc -> dwMaxIFSD);
751    
752                    DEBUG_COMM3("T=1: IFSC=%d, IFSD=%d", t1->ifsc, t1->ifsd);
753            }
754    
755            /* store used protocol for use by the secure commands (verify/change PIN) */
756            ccid_desc->cardProtocol = Protocol;
757    
758            return IFD_SUCCESS;
759  } /* IFDHSetProtocolParameters */  } /* IFDHSetProtocolParameters */
760    
761    
762  RESPONSECODE IFDHPowerICC(DWORD Lun, DWORD Action,  EXTERNAL RESPONSECODE IFDHPowerICC(DWORD Lun, DWORD Action,
763          PUCHAR Atr, PDWORD AtrLength)          PUCHAR Atr, PDWORD AtrLength)
764  {  {
765          /*          /*
# Line 382  RESPONSECODE IFDHPowerICC(DWORD Lun, DWO Line 801  RESPONSECODE IFDHPowerICC(DWORD Lun, DWO
801          unsigned int nlength;          unsigned int nlength;
802          RESPONSECODE return_value = IFD_SUCCESS;          RESPONSECODE return_value = IFD_SUCCESS;
803          unsigned char pcbuffer[RESP_BUF_SIZE];          unsigned char pcbuffer[RESP_BUF_SIZE];
804            int reader_index;
805    
806          DEBUG_INFO2("lun: %X", Lun);          DEBUG_INFO2("lun: %X", Lun);
807    
808          /* By default, assume it won't work :) */          /* By default, assume it won't work :) */
809          *AtrLength = 0;          *AtrLength = 0;
810    
811          if (CheckLun(Lun))          if (-1 == (reader_index = LunToReaderIndex(Lun)))
812                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
813    
814          switch (Action)          switch (Action)
815          {          {
816                  case IFD_POWER_DOWN:                  case IFD_POWER_DOWN:
817                          /* Clear ATR buffer */                          /* Clear ATR buffer */
818                          CcidSlots[LunToReaderIndex(Lun)].nATRLength = 0;                          CcidSlots[reader_index].nATRLength = 0;
819                          *CcidSlots[LunToReaderIndex(Lun)].pcATRBuffer = '\0';                          *CcidSlots[reader_index].pcATRBuffer = '\0';
820    
821                          /* Memorise the request */                          /* Memorise the request */
822                          CcidSlots[LunToReaderIndex(Lun)].bPowerFlags |=                          CcidSlots[reader_index].bPowerFlags |= MASK_POWERFLAGS_PDWN;
823                                  MASK_POWERFLAGS_PDWN;  
824                          /* send the command */                          /* send the command */
825                          if (IFD_SUCCESS != CmdPowerOff(Lun))                          if (IFD_SUCCESS != CmdPowerOff(reader_index))
826                          {                          {
827                                  DEBUG_CRITICAL("PowerDown failed");                                  DEBUG_CRITICAL("PowerDown failed");
828                                  return_value = IFD_ERROR_POWER_ACTION;                                  return_value = IFD_ERROR_POWER_ACTION;
829                                  goto end;                                  goto end;
830                          }                          }
831    
832                          return_value = CardDown(Lun);                          /* clear T=1 context */
833                            t1_release(&(get_ccid_slot(reader_index) -> t1));
834                          break;                          break;
835    
836                  case IFD_POWER_UP:                  case IFD_POWER_UP:
837                  case IFD_RESET:                  case IFD_RESET:
838                          nlength = sizeof(pcbuffer);                          nlength = sizeof(pcbuffer);
839                          if (CmdPowerOn(Lun, &nlength, pcbuffer) != IFD_SUCCESS)                          if (CmdPowerOn(reader_index, &nlength, pcbuffer, PowerOnVoltage)
840                                    != IFD_SUCCESS)
841                          {                          {
842                                  DEBUG_CRITICAL("PowerUp failed");                                  DEBUG_CRITICAL("PowerUp failed");
843                                  return_value = IFD_ERROR_POWER_ACTION;                                  return_value = IFD_ERROR_POWER_ACTION;
# Line 423  RESPONSECODE IFDHPowerICC(DWORD Lun, DWO Line 845  RESPONSECODE IFDHPowerICC(DWORD Lun, DWO
845                          }                          }
846    
847                          /* Power up successful, set state variable to memorise it */                          /* Power up successful, set state variable to memorise it */
848                          CcidSlots[LunToReaderIndex(Lun)].bPowerFlags |=                          CcidSlots[reader_index].bPowerFlags |= MASK_POWERFLAGS_PUP;
849                                  MASK_POWERFLAGS_PUP;                          CcidSlots[reader_index].bPowerFlags &= ~MASK_POWERFLAGS_PDWN;
                         CcidSlots[LunToReaderIndex(Lun)].bPowerFlags &=  
                                 ~MASK_POWERFLAGS_PDWN;  
850    
851                          /* Reset is returned, even if TCK is wrong */                          /* Reset is returned, even if TCK is wrong */
852                          CcidSlots[LunToReaderIndex(Lun)].nATRLength = *AtrLength =                          CcidSlots[reader_index].nATRLength = *AtrLength =
853                                  (nlength < MAX_ATR_SIZE) ? nlength : MAX_ATR_SIZE;                                  (nlength < MAX_ATR_SIZE) ? nlength : MAX_ATR_SIZE;
854                          memcpy(Atr, pcbuffer, *AtrLength);                          memcpy(Atr, pcbuffer, *AtrLength);
855                          memcpy(CcidSlots[LunToReaderIndex(Lun)].pcATRBuffer,                          memcpy(CcidSlots[reader_index].pcATRBuffer, pcbuffer, *AtrLength);
                                 pcbuffer, *AtrLength);  
856    
857                          return_value = CardUp(Lun);                          /* initialise T=1 context */
858                            t1_init(&(get_ccid_slot(reader_index) -> t1), reader_index);
859                          break;                          break;
860    
861                  default:                  default:
# Line 448  end: Line 868  end:
868  } /* IFDHPowerICC */  } /* IFDHPowerICC */
869    
870    
871  RESPONSECODE IFDHTransmitToICC(DWORD Lun, SCARD_IO_HEADER SendPci,  EXTERNAL RESPONSECODE IFDHTransmitToICC(DWORD Lun, SCARD_IO_HEADER SendPci,
872          PUCHAR TxBuffer, DWORD TxLength,          PUCHAR TxBuffer, DWORD TxLength,
873          PUCHAR RxBuffer, PDWORD RxLength, PSCARD_IO_HEADER RecvPci)          PUCHAR RxBuffer, PDWORD RxLength, /*@unused@*/ PSCARD_IO_HEADER RecvPci)
874  {  {
875          /*          /*
876           * This function performs an APDU exchange with the card/slot           * This function performs an APDU exchange with the card/slot
# Line 488  RESPONSECODE IFDHTransmitToICC(DWORD Lun Line 908  RESPONSECODE IFDHTransmitToICC(DWORD Lun
908    
909          RESPONSECODE return_value;          RESPONSECODE return_value;
910          unsigned int rx_length;          unsigned int rx_length;
911            int reader_index;
912    
913          DEBUG_INFO2("lun: %X", Lun);          DEBUG_INFO2("lun: %X", Lun);
914    
915          if (CheckLun(Lun))          if (-1 == (reader_index = LunToReaderIndex(Lun)))
916                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
917    
918          rx_length = *RxLength;          rx_length = *RxLength;
919          return_value = CmdXfrBlock(Lun, TxLength, TxBuffer, &rx_length, RxBuffer,          return_value = CmdXfrBlock(reader_index, TxLength, TxBuffer, &rx_length,
920                  SendPci.Protocol);                  RxBuffer, SendPci.Protocol);
921          *RxLength = rx_length;          *RxLength = rx_length;
922    
923          return return_value;          return return_value;
924  } /* IFDHTransmitToICC */  } /* IFDHTransmitToICC */
925    
926    
927  RESPONSECODE IFDHControl(DWORD Lun, DWORD dwControlCode, LPCVOID TxBuffer,  EXTERNAL RESPONSECODE IFDHControl(DWORD Lun, DWORD dwControlCode,
928          DWORD TxLength, LPVOID RxBuffer, DWORD RxLength, PDWORD pdwBytesReturned)          PUCHAR TxBuffer, DWORD TxLength, PUCHAR RxBuffer, DWORD RxLength,
929            PDWORD pdwBytesReturned)
930  {  {
931          /*          /*
932           * This function performs a data exchange with the reader (not the           * This function performs a data exchange with the reader (not the
# Line 521  RESPONSECODE IFDHControl(DWORD Lun, DWOR Line 943  RESPONSECODE IFDHControl(DWORD Lun, DWOR
943           * Notes: RxLength should be zero on error.           * Notes: RxLength should be zero on error.
944           */           */
945          RESPONSECODE return_value = IFD_COMMUNICATION_ERROR;          RESPONSECODE return_value = IFD_COMMUNICATION_ERROR;
946            int reader_index;
947    
948          DEBUG_INFO3("lun: %X, ControlCode: 0x%X", Lun, dwControlCode);          DEBUG_INFO3("lun: %X, ControlCode: 0x%X", Lun, dwControlCode);
949    
950          if (CheckLun(Lun) || (NULL == pdwBytesReturned) || (NULL == RxBuffer))          reader_index = LunToReaderIndex(Lun);
951            if ((-1 == reader_index) || (NULL == pdwBytesReturned))
952                  return return_value;                  return return_value;
953    
954          /* Set the return length to 0 to avoid problems */          /* Set the return length to 0 to avoid problems */
# Line 542  RESPONSECODE IFDHControl(DWORD Lun, DWOR Line 966  RESPONSECODE IFDHControl(DWORD Lun, DWOR
966                          unsigned int iBytesReturned;                          unsigned int iBytesReturned;
967    
968                          iBytesReturned = RxLength;                          iBytesReturned = RxLength;
969                          return_value = CmdEscape(Lun, TxBuffer, TxLength, RxBuffer,                          return_value = CmdEscape(reader_index, TxBuffer, TxLength, RxBuffer,
970                                  &iBytesReturned);                                  &iBytesReturned);
971                          *pdwBytesReturned = iBytesReturned;                          *pdwBytesReturned = iBytesReturned;
972                  }                  }
973          }          }
974    
975          if (IOCTL_SMARTCARD_VENDOR_VERIFY_PIN == dwControlCode)          /* Implement the PC/SC v2.1.2 Part 10 IOCTL mechanism */
976    
977            /* Query for features */
978            if (CM_IOCTL_GET_FEATURE_REQUEST == dwControlCode)
979            {
980                    unsigned int iBytesReturned = 0;
981                    PCSC_TLV_STRUCTURE *pcsc_tlv = (PCSC_TLV_STRUCTURE *)RxBuffer;
982    
983                    /* we need room for two records */
984                    if (RxLength < 2 * sizeof(PCSC_TLV_STRUCTURE))
985                            return IFD_COMMUNICATION_ERROR;
986    
987                    /* We can only support direct verify and/or modify currently */
988                    if (get_ccid_descriptor(reader_index) -> bPINSupport
989                            & CCID_CLASS_PIN_VERIFY)
990                    {
991                            pcsc_tlv -> tag = FEATURE_VERIFY_PIN_DIRECT;
992                            pcsc_tlv -> length = 0x04; /* always 0x04 */
993                            pcsc_tlv -> value = htonl(IOCTL_FEATURE_VERIFY_PIN_DIRECT);
994    
995                            pcsc_tlv++;
996                            iBytesReturned += sizeof(PCSC_TLV_STRUCTURE);
997                    }
998    
999                    if (get_ccid_descriptor(reader_index) -> bPINSupport
1000                            & CCID_CLASS_PIN_MODIFY)
1001                    {
1002                            pcsc_tlv -> tag = FEATURE_MODIFY_PIN_DIRECT;
1003                            pcsc_tlv -> length = 0x04; /* always 0x04 */
1004                            pcsc_tlv -> value = htonl(IOCTL_FEATURE_MODIFY_PIN_DIRECT);
1005    
1006                            pcsc_tlv++;
1007                            iBytesReturned += sizeof(PCSC_TLV_STRUCTURE);
1008                    }
1009                    *pdwBytesReturned = iBytesReturned;
1010                    return_value = IFD_SUCCESS;
1011            }
1012    
1013            /* Verify a PIN, plain CCID */
1014            if (IOCTL_FEATURE_VERIFY_PIN_DIRECT == dwControlCode)
1015            {
1016                    unsigned int iBytesReturned;
1017    
1018                    iBytesReturned = RxLength;
1019                    return_value = SecurePINVerify(reader_index, TxBuffer, TxLength,
1020                            RxBuffer, &iBytesReturned);
1021                    *pdwBytesReturned = iBytesReturned;
1022            }
1023    
1024            /* Modify a PIN, plain CCID */
1025            if (IOCTL_FEATURE_MODIFY_PIN_DIRECT == dwControlCode)
1026          {          {
1027                  unsigned int iBytesReturned;                  unsigned int iBytesReturned;
1028    
1029                  iBytesReturned = RxLength;                  iBytesReturned = RxLength;
1030                  return_value = SecurePIN(Lun, TxBuffer, TxLength, RxBuffer,                  return_value = SecurePINModify(reader_index, TxBuffer, TxLength,
1031                          &iBytesReturned);                          RxBuffer, &iBytesReturned);
1032                  *pdwBytesReturned = iBytesReturned;                  *pdwBytesReturned = iBytesReturned;
1033          }          }
1034    
# Line 562  RESPONSECODE IFDHControl(DWORD Lun, DWOR Line 1036  RESPONSECODE IFDHControl(DWORD Lun, DWOR
1036  } /* IFDHControl */  } /* IFDHControl */
1037    
1038    
1039  RESPONSECODE IFDHICCPresence(DWORD Lun)  EXTERNAL RESPONSECODE IFDHICCPresence(DWORD Lun)
1040  {  {
1041          /*          /*
1042           * This function returns the status of the card inserted in the           * This function returns the status of the card inserted in the
# Line 574  RESPONSECODE IFDHICCPresence(DWORD Lun) Line 1048  RESPONSECODE IFDHICCPresence(DWORD Lun)
1048    
1049          unsigned char pcbuffer[SIZE_GET_SLOT_STATUS];          unsigned char pcbuffer[SIZE_GET_SLOT_STATUS];
1050          RESPONSECODE return_value = IFD_COMMUNICATION_ERROR;          RESPONSECODE return_value = IFD_COMMUNICATION_ERROR;
1051            int oldLogLevel;
1052            int reader_index;
1053            _ccid_descriptor *ccid_descriptor;
1054            unsigned int oldReadTimeout;
1055    
1056          DEBUG_PERIODIC2("lun: %X", Lun);          DEBUG_PERIODIC2("lun: %X", Lun);
1057    
1058          if (CheckLun(Lun))          if (-1 == (reader_index = LunToReaderIndex(Lun)))
1059                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
1060    
1061          if (CmdGetSlotStatus(Lun, pcbuffer) != IFD_SUCCESS)          ccid_descriptor = get_ccid_descriptor(reader_index);
1062    
1063            /* save the current read timeout computed from card capabilities */
1064            oldReadTimeout = ccid_descriptor->readTimeout;
1065    
1066            /* use default timeout since the reader may not be present anymore */
1067            ccid_descriptor->readTimeout = DEFAULT_COM_READ_TIMEOUT;
1068    
1069            /* if DEBUG_LEVEL_PERIODIC is not set we remove DEBUG_LEVEL_COMM */
1070            oldLogLevel = LogLevel;
1071            if (! (LogLevel & DEBUG_LEVEL_PERIODIC))
1072                    LogLevel &= ~DEBUG_LEVEL_COMM;
1073    
1074            return_value = CmdGetSlotStatus(reader_index, pcbuffer);
1075    
1076            /* set back the old timeout */
1077            ccid_descriptor->readTimeout = oldReadTimeout;
1078    
1079            /* set back the old LogLevel */
1080            LogLevel = oldLogLevel;
1081    
1082            if (return_value != IFD_SUCCESS)
1083                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
1084    
1085          switch (pcbuffer[7])    /* bStatus */          return_value = IFD_COMMUNICATION_ERROR;
1086            switch (pcbuffer[7] & CCID_ICC_STATUS_MASK)     /* bStatus */
1087          {          {
1088                  case 0x00:                  case CCID_ICC_PRESENT_ACTIVE:
1089                  case 0x01:                  case CCID_ICC_PRESENT_INACTIVE:
1090                          return_value = IFD_ICC_PRESENT;                          return_value = IFD_ICC_PRESENT;
1091                            /* use default slot */
1092                          break;                          break;
1093    
1094                  case 0x02:                  case CCID_ICC_ABSENT:
1095                          /* Reset ATR buffer */                          /* Reset ATR buffer */
1096                          CcidSlots[LunToReaderIndex(Lun)].nATRLength = 0;                          CcidSlots[reader_index].nATRLength = 0;
1097                          *CcidSlots[LunToReaderIndex(Lun)].pcATRBuffer = '\0';                          *CcidSlots[reader_index].pcATRBuffer = '\0';
1098    
1099                          /* Reset PowerFlags */                          /* Reset PowerFlags */
1100                          CcidSlots[LunToReaderIndex(Lun)].bPowerFlags = POWERFLAGS_RAZ;                          CcidSlots[reader_index].bPowerFlags = POWERFLAGS_RAZ;
1101    
1102                          return_value = IFD_ICC_NOT_PRESENT;                          return_value = IFD_ICC_NOT_PRESENT;
1103                          break;                          break;
1104          }          }
1105    
1106            /* SCR331-DI contactless reader */
1107            if (((SCR331DI == ccid_descriptor->readerID)
1108                    || (SDI010 == ccid_descriptor->readerID)
1109                    || (SCR331DINTTCOM == ccid_descriptor->readerID))
1110                    && (ccid_descriptor->bCurrentSlotIndex > 0))
1111            {
1112                    unsigned char cmd[] = { 0x11 };
1113                    /*  command: 11 ??
1114                     * response: 00 11 01 ?? no card
1115                     *           01 04 00 ?? card present */
1116    
1117                    unsigned char res[10];
1118                    unsigned int length_res = sizeof(res);
1119                    RESPONSECODE ret;
1120    
1121                    /* if DEBUG_LEVEL_PERIODIC is not set we remove DEBUG_LEVEL_COMM */
1122                    oldLogLevel = LogLevel;
1123                    if (! (LogLevel & DEBUG_LEVEL_PERIODIC))
1124                            LogLevel &= ~DEBUG_LEVEL_COMM;
1125    
1126                    ret = CmdEscape(reader_index, cmd, sizeof(cmd), res, &length_res);
1127    
1128                    /* set back the old LogLevel */
1129                    LogLevel = oldLogLevel;
1130    
1131                    if (ret != IFD_SUCCESS)
1132                    {
1133                            DEBUG_INFO("CmdEscape failed");
1134                            /* simulate a card absent */
1135                            res[0] = 0;
1136                    }
1137    
1138                    if (0x01 == res[0])
1139                            return_value = IFD_ICC_PRESENT;
1140                    else
1141                    {
1142                            /* Reset ATR buffer */
1143                            CcidSlots[reader_index].nATRLength = 0;
1144                            *CcidSlots[reader_index].pcATRBuffer = '\0';
1145    
1146                            /* Reset PowerFlags */
1147                            CcidSlots[reader_index].bPowerFlags = POWERFLAGS_RAZ;
1148    
1149                            return_value = IFD_ICC_NOT_PRESENT;
1150                    }
1151            }
1152    
1153            DEBUG_PERIODIC2("Card %s",
1154                    IFD_ICC_PRESENT == return_value ? "present" : "absent");
1155    
1156          return return_value;          return return_value;
1157  } /* IFDHICCPresence */  } /* IFDHICCPresence */
1158    
1159    
1160  CcidDesc *get_ccid_slot(int lun)  CcidDesc *get_ccid_slot(unsigned int reader_index)
1161  {  {
1162          return &CcidSlots[LunToReaderIndex(lun)];          return &CcidSlots[reader_index];
1163  } /* get_ccid_slot */  } /* get_ccid_slot */
1164    
1165    
1166  RESPONSECODE CardUp(int lun)  void init_driver(void)
1167  {  {
1168          ATR atr;          char keyValue[TOKEN_MAX_VALUE_SIZE];
1169          BYTE protocol = ATR_PROTOCOL_TYPE_T0;          char infofile[FILENAME_MAX];
         unsigned int np;  
         CcidDesc *ccid_slot = get_ccid_slot(lun);  
         _ccid_descriptor *ccid_desc = get_ccid_descriptor(lun);  
   
         /* Get ATR of the card */  
         ATR_InitFromArray(&atr, ccid_slot -> pcATRBuffer, ccid_slot -> nATRLength);  
1170    
1171          ATR_GetNumberOfProtocols(&atr, &np);          /* Info.plist full patch filename */
1172            snprintf(infofile, sizeof(infofile), "%s/%s/Contents/Info.plist",
1173                    PCSCLITE_HP_DROPDIR, BUNDLE);
1174    
1175          /* PPS not negociated by reader, and TA1 present */          /* Log level */
1176          if (atr.ib[0][ATR_INTERFACE_BYTE_TA].present &&          if (0 == LTPBundleFindValueWithKey(infofile, "ifdLogLevel", keyValue, 0))
                 ! (ccid_desc->dwFeatures & CCID_CLASS_AUTO_PPS_CUR))  
1177          {          {
1178                  unsigned int baudrate;                  /* convert from hex or dec or octal */
1179                  double f, d;                  LogLevel = strtoul(keyValue, NULL, 0);
   
                 ATR_GetParameter(&atr, ATR_PARAMETER_D, &d);  
                 ATR_GetParameter(&atr, ATR_PARAMETER_F, &f);  
   
                 /* Baudrate = f x D/F */  
                 baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock * d / f);  
1180    
1181                  /* if the reader is fast enough */                  /* print the log level used */
1182                  if (baudrate < ccid_desc->dwMaxDataRate)                  DEBUG_INFO2("LogLevel: 0x%.4X", LogLevel);
1183                  {          }
                         unsigned int len = 3;  
                         BYTE pps[] = {  
                                 0xFF,   /* PTSS */  
                                 0x10,   /* PTS0: PTS1 present */  
                                 0,              /* PTS1 */  
                                 0};             /* PCK: will be calculated */  
   
                         /* TD1: protocol */  
                         if (atr.ib[0][ATR_INTERFACE_BYTE_TD].present)  
                                 pps[1] |= (atr.ib[0][ATR_INTERFACE_BYTE_TD].value & 0x0F);  
1184    
1185                          /* PTS1 = TA1 */          /* Driver options */
1186                          pps[2] = atr.ib[0][ATR_INTERFACE_BYTE_TA].value;          if (0 == LTPBundleFindValueWithKey(infofile, "ifdDriverOptions", keyValue, 0))
1187            {
1188                    /* convert from hex or dec or octal */
1189                    DriverOptions = strtoul(keyValue, NULL, 0);
1190    
1191                          PPS_Exchange(lun, pps, &len);                  /* print the log level used */
1192                  }                  DEBUG_INFO2("DriverOptions: 0x%.4X", DriverOptions);
                 else  
                 {  
                         DEBUG_INFO3("The reader is too slow (%d bauds) for the card (%d bauds)", ccid_desc->dwMaxDataRate, baudrate);  
                 }  
1193          }          }
1194    
1195          /*          /* get the voltage parameter */
1196           * Get protocol offered by interface bytes T*2 if available,          switch ((DriverOptions >> 4) & 0x03)
          * (that is, if TD1 is available), otherwise use default T=0  
          */  
         if (np>1)  
                 ATR_GetProtocolType(&atr, 2, &protocol);  
   
         /* SetParameters */  
1197          {          {
1198                  int convention;                  case 0:
1199                            PowerOnVoltage = VOLTAGE_5V;
1200                            break;
1201    
1202                  ATR_GetConvention(&atr, &convention);                  case 1:
1203                            PowerOnVoltage = VOLTAGE_3V;
1204                            break;
1205    
1206                  /* T=1 */                  case 2:
1207                  if (protocol == ATR_PROTOCOL_TYPE_T1)                          PowerOnVoltage = VOLTAGE_1_8V;
1208                  {                          break;
                         BYTE param[] = {0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00};  
                         Protocol_T1 *t1 = &(ccid_slot -> t1);  
1209    
1210                          /* get TA1 Fi/Di */                  case 3:
1211                          if (atr.ib[0][ATR_INTERFACE_BYTE_TA].present)                          PowerOnVoltage = VOLTAGE_AUTO;
1212                                  param[0] = atr.ib[0][ATR_INTERFACE_BYTE_TA].value;                          break;
1213            }
1214    
1215                          if (convention == ATR_CONVENTION_INVERSE)          /* initialise the Lun to reader_index mapping */
1216                                  param[1] &= 0x02;          InitReaderIndex();
1217    
1218                          /* get TC1 Extra guard time */          DebugInitialized = TRUE;
1219                          if (atr.ib[0][ATR_INTERFACE_BYTE_TC].present)  } /* init_driver */
                                 param[2] = atr.ib[0][ATR_INTERFACE_BYTE_TC].value;  
1220    
                         /* get TB3 BWI/BCI */  
                         if (atr.ib[2][ATR_INTERFACE_BYTE_TB].present)  
                                 param[3] = atr.ib[2][ATR_INTERFACE_BYTE_TB].value;  
1221    
1222                          /* set T=1 context */  void extra_egt(ATR_t *atr, _ccid_descriptor *ccid_desc, DWORD Protocol)
1223                          Protocol_T1_Init(t1, lun);  {
1224            /* This function use an EGT value for cards who comply with followings
1225             * criterias:
1226             * - TA1 > 11
1227             * - current EGT = 0x00 or 0xFF
1228             * - T=0 or (T=1 and CWI >= 2)
1229             *
1230             * Without this larger EGT some non ISO 7816-3 smart cards may not
1231             * communicate with the reader.
1232             *
1233             * This modification is harmless, the reader will just be less restrictive
1234             */
1235    
1236                          SetParameters(lun, 1, sizeof(param), param);          unsigned int card_baudrate;
1237                  }          unsigned int default_baudrate;
1238                  else          double f, d;
1239                  /* T=0 */          int i;
1240    
1241            /* if TA1 not present */
1242            if (! atr->ib[0][ATR_INTERFACE_BYTE_TA].present)
1243                    return;
1244    
1245            ATR_GetParameter(atr, ATR_PARAMETER_D, &d);
1246            ATR_GetParameter(atr, ATR_PARAMETER_F, &f);
1247    
1248            /* may happen with non ISO cards */
1249            if ((0 == f) || (0 == d))
1250                    return;
1251    
1252            /* Baudrate = f x D/F */
1253            card_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock * d / f);
1254    
1255            default_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock
1256                    * ATR_DEFAULT_D / ATR_DEFAULT_F);
1257    
1258            /* TA1 > 11? */
1259            if (card_baudrate <= default_baudrate)
1260                    return;
1261    
1262            /* Current EGT = 0 or FF? */
1263            if (atr->ib[0][ATR_INTERFACE_BYTE_TC].present &&
1264                    ((0x00 == atr->ib[0][ATR_INTERFACE_BYTE_TC].value) ||
1265                    (0xFF == atr->ib[0][ATR_INTERFACE_BYTE_TC].value)))
1266            {
1267                    if (SCARD_PROTOCOL_T0 == Protocol)
1268                  {                  {
1269                          BYTE param[] = {0x11, 0x00, 0x00, 0x0a, 0x00};                          /* Init TC1 */
1270                            atr->ib[0][ATR_INTERFACE_BYTE_TC].present = TRUE;
1271                          /* get TA1 Fi/Di, default 0x11 */                          atr->ib[0][ATR_INTERFACE_BYTE_TC].value = 2;
1272                          if (atr.ib[0][ATR_INTERFACE_BYTE_TA].present)                          DEBUG_INFO("Extra EGT patch applied");
1273                                  param[0] = atr.ib[0][ATR_INTERFACE_BYTE_TA].value;                  }
   
                         if (convention == ATR_CONVENTION_INVERSE)  
                                 param[1] &= 0x02;  
   
                         /* get TC1 Extra guard time */  
                         if (atr.ib[0][ATR_INTERFACE_BYTE_TC].present)  
                                 param[2] = atr.ib[0][ATR_INTERFACE_BYTE_TC].value;  
   
                         /* TC2 WWT */  
                         if (atr.ib[1][ATR_INTERFACE_BYTE_TC].present)  
                                 param[3] = atr.ib[1][ATR_INTERFACE_BYTE_TC].value;  
1274    
1275                          SetParameters(lun, 0, sizeof(param), param);                  if (SCARD_PROTOCOL_T1 == Protocol)
1276                    {
1277                            /* TBi (i>2) present? BWI/CWI */
1278                            for (i=2; i<ATR_MAX_PROTOCOLS; i++)
1279                            {
1280                                    /* CWI >= 2 ? */
1281                                    if (atr->ib[i][ATR_INTERFACE_BYTE_TB].present &&
1282                                            ((atr->ib[i][ATR_INTERFACE_BYTE_TB].value & 0x0F) >= 2))
1283                                    {
1284                                            /* Init TC1 */
1285                                            atr->ib[0][ATR_INTERFACE_BYTE_TC].present = TRUE;
1286                                            atr->ib[0][ATR_INTERFACE_BYTE_TC].value = 2;
1287                                            DEBUG_INFO("Extra EGT patch applied");
1288    
1289                                            /* only the first TBi (i>2) must be used */
1290                                            break;
1291                                    }
1292                            }
1293                  }                  }
1294          }          }
1295    } /* extra_egt */
1296    
1297    
1298          /* negotiate IFSD in T=1 */  static char find_baud_rate(unsigned int baudrate, unsigned int *list)
1299          if ((protocol == ATR_PROTOCOL_TYPE_T1) &&  {
1300                  ! (ccid_desc->dwFeatures & CCID_CLASS_AUTO_IFSD))          int i;
1301    
1302            DEBUG_COMM2("Card baud rate: %d", baudrate);
1303    
1304            /* Does the reader support the announced smart card data speed? */
1305            for (i=0;; i++)
1306          {          {
1307                  Protocol_T1 *t1 = &(ccid_slot -> t1);                  /* end of array marker */
1308                    if (0 == list[i])
1309                            break;
1310    
1311                  Protocol_T1_Negociate_IFSD(t1, ccid_desc -> dwMaxIFSD);                  DEBUG_COMM2("Reader can do: %d", list[i]);
1312    
1313                  DEBUG_COMM3("T=1: IFSC=%d, IFSD=%d", t1->ifsc, t1->ifsd);                  /* We must take into account that the card_baudrate integral value
1314                     * is an approximative result, computed from the d/f float result.
1315                     */
1316                    if ((baudrate < list[i] + 2) && (baudrate > list[i] - 2))
1317                            return TRUE;
1318          }          }
1319    
1320          return IFD_SUCCESS;          return FALSE;
1321  } /* CardUp */  } /* find_baud_rate */
1322    
1323    
1324  RESPONSECODE CardDown(int lun)  static unsigned int T0_card_timeout(double f, double d, int TC1, int TC2,
1325            int clock_frequency)
1326  {  {
1327          /* clear T=1 context */          unsigned int timeout = DEFAULT_COM_READ_TIMEOUT;
1328          Protocol_T1_Close(&((get_ccid_slot(lun)) -> t1));          double EGT, WWT;
1329            unsigned int t;
1330    
1331            /* Timeout applied on ISO_IN or ISO_OUT card exchange
1332             * we choose the maximum computed value.
1333             *
1334             * ISO_IN timeout is the sum of:
1335             * Terminal:                                    Smart card:
1336             * 5 bytes header cmd  ->
1337             *                    <-                Procedure byte
1338             * 256 data bytes          ->
1339             *                                        <-            SW1-SW2
1340             * = 261 EGT       + 3 WWT     + 3 WWT
1341             *
1342             * ISO_OUT Timeout is the sum of:
1343             * Terminal:                    Smart card:
1344             * 5 bytes header cmd  ->
1345             *                                        <-        Procedure byte + 256 data bytes + SW1-SW2
1346             * = 5 EGT          + 1 WWT     + 259 WWT
1347             */
1348    
1349          /* Reset ATR buffer */          /* clock_frequency is in kHz so the times are in milliseconds and not
1350          CcidSlots[LunToReaderIndex(lun)].nATRLength = 0;           * in seconds */
         *CcidSlots[LunToReaderIndex(lun)].pcATRBuffer = '\0';  
1351    
1352          /* Reset PowerFlags */          /* may happen with non ISO cards */
1353          CcidSlots[LunToReaderIndex(lun)].bPowerFlags = POWERFLAGS_RAZ;          if ((0 == f) || (0 == d) || (0 == clock_frequency))
1354                    return 60;      /* 60 seconds */
1355    
1356            /* EGT */
1357            /* see ch. 6.5.3 Extra Guard Time, page 12 of ISO 7816-3 */
1358            EGT = 12 * f / d / clock_frequency + (f / d) * TC1 / clock_frequency;
1359    
1360            /* card WWT */
1361            /* see ch. 8.2 Character level, page 15 of ISO 7816-3 */
1362            WWT = 960 * TC2 * f / clock_frequency;
1363    
1364            /* ISO in */
1365            t  = 261 * EGT + (3 + 3) * WWT;
1366            /* Convert from milliseonds to seconds rouned to the upper value
1367             * use +1 instead of ceil() to round up to the nearest interger
1368             * so we can avoid a dependency on the math library */
1369            t = t/1000 +1;
1370            if (timeout < t)
1371                    timeout = t;
1372    
1373            /* ISO out */
1374            t = 5 * EGT + (1 + 259) * WWT;
1375            t = t/1000 +1;
1376            if (timeout < t)
1377                    timeout = t;
1378    
1379          return IFD_SUCCESS;          return timeout;
1380  } /* CardDown */  } /* T0_card_timeout  */
1381    
1382    
1383  void init_driver(void)  static unsigned int T1_card_timeout(double f, double d, int TC1,
1384            int BWI, int CWI, int clock_frequency)
1385  {  {
1386          char keyValue[TOKEN_MAX_VALUE_SIZE];          double EGT, BWT, CWT, etu;
1387          char infofile[FILENAME_MAX];          unsigned int timeout;
1388    
1389          /* Info.plist full patch filename */          /* Timeout applied on ISO in + ISO out card exchange
1390          snprintf(infofile, sizeof(infofile), "%s/%s/Contents/Info.plist",           *
1391                  PCSCLITE_HP_DROPDIR, BUNDLE);       * Timeout is the sum of:
1392             * - ISO in delay between leading edge of the first character sent by the
1393             *   interface device and the last one (NAD PCB LN APDU CKS) = 260 EGT,
1394             * - delay between ISO in and ISO out = BWT,
1395             * - ISO out delay between leading edge of the first character sent by the
1396             *   card and the last one (NAD PCB LN DATAS CKS) = 260 CWT.
1397             */
1398    
1399          /* Log level */          /* clock_frequency is in kHz so the times are in milliseconds and not
1400          if (0 == LTPBundleFindValueWithKey(infofile, "ifdLogLevel", keyValue, 0))           * in seconds */
         {  
                 /* convert from hex or dec or octal */  
                 LogLevel = strtoul(keyValue, 0, 16);  
1401    
1402                  /* print the log level used */          /* may happen with non ISO cards */
1403                  debug_msg("%s:%d:%s LogLevel: 0x%.4X", __FILE__, __LINE__, __FUNCTION__,          if ((0 == f) || (0 == d) || (0 == clock_frequency))
1404                          LogLevel);                  return 60;      /* 60 seconds */
         }  
1405    
1406          /* Driver options */          /* see ch. 6.5.2 Transmission factors F and D, page 12 of ISO 7816-3 */
1407          if (0 == LTPBundleFindValueWithKey(infofile, "ifdDriverOptions", keyValue, 0))          etu = f / d / clock_frequency;
         {  
                 /* convert from hex or dec or octal */  
                 DriverOptions = strtoul(keyValue, 0, 16);  
1408    
1409                  /* print the log level used */          /* EGT */
1410                  debug_msg("%s:%d:%s DriverOptions: 0x%.4X", __FILE__, __LINE__,          /* see ch. 6.5.3 Extra Guard Time, page 12 of ISO 7816-3 */
1411                          __FUNCTION__, DriverOptions);          EGT = 12 * etu + (f / d) * TC1 / clock_frequency;
         }  
1412    
1413            /* card BWT */
1414            /* see ch. 9.5.3.2 Block Waiting Time, page 20 of ISO 7816-3 */
1415            BWT = 11 * etu + (1<<BWI) * 960 * 372 / clock_frequency;
1416    
1417          DebugInitialized = TRUE;          /* card CWT */
1418  } /* init_driver */          /* see ch. 9.5.3.1 Caracter Waiting Time, page 20 of ISO 7816-3 */
1419            CWT = (11 + (1<<CWI)) * etu;
1420    
1421            timeout = 260*EGT + BWT + 260*CWT;
1422    
1423            /* Convert from milliseonds to seconds rounded to the upper value
1424             * we use +1 instead of ceil() to round up to the nearest greater interger
1425             * so we can avoid a dependency on the math library */
1426            timeout = timeout/1000 +1;
1427    
1428            return timeout;
1429    } /* T1_card_timeout  */
1430    

Legend:
Removed from v.892  
changed lines
  Added in v.2130

  ViewVC Help
Powered by ViewVC 1.1.5