/[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 663 by rousseau, Thu Jan 29 13:37:35 2004 UTC revision 2109 by rousseau, Wed Jul 12 08:30:26 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$ */
21    
22  #include <stdio.h>  #include <stdio.h>
23  #include <string.h>  #include <string.h>
24    #include <stdlib.h>
25    #include "misc.h"
26    #include <pcsclite.h>
27    #include <ifdhandler.h>
28    #include <reader.h>
29    
30  #include "pcscdefines.h"  #include "ccid.h"
31  #include "defs.h"  #include "defs.h"
32  #include "ifdhandler.h"  #include "ccid_ifdhandler.h"
33  #include "config.h"  #include "config.h"
34  #include "debug.h"  #include "debug.h"
35  #include "utils.h"  #include "utils.h"
36  #include "commands.h"  #include "commands.h"
37  #include "ccid.h"  #include "towitoko/atr.h"
38    #include "towitoko/pps.h"
39    #include "parser.h"
40    
41  #ifdef HAVE_PTHREAD  #ifdef HAVE_PTHREAD
42  #include <pthread.h>  #include <pthread.h>
43  #endif  #endif
44    
45  /* 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 */
46  static CcidDesc CcidSlots[PCSCLITE_MAX_READERS];  static CcidDesc CcidSlots[CCID_DRIVER_MAX_READERS];
47    
48  /* global mutex */  /* global mutex */
49  #ifdef HAVE_PTHREAD  #ifdef HAVE_PTHREAD
50  static pthread_mutex_t ifdh_context_mutex = PTHREAD_MUTEX_INITIALIZER;  static pthread_mutex_t ifdh_context_mutex = PTHREAD_MUTEX_INITIALIZER;
51  #endif  #endif
52    
53    int LogLevel = DEBUG_LEVEL_CRITICAL | DEBUG_LEVEL_INFO;
54    int DriverOptions = 0;
55    int PowerOnVoltage = VOLTAGE_5V;
56    static int DebugInitialized = FALSE;
57    
58    /* local functions */
59    static void init_driver(void);
60    static void extra_egt(ATR_t *atr, _ccid_descriptor *ccid_desc, DWORD Protocol);
61    static char find_baud_rate(unsigned int baudrate, unsigned int *list);
62    static unsigned int T0_card_timeout(double f, double d, int TC1, int TC2,
63            int clock_frequency);
64    static unsigned int T1_card_timeout(double f, double d, int TC1, int BWI,
65            int CWI, int clock_frequency);
66    
67    
68  RESPONSECODE IFDHCreateChannelByName(DWORD Lun, LPSTR lpcDevice)  EXTERNAL RESPONSECODE IFDHCreateChannelByName(DWORD Lun, LPSTR lpcDevice)
69  {  {
70            RESPONSECODE return_value = IFD_SUCCESS;
71            int reader_index;
72    
73            if (! DebugInitialized)
74                    init_driver();
75    
76          DEBUG_INFO3("lun: %X, device: %s", Lun, lpcDevice);          DEBUG_INFO3("lun: %X, device: %s", Lun, lpcDevice);
77    
78          if (CheckLun(Lun))          if (-1 == (reader_index = GetNewReaderIndex(Lun)))
79                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
80    
81          // Reset ATR buffer          /* Reset ATR buffer */
82          CcidSlots[LunToReaderIndex(Lun)].nATRLength = 0;          CcidSlots[reader_index].nATRLength = 0;
83          *CcidSlots[LunToReaderIndex(Lun)].pcATRBuffer = '\0';          *CcidSlots[reader_index].pcATRBuffer = '\0';
84    
85          // Reset PowerFlags          /* Reset PowerFlags */
86          CcidSlots[LunToReaderIndex(Lun)].bPowerFlags = POWERFLAGS_RAZ;          CcidSlots[reader_index].bPowerFlags = POWERFLAGS_RAZ;
87    
88  #ifdef HAVE_PTHREAD  #ifdef HAVE_PTHREAD
89          pthread_mutex_lock(&ifdh_context_mutex);          pthread_mutex_lock(&ifdh_context_mutex);
90  #endif  #endif
91    
92          if (OpenPortByName(Lun, lpcDevice) != STATUS_SUCCESS)          if (OpenPortByName(reader_index, lpcDevice) != STATUS_SUCCESS)
93          {          {
94                  DEBUG_CRITICAL("failed");                  DEBUG_CRITICAL("failed");
95                  return IFD_COMMUNICATION_ERROR;                  return_value = IFD_COMMUNICATION_ERROR;
96    
97                    /* release the allocated reader_index */
98                    ReleaseReaderIndex(reader_index);
99          }          }
100            else
101                    /* Maybe we have a special treatment for this reader */
102                    ccid_open_hack(reader_index);
103    
104  #ifdef HAVE_PTHREAD  #ifdef HAVE_PTHREAD
105          pthread_mutex_unlock(&ifdh_context_mutex);          pthread_mutex_unlock(&ifdh_context_mutex);
106  #endif  #endif
107    
108          return IFD_SUCCESS;          return return_value;
109  } /* IFDHCreateChannelByName */  } /* IFDHCreateChannelByName */
110    
111    
112  RESPONSECODE IFDHCreateChannel(DWORD Lun, DWORD Channel)  EXTERNAL RESPONSECODE IFDHCreateChannel(DWORD Lun, DWORD Channel)
113  {  {
114          /*          /*
115           * Lun - Logical Unit Number, use this for multiple card slots or           * Lun - Logical Unit Number, use this for multiple card slots or
# Line 110  RESPONSECODE IFDHCreateChannel(DWORD Lun Line 145  RESPONSECODE IFDHCreateChannel(DWORD Lun
145           * IFD_SUCCESS IFD_COMMUNICATION_ERROR           * IFD_SUCCESS IFD_COMMUNICATION_ERROR
146           */           */
147          RESPONSECODE return_value = IFD_SUCCESS;          RESPONSECODE return_value = IFD_SUCCESS;
148            int reader_index;
149    
150            if (! DebugInitialized)
151                    init_driver();
152    
153          DEBUG_INFO2("lun: %X", Lun);          DEBUG_INFO2("lun: %X", Lun);
154    
155          if (CheckLun(Lun))          if (-1 == (reader_index = GetNewReaderIndex(Lun)))
156                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
157    
158          /* Reset ATR buffer */          /* Reset ATR buffer */
159          CcidSlots[LunToReaderIndex(Lun)].nATRLength = 0;          CcidSlots[reader_index].nATRLength = 0;
160          *CcidSlots[LunToReaderIndex(Lun)].pcATRBuffer = '\0';          *CcidSlots[reader_index].pcATRBuffer = '\0';
161    
162          /* Reset PowerFlags */          /* Reset PowerFlags */
163          CcidSlots[LunToReaderIndex(Lun)].bPowerFlags = POWERFLAGS_RAZ;          CcidSlots[reader_index].bPowerFlags = POWERFLAGS_RAZ;
164    
165  #ifdef HAVE_PTHREAD  #ifdef HAVE_PTHREAD
166          pthread_mutex_lock(&ifdh_context_mutex);          pthread_mutex_lock(&ifdh_context_mutex);
167  #endif  #endif
168    
169          if (OpenPort(Lun, Channel) != STATUS_SUCCESS)          if (OpenPort(reader_index, Channel) != STATUS_SUCCESS)
170          {          {
171                  DEBUG_CRITICAL("failed");                  DEBUG_CRITICAL("failed");
172                  return_value = IFD_COMMUNICATION_ERROR;                  return_value = IFD_COMMUNICATION_ERROR;
         }  
   
         /* Maybe we have a special treatment for this reader */  
         ccid_open_hack(Lun);  
173    
174          /* initialize T=1 context */                  /* release the allocated reader_index */
175          Protocol_T1_Close(&((get_ccid_slot(Lun)) -> t1));                  ReleaseReaderIndex(reader_index);
176            }
177            else
178                    /* Maybe we have a special treatment for this reader */
179                    ccid_open_hack(reader_index);
180    
181  #ifdef HAVE_PTHREAD  #ifdef HAVE_PTHREAD
182          pthread_mutex_unlock(&ifdh_context_mutex);          pthread_mutex_unlock(&ifdh_context_mutex);
# Line 147  RESPONSECODE IFDHCreateChannel(DWORD Lun Line 186  RESPONSECODE IFDHCreateChannel(DWORD Lun
186  } /* IFDHCreateChannel */  } /* IFDHCreateChannel */
187    
188    
189  RESPONSECODE IFDHCloseChannel(DWORD Lun)  EXTERNAL RESPONSECODE IFDHCloseChannel(DWORD Lun)
190  {  {
191          /*          /*
192           * This function should close the reader communication channel for the           * This function should close the reader communication channel for the
# Line 159  RESPONSECODE IFDHCloseChannel(DWORD Lun) Line 198  RESPONSECODE IFDHCloseChannel(DWORD Lun)
198           *           *
199           * IFD_SUCCESS IFD_COMMUNICATION_ERROR           * IFD_SUCCESS IFD_COMMUNICATION_ERROR
200           */           */
201            int reader_index;
202    
203          DEBUG_INFO2("lun: %X", Lun);          DEBUG_INFO2("lun: %X", Lun);
204    
205          if (CheckLun(Lun))          if (-1 == (reader_index = LunToReaderIndex(Lun)))
206                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
207    
208          CmdPowerOff(Lun);          /* Restore the default timeout
209             * No need to wait too long if the reader disapeared */
210            get_ccid_descriptor(reader_index)->readTimeout = DEFAULT_COM_READ_TIMEOUT;
211    
212            (void)CmdPowerOff(reader_index);
213          /* No reader status check, if it failed, what can you do ? :) */          /* No reader status check, if it failed, what can you do ? :) */
214    
215  #ifdef HAVE_PTHREAD  #ifdef HAVE_PTHREAD
216          pthread_mutex_lock(&ifdh_context_mutex);          pthread_mutex_lock(&ifdh_context_mutex);
217  #endif  #endif
218    
219          ClosePort(Lun);          (void)ClosePort(reader_index);
220            ReleaseReaderIndex(reader_index);
221    
222  #ifdef HAVE_PTHREAD  #ifdef HAVE_PTHREAD
223          pthread_mutex_unlock(&ifdh_context_mutex);          pthread_mutex_unlock(&ifdh_context_mutex);
# Line 182  RESPONSECODE IFDHCloseChannel(DWORD Lun) Line 227  RESPONSECODE IFDHCloseChannel(DWORD Lun)
227  } /* IFDHCloseChannel */  } /* IFDHCloseChannel */
228    
229    
230  RESPONSECODE IFDHGetCapabilities(DWORD Lun, DWORD Tag,  EXTERNAL RESPONSECODE IFDHGetCapabilities(DWORD Lun, DWORD Tag,
231          PDWORD Length, PUCHAR Value)          PDWORD Length, PUCHAR Value)
232  {  {
233          /*          /*
# Line 202  RESPONSECODE IFDHGetCapabilities(DWORD L Line 247  RESPONSECODE IFDHGetCapabilities(DWORD L
247           *           *
248           * IFD_SUCCESS IFD_ERROR_TAG           * IFD_SUCCESS IFD_ERROR_TAG
249           */           */
250            int reader_index;
251    
252          DEBUG_INFO3("lun: %X, tag: %02X", Lun, Tag);          DEBUG_INFO3("lun: %X, tag: 0x%X", Lun, Tag);
253    
254          if (CheckLun(Lun))          if (-1 == (reader_index = LunToReaderIndex(Lun)))
255                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
256    
257          switch (Tag)          switch (Tag)
258          {          {
259                  case TAG_IFD_ATR:                  case TAG_IFD_ATR:
260                    case SCARD_ATTR_ATR_STRING:
261                          /* If Length is not zero, powerICC has been performed.                          /* If Length is not zero, powerICC has been performed.
262                           * Otherwise, return NULL pointer                           * Otherwise, return NULL pointer
263                           * Buffer size is stored in *Length */                           * Buffer size is stored in *Length */
264                          *Length = (*Length < CcidSlots[LunToReaderIndex(Lun)]                          *Length = (*Length < CcidSlots[reader_index].nATRLength) ?
265                                  .nATRLength) ?                                  *Length : CcidSlots[reader_index].nATRLength;
                                 *Length : CcidSlots[LunToReaderIndex(Lun)]  
                                 .nATRLength;  
266    
267                          if (*Length)                          if (*Length)
268                                  memcpy(Value, CcidSlots[LunToReaderIndex(Lun)]                                  memcpy(Value, CcidSlots[reader_index].pcATRBuffer, *Length);
                                         .pcATRBuffer, *Length);  
269                          break;                          break;
270    
271  #ifdef HAVE_PTHREAD  #ifdef HAVE_PTHREAD
# Line 229  RESPONSECODE IFDHGetCapabilities(DWORD L Line 273  RESPONSECODE IFDHGetCapabilities(DWORD L
273                          if (*Length >= 1)                          if (*Length >= 1)
274                          {                          {
275                                  *Length = 1;                                  *Length = 1;
276                                  *Value = PCSCLITE_MAX_READERS;                                  *Value = CCID_DRIVER_MAX_READERS;
277                          }                          }
278                          break;                          break;
279    
# Line 246  RESPONSECODE IFDHGetCapabilities(DWORD L Line 290  RESPONSECODE IFDHGetCapabilities(DWORD L
290                          if (*Length >= 1)                          if (*Length >= 1)
291                          {                          {
292                                  *Length = 1;                                  *Length = 1;
293                                  *Value = 1; /* One slot only */                                  *Value = 1 + get_ccid_descriptor(reader_index) -> bMaxSlotIndex;
294                                    DEBUG_INFO2("Reader supports %d slots", *Value);
295                            }
296                            break;
297    
298                    case TAG_IFD_SLOT_THREAD_SAFE:
299                            if (*Length >= 1)
300                            {
301                                    *Length = 1;
302                                    *Value = 0; /* Can NOT talk to multiple slots at the same time */
303                          }                          }
304                          break;                          break;
305    
# Line 258  RESPONSECODE IFDHGetCapabilities(DWORD L Line 311  RESPONSECODE IFDHGetCapabilities(DWORD L
311  } /* IFDHGetCapabilities */  } /* IFDHGetCapabilities */
312    
313    
314  RESPONSECODE IFDHSetCapabilities(DWORD Lun, DWORD Tag,  EXTERNAL RESPONSECODE IFDHSetCapabilities(DWORD Lun, DWORD Tag,
315          DWORD Length, PUCHAR Value)          /*@unused@*/ DWORD Length, /*@unused@*/ PUCHAR Value)
316  {  {
317          /*          /*
318           * This function should set the slot/card capabilities for a           * This function should set the slot/card capabilities for a
# Line 280  RESPONSECODE IFDHSetCapabilities(DWORD L Line 333  RESPONSECODE IFDHSetCapabilities(DWORD L
333    
334          /* By default, say it worked */          /* By default, say it worked */
335    
336          DEBUG_PERIODIC2("lun: %X", Lun);          DEBUG_INFO3("lun: %X, tag: 0x%X", Lun, Tag);
337    
338          /* if (CheckLun(Lun))          /* if (CheckLun(Lun))
339                  return IFD_COMMUNICATION_ERROR; */                  return IFD_COMMUNICATION_ERROR; */
# Line 289  RESPONSECODE IFDHSetCapabilities(DWORD L Line 342  RESPONSECODE IFDHSetCapabilities(DWORD L
342  } /* IFDHSetCapabilities */  } /* IFDHSetCapabilities */
343    
344    
345  RESPONSECODE IFDHSetProtocolParameters(DWORD Lun, DWORD Protocol,  EXTERNAL RESPONSECODE IFDHSetProtocolParameters(DWORD Lun, DWORD Protocol,
346          UCHAR Flags, UCHAR PTS1, UCHAR PTS2, UCHAR PTS3)          UCHAR Flags, UCHAR PTS1, UCHAR PTS2, UCHAR PTS3)
347  {  {
348          /*          /*
349           * This function should set the PTS of a particular card/slot using           * This function should set the PTS of a particular card/slot using
350           * the three PTS parameters sent           * the three PTS parameters sent
351           *           *
352           * Protocol - 0 .... 14 T=0 .... T=14 Flags - Logical OR of possible           * Protocol - 0 .... 14 T=0 .... T=14
353           * values: IFD_NEGOTIATE_PTS1 IFD_NEGOTIATE_PTS2 IFD_NEGOTIATE_PTS3 to           * Flags - Logical OR of possible values:
354           * determine which PTS values to negotiate. PTS1,PTS2,PTS3 - PTS           *  IFD_NEGOTIATE_PTS1
355           * Values.           *  IFD_NEGOTIATE_PTS2
356             *  IFD_NEGOTIATE_PTS3
357             * to determine which PTS values to negotiate.
358             * PTS1,PTS2,PTS3 - PTS Values.
359           *           *
360           * returns:           * returns:
361           *           *  IFD_SUCCESS
362           * IFD_SUCCESS IFD_ERROR_PTS_FAILURE IFD_COMMUNICATION_ERROR           *  IFD_ERROR_PTS_FAILURE
363           * IFD_PROTOCOL_NOT_SUPPORTED           *  IFD_COMMUNICATION_ERROR
364             *  IFD_PROTOCOL_NOT_SUPPORTED
365           */           */
366    
367          DEBUG_INFO2("lun: %X", Lun);          BYTE pps[PPS_MAX_LENGTH];
368            ATR_t atr;
369            unsigned int len;
370            int convention;
371            int reader_index;
372    
373            /* Set ccid desc params */
374            CcidDesc *ccid_slot;
375            _ccid_descriptor *ccid_desc;
376    
377          /* if (CheckLun(Lun))          DEBUG_INFO3("lun: %X, protocol T=%d", Lun, Protocol-1);
                 return IFD_COMMUNICATION_ERROR; */  
378    
379          return IFD_NOT_SUPPORTED;          if (-1 == (reader_index = LunToReaderIndex(Lun)))
380                    return IFD_COMMUNICATION_ERROR;
381    
382            /* Set to zero buffer */
383            memset(pps, 0, sizeof(pps));
384            memset(&atr, 0, sizeof(atr));
385    
386            /* Get ccid params */
387            ccid_slot = get_ccid_slot(reader_index);
388            ccid_desc = get_ccid_descriptor(reader_index);
389    
390            /* Do not send CCID command SetParameters or PPS to the CCID
391             * The CCID will do this himself */
392            if (ccid_desc->dwFeatures & CCID_CLASS_AUTO_PPS_PROP)
393                    return IFD_SUCCESS;
394    
395            /* Get ATR of the card */
396            ATR_InitFromArray(&atr, ccid_slot->pcATRBuffer, ccid_slot->nATRLength);
397    
398            /* Apply Extra EGT patch for bogus cards */
399            extra_egt(&atr, ccid_desc, Protocol);
400    
401            if (SCARD_PROTOCOL_T0 == Protocol)
402                    pps[1] |= ATR_PROTOCOL_TYPE_T0;
403            else
404                    if (SCARD_PROTOCOL_T1 == Protocol)
405                            pps[1] |= ATR_PROTOCOL_TYPE_T1;
406                    else
407                            return IFD_PROTOCOL_NOT_SUPPORTED;
408    
409            /* TA2 present -> specific mode */
410            if (atr.ib[1][ATR_INTERFACE_BYTE_TA].present)
411            {
412                    if (pps[1] != (atr.ib[1][ATR_INTERFACE_BYTE_TA].value & 0x0F))
413                    {
414                            /* wrong protocol */
415                            DEBUG_COMM3("Specific mode in T=%d and T=%d requested",
416                                    atr.ib[1][ATR_INTERFACE_BYTE_TA].value & 0x0F, pps[1]);
417    
418                            return IFD_PROTOCOL_NOT_SUPPORTED;
419                    }
420            }
421    
422            /* TCi (i>2) indicates CRC instead of LRC */
423            if (SCARD_PROTOCOL_T1 == Protocol)
424            {
425                    t1_state_t *t1 = &(ccid_slot -> t1);
426                    int i;
427    
428                    /* TCi (i>2) present? */
429                    for (i=2; i<ATR_MAX_PROTOCOLS; i++)
430                            if (atr.ib[i][ATR_INTERFACE_BYTE_TC].present)
431                            {
432                                    if (0 == atr.ib[i][ATR_INTERFACE_BYTE_TC].value)
433                                    {
434                                            DEBUG_COMM("Use LRC");
435                                            t1_set_param(t1, IFD_PROTOCOL_T1_CHECKSUM_LRC, 0);
436                                    }
437                                    else
438                                            if (1 == atr.ib[i][ATR_INTERFACE_BYTE_TC].value)
439                                            {
440                                                    DEBUG_COMM("Use CRC");
441                                                    t1_set_param(t1, IFD_PROTOCOL_T1_CHECKSUM_CRC, 0);
442                                            }
443                                            else
444                                                    DEBUG_COMM2("Wrong value for TCi: %d",
445                                                            atr.ib[i][ATR_INTERFACE_BYTE_TC].value);
446    
447                                    /* only the first TCi (i>2) must be used */
448                                    break;
449                            }
450            }
451    
452            /* PTS1? */
453            if (Flags & IFD_NEGOTIATE_PTS1)
454            {
455                    /* just use the value passed in argument */
456                    pps[1] |= 0x10; /* PTS1 presence */
457                    pps[2] = PTS1;
458            }
459            else
460            {
461                    /* TA1 present */
462                    if (atr.ib[0][ATR_INTERFACE_BYTE_TA].present)
463                    {
464                            unsigned int card_baudrate;
465                            unsigned int default_baudrate;
466                            double f, d;
467    
468                            ATR_GetParameter(&atr, ATR_PARAMETER_D, &d);
469                            ATR_GetParameter(&atr, ATR_PARAMETER_F, &f);
470    
471                            /* may happen with non ISO cards */
472                            if ((0 == f) || (0 == d))
473                            {
474                                    /* values for TA1=11 */
475                                    f = 372;
476                                    d = 1;
477                            }
478    
479                            /* Baudrate = f x D/F */
480                            card_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock
481                                    * d / f);
482    
483                            default_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock
484                                    * ATR_DEFAULT_D / ATR_DEFAULT_F);
485    
486                            /* if the card does not try to lower the default speed */
487                            if ((card_baudrate > default_baudrate)
488                                    /* and the reader is fast enough */
489                                    && (card_baudrate <= ccid_desc->dwMaxDataRate))
490                            {
491                                    /* the reader has no baud rates table */
492                                    if ((NULL == ccid_desc->arrayOfSupportedDataRates)
493                                            /* or explicitely support it */
494                                            || find_baud_rate(card_baudrate,
495                                                    ccid_desc->arrayOfSupportedDataRates))
496                                    {
497                                            pps[1] |= 0x10; /* PTS1 presence */
498                                            pps[2] = atr.ib[0][ATR_INTERFACE_BYTE_TA].value;
499    
500                                            DEBUG_COMM2("Set speed to %d bauds", card_baudrate);
501                                    }
502                                    else
503                                    {
504                                            DEBUG_COMM2("Reader does not support %d bauds",
505                                                    card_baudrate);
506    
507                                            /* TA2 present -> specific mode: the card is supporting
508                                             * only the baud rate specified in TA1 but reader does not
509                                             * support this value. Reject the card. */
510                                            if (atr.ib[1][ATR_INTERFACE_BYTE_TA].present)
511                                                    return IFD_COMMUNICATION_ERROR;
512                                    }
513                            }
514                            else
515                            {
516                                    /* the card is too fast for the reader */
517                                    if ((card_baudrate > ccid_desc->dwMaxDataRate +2)
518                                            /* but TA1 <= 97 */
519                                            && (atr.ib[0][ATR_INTERFACE_BYTE_TA].value <= 0x97)
520                                            /* and the reader has a baud rate table */
521                                            && ccid_desc->arrayOfSupportedDataRates)
522                                    {
523                                            unsigned char old_TA1;
524    
525                                            old_TA1 = atr.ib[0][ATR_INTERFACE_BYTE_TA].value;
526                                            while (atr.ib[0][ATR_INTERFACE_BYTE_TA].value > 0x94)
527                                            {
528                                                    /* use a lower TA1 */
529                                                    atr.ib[0][ATR_INTERFACE_BYTE_TA].value--;
530    
531                                                    ATR_GetParameter(&atr, ATR_PARAMETER_D, &d);
532                                                    ATR_GetParameter(&atr, ATR_PARAMETER_F, &f);
533    
534                                                    /* Baudrate = f x D/F */
535                                                    card_baudrate = (unsigned int) (1000 *
536                                                            ccid_desc->dwDefaultClock * d / f);
537    
538                                                    if (find_baud_rate(card_baudrate,
539                                                            ccid_desc->arrayOfSupportedDataRates))
540                                                    {
541                                                            pps[1] |= 0x10; /* PTS1 presence */
542                                                            pps[2] = atr.ib[0][ATR_INTERFACE_BYTE_TA].value;
543    
544                                                            DEBUG_COMM2("Set adapted speed to %d bauds",
545                                                                    card_baudrate);
546    
547                                                            break;
548                                                    }
549                                            }
550    
551                                            /* restore original TA1 value */
552                                            atr.ib[0][ATR_INTERFACE_BYTE_TA].value = old_TA1;
553                                    }
554                            }
555                    }
556            }
557    
558            /* PTS2? */
559            if (Flags & IFD_NEGOTIATE_PTS2)
560            {
561                    pps[1] |= 0x20; /* PTS2 presence */
562                    pps[3] = PTS2;
563            }
564    
565            /* PTS3? */
566            if (Flags & IFD_NEGOTIATE_PTS3)
567            {
568                    pps[1] |= 0x40; /* PTS3 presence */
569                    pps[4] = PTS3;
570            }
571    
572            /* Generate PPS */
573            pps[0] = 0xFF;
574    
575            /* Automatic PPS made by the ICC? */
576            if ((! (ccid_desc->dwFeatures & CCID_CLASS_AUTO_PPS_CUR))
577                    /* TA2 absent: negociable mode */
578                    && (! atr.ib[1][ATR_INTERFACE_BYTE_TA].present))
579            {
580                    int default_protocol;
581    
582                    if (ATR_MALFORMED == ATR_GetDefaultProtocol(&atr, &default_protocol))
583                            return IFD_PROTOCOL_NOT_SUPPORTED;
584    
585                    /* if the requested protocol is not the default one
586                     * or a TA1/PPS1 is present */
587                    if (((pps[1] & 0x0F) != default_protocol) || (PPS_HAS_PPS1(pps)))
588                            if (PPS_Exchange(reader_index, pps, &len, &pps[2]) != PPS_OK)
589                            {
590                                    DEBUG_INFO("PPS_Exchange Failed");
591    
592                                    return IFD_ERROR_PTS_FAILURE;
593                            }
594            }
595    
596            /* Now we must set the reader parameters */
597            ATR_GetConvention(&atr, &convention);
598    
599            /* specific mode and implicit parameters? (b5 of TA2) */
600            if (atr.ib[1][ATR_INTERFACE_BYTE_TA].present
601                    && (atr.ib[1][ATR_INTERFACE_BYTE_TA].value & 0x10))
602                    return IFD_COMMUNICATION_ERROR;
603    
604            /* T=1 */
605            if (SCARD_PROTOCOL_T1 == Protocol)
606            {
607                    BYTE param[] = {
608                            0x11,   /* Fi/Di                */
609                            0x10,   /* TCCKS                */
610                            0x00,   /* GuardTime    */
611                            0x4D,   /* BWI/CWI              */
612                            0x00,   /* ClockStop    */
613                            0x20,   /* IFSC                 */
614                            0x00    /* NADValue             */
615                    };
616                    int i;
617                    t1_state_t *t1 = &(ccid_slot -> t1);
618                    RESPONSECODE ret;
619                    double f, d;
620    
621                    /* TA1 is not default */
622                    if (PPS_HAS_PPS1(pps))
623                            param[0] = pps[2];
624    
625                    /* CRC checksum? */
626                    if (2 == t1->rc_bytes)
627                            param[1] |= 0x01;
628    
629                    /* the CCID should ignore this bit */
630                    if (ATR_CONVENTION_INVERSE == convention)
631                            param[1] |= 0x02;
632    
633                    /* get TC1 Extra guard time */
634                    if (atr.ib[0][ATR_INTERFACE_BYTE_TC].present)
635                            param[2] = atr.ib[0][ATR_INTERFACE_BYTE_TC].value;
636    
637                    /* TBi (i>2) present? BWI/CWI */
638                    for (i=2; i<ATR_MAX_PROTOCOLS; i++)
639                            if (atr.ib[i][ATR_INTERFACE_BYTE_TB].present)
640                            {
641                                    DEBUG_COMM3("BWI/CWI (TB%d) present: 0x%02X", i+1,
642                                            atr.ib[i][ATR_INTERFACE_BYTE_TB].value);
643                                    param[3] = atr.ib[i][ATR_INTERFACE_BYTE_TB].value;
644    
645                                    /* only the first TBi (i>2) must be used */
646                                    break;
647                            }
648    
649                    /* compute communication timeout */
650                    ATR_GetParameter(&atr, ATR_PARAMETER_F, &f);
651                    ATR_GetParameter(&atr, ATR_PARAMETER_D, &d);
652                    ccid_desc->readTimeout = T1_card_timeout(f, d, param[2],
653                            (param[3] & 0xF0) >> 4 /* BWI */, param[3] & 0x0F /* CWI */,
654                            ccid_desc->dwDefaultClock);
655    
656                    DEBUG_COMM2("Timeout: %d seconds", ccid_desc->readTimeout);
657    
658                    ret = SetParameters(reader_index, 1, sizeof(param), param);
659                    if (IFD_SUCCESS != ret)
660                            return ret;
661            }
662            else
663            /* T=0 */
664            {
665                    BYTE param[] = {
666                            0x11,   /* Fi/Di                        */
667                            0x00,   /* TCCKS                        */
668                            0x00,   /* GuardTime            */
669                            0x0A,   /* WaitingInteger       */
670                            0x00    /* ClockStop            */
671                    };
672                    RESPONSECODE ret;
673                    double f, d;
674    
675                    /* TA1 is not default */
676                    if (PPS_HAS_PPS1(pps))
677                            param[0] = pps[2];
678    
679                    if (ATR_CONVENTION_INVERSE == convention)
680                            param[1] |= 0x02;
681    
682                    /* get TC1 Extra guard time */
683                    if (atr.ib[0][ATR_INTERFACE_BYTE_TC].present)
684                            param[2] = atr.ib[0][ATR_INTERFACE_BYTE_TC].value;
685    
686                    /* TC2 WWT */
687                    if (atr.ib[1][ATR_INTERFACE_BYTE_TC].present)
688                            param[3] = atr.ib[1][ATR_INTERFACE_BYTE_TC].value;
689    
690                    /* compute communication timeout */
691                    ATR_GetParameter(&atr, ATR_PARAMETER_F, &f);
692                    ATR_GetParameter(&atr, ATR_PARAMETER_D, &d);
693    
694                    ccid_desc->readTimeout = T0_card_timeout(f, d, param[2] /* TC1 */,
695                            param[3] /* TC2 */, ccid_desc->dwDefaultClock);
696    
697                    DEBUG_COMM2("Communication timeout: %d seconds",
698                            ccid_desc->readTimeout);
699    
700                    ret = SetParameters(reader_index, 0, sizeof(param), param);
701                    if (IFD_SUCCESS != ret)
702                            return ret;
703            }
704    
705            /* set IFSC & IFSD in T=1 */
706            if (SCARD_PROTOCOL_T1 == Protocol)
707            {
708                    t1_state_t *t1 = &(ccid_slot -> t1);
709                    int i;
710    
711                    /* TAi (i>2) present? */
712                    for (i=2; i<ATR_MAX_PROTOCOLS; i++)
713                            if (atr.ib[i][ATR_INTERFACE_BYTE_TA].present)
714                            {
715                                    DEBUG_COMM3("IFSC (TA%d) present: %d", i+1,
716                                            atr.ib[i][ATR_INTERFACE_BYTE_TA].value);
717                                    t1_set_param(t1, IFD_PROTOCOL_T1_IFSC,
718                                            atr.ib[i][ATR_INTERFACE_BYTE_TA].value);
719    
720                                    /* only the first TAi (i>2) must be used */
721                                    break;
722                            }
723    
724                    /* IFSD not negociated by the reader? */
725                    if (! (ccid_desc->dwFeatures & CCID_CLASS_AUTO_IFSD))
726                    {
727                            DEBUG_COMM2("Negociate IFSD at %d", ccid_desc -> dwMaxIFSD);
728                            if (t1_negociate_ifsd(t1, 0, ccid_desc -> dwMaxIFSD) < 0)
729                                    return IFD_COMMUNICATION_ERROR;
730                    }
731                    t1_set_param(t1, IFD_PROTOCOL_T1_IFSD, ccid_desc -> dwMaxIFSD);
732    
733                    DEBUG_COMM3("T=1: IFSC=%d, IFSD=%d", t1->ifsc, t1->ifsd);
734            }
735    
736            /* store used protocol for use by the secure commands (verify/change PIN) */
737            ccid_desc->cardProtocol = Protocol;
738    
739            return IFD_SUCCESS;
740  } /* IFDHSetProtocolParameters */  } /* IFDHSetProtocolParameters */
741    
742    
743  RESPONSECODE IFDHPowerICC(DWORD Lun, DWORD Action,  EXTERNAL RESPONSECODE IFDHPowerICC(DWORD Lun, DWORD Action,
744          PUCHAR Atr, PDWORD AtrLength)          PUCHAR Atr, PDWORD AtrLength)
745  {  {
746          /*          /*
# Line 355  RESPONSECODE IFDHPowerICC(DWORD Lun, DWO Line 779  RESPONSECODE IFDHPowerICC(DWORD Lun, DWO
779           * IFD_NOT_SUPPORTED           * IFD_NOT_SUPPORTED
780           */           */
781    
782          int nlength;          unsigned int nlength;
783          RESPONSECODE return_value = IFD_SUCCESS;          RESPONSECODE return_value = IFD_SUCCESS;
784          unsigned char pcbuffer[RESP_BUF_SIZE];          unsigned char pcbuffer[RESP_BUF_SIZE];
785            int reader_index;
786    
787          DEBUG_INFO2("lun: %X", Lun);          DEBUG_INFO2("lun: %X", Lun);
788    
789          /* By default, assume it won't work :) */          /* By default, assume it won't work :) */
790          *AtrLength = 0;          *AtrLength = 0;
791    
792          if (CheckLun(Lun))          if (-1 == (reader_index = LunToReaderIndex(Lun)))
793                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
794    
795          switch (Action)          switch (Action)
796          {          {
797                    case IFD_POWER_DOWN:
798                            /* Clear ATR buffer */
799                            CcidSlots[reader_index].nATRLength = 0;
800                            *CcidSlots[reader_index].pcATRBuffer = '\0';
801    
802                            /* Memorise the request */
803                            CcidSlots[reader_index].bPowerFlags |= MASK_POWERFLAGS_PDWN;
804    
805                            /* send the command */
806                            if (IFD_SUCCESS != CmdPowerOff(reader_index))
807                            {
808                                    DEBUG_CRITICAL("PowerDown failed");
809                                    return_value = IFD_ERROR_POWER_ACTION;
810                                    goto end;
811                            }
812    
813                            /* clear T=1 context */
814                            t1_release(&(get_ccid_slot(reader_index) -> t1));
815                            break;
816    
817                  case IFD_POWER_UP:                  case IFD_POWER_UP:
818                  case IFD_RESET:                  case IFD_RESET:
819                          nlength = sizeof(pcbuffer);                          nlength = sizeof(pcbuffer);
820                          if (CmdPowerOn(Lun, &nlength, pcbuffer) != IFD_SUCCESS)                          if (CmdPowerOn(reader_index, &nlength, pcbuffer, PowerOnVoltage)
821                                    != IFD_SUCCESS)
822                          {                          {
823                                  DEBUG_CRITICAL("PowerUp failed");                                  DEBUG_CRITICAL("PowerUp failed");
824                                  return_value = IFD_ERROR_POWER_ACTION;                                  return_value = IFD_ERROR_POWER_ACTION;
# Line 380  RESPONSECODE IFDHPowerICC(DWORD Lun, DWO Line 826  RESPONSECODE IFDHPowerICC(DWORD Lun, DWO
826                          }                          }
827    
828                          /* Power up successful, set state variable to memorise it */                          /* Power up successful, set state variable to memorise it */
829                          CcidSlots[LunToReaderIndex(Lun)].bPowerFlags |=                          CcidSlots[reader_index].bPowerFlags |= MASK_POWERFLAGS_PUP;
830                                  MASK_POWERFLAGS_PUP;                          CcidSlots[reader_index].bPowerFlags &= ~MASK_POWERFLAGS_PDWN;
                         CcidSlots[LunToReaderIndex(Lun)].bPowerFlags &=  
                                 ~MASK_POWERFLAGS_PDWN;  
831    
832                          /* Reset is returned, even if TCK is wrong */                          /* Reset is returned, even if TCK is wrong */
833                          CcidSlots[LunToReaderIndex(Lun)].nATRLength = *AtrLength =                          CcidSlots[reader_index].nATRLength = *AtrLength =
834                                  (nlength < MAX_ATR_SIZE) ? nlength : MAX_ATR_SIZE;                                  (nlength < MAX_ATR_SIZE) ? nlength : MAX_ATR_SIZE;
835                          memcpy(Atr, pcbuffer, *AtrLength);                          memcpy(Atr, pcbuffer, *AtrLength);
836                          memcpy(CcidSlots[LunToReaderIndex(Lun)].pcATRBuffer,                          memcpy(CcidSlots[reader_index].pcATRBuffer, pcbuffer, *AtrLength);
                                 pcbuffer, *AtrLength);  
   
                         /* set T=1 context */  
                         Protocol_T1_Init(&((get_ccid_slot(Lun)) -> t1), Lun);  
   
                         break;  
   
                 case IFD_POWER_DOWN:  
                         /* Clear ATR buffer */  
                         CcidSlots[LunToReaderIndex(Lun)].nATRLength = 0;  
                         *CcidSlots[LunToReaderIndex(Lun)].pcATRBuffer = '\0';  
   
                         /* Memorise the request */  
                         CcidSlots[LunToReaderIndex(Lun)].bPowerFlags |=  
                                 MASK_POWERFLAGS_PDWN;  
                         /* send the command */  
                         return_value = CmdPowerOff(Lun);  
   
                         /* clear T=1 context */  
                         Protocol_T1_Close(&((get_ccid_slot(Lun)) -> t1));  
837    
838                            /* initialise T=1 context */
839                            t1_init(&(get_ccid_slot(reader_index) -> t1), reader_index);
840                          break;                          break;
841    
842                  default:                  default:
# Line 423  end: Line 849  end:
849  } /* IFDHPowerICC */  } /* IFDHPowerICC */
850    
851    
852  RESPONSECODE IFDHTransmitToICC(DWORD Lun, SCARD_IO_HEADER SendPci,  EXTERNAL RESPONSECODE IFDHTransmitToICC(DWORD Lun, SCARD_IO_HEADER SendPci,
853          PUCHAR TxBuffer, DWORD TxLength,          PUCHAR TxBuffer, DWORD TxLength,
854          PUCHAR RxBuffer, PDWORD RxLength, PSCARD_IO_HEADER RecvPci)          PUCHAR RxBuffer, PDWORD RxLength, /*@unused@*/ PSCARD_IO_HEADER RecvPci)
855  {  {
856          /*          /*
857           * This function performs an APDU exchange with the card/slot           * This function performs an APDU exchange with the card/slot
# Line 462  RESPONSECODE IFDHTransmitToICC(DWORD Lun Line 888  RESPONSECODE IFDHTransmitToICC(DWORD Lun
888           */           */
889    
890          RESPONSECODE return_value;          RESPONSECODE return_value;
891          int rx_length;          unsigned int rx_length;
892            int reader_index;
893    
894          DEBUG_INFO2("lun: %X", Lun);          DEBUG_INFO2("lun: %X", Lun);
895    
896          if (CheckLun(Lun))          if (-1 == (reader_index = LunToReaderIndex(Lun)))
897                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
898    
899          rx_length = *RxLength;          rx_length = *RxLength;
900          return_value = CmdXfrBlock(Lun, TxLength, TxBuffer, &rx_length, RxBuffer,          return_value = CmdXfrBlock(reader_index, TxLength, TxBuffer, &rx_length,
901                  SendPci.Protocol);                  RxBuffer, SendPci.Protocol);
902          *RxLength = rx_length;          *RxLength = rx_length;
903    
904          return return_value;          return return_value;
905  } /* IFDHTransmitToICC */  } /* IFDHTransmitToICC */
906    
907    
908  RESPONSECODE IFDHControl(DWORD Lun, PUCHAR TxBuffer,  EXTERNAL RESPONSECODE IFDHControl(DWORD Lun, DWORD dwControlCode,
909          DWORD TxLength, PUCHAR RxBuffer, PDWORD RxLength)          PUCHAR TxBuffer, DWORD TxLength, PUCHAR RxBuffer, DWORD RxLength,
910            PDWORD pdwBytesReturned)
911  {  {
912          /*          /*
913           * This function performs a data exchange with the reader (not the           * This function performs a data exchange with the reader (not the
# Line 495  RESPONSECODE IFDHControl(DWORD Lun, PUCH Line 923  RESPONSECODE IFDHControl(DWORD Lun, PUCH
923           *           *
924           * Notes: RxLength should be zero on error.           * Notes: RxLength should be zero on error.
925           */           */
926            RESPONSECODE return_value = IFD_COMMUNICATION_ERROR;
927            int reader_index;
928    
929          DEBUG_INFO2("lun: %X", Lun);          DEBUG_INFO3("lun: %X, ControlCode: 0x%X", Lun, dwControlCode);
930    
931          /* if (CheckLun(Lun))          reader_index = LunToReaderIndex(Lun);
932                  return IFD_COMMUNICATION_ERROR; */          if ((-1 == reader_index) || (NULL == pdwBytesReturned))
933                    return return_value;
934    
935          /* Set the return length to 0 to avoid problems */          /* Set the return length to 0 to avoid problems */
936          if (RxLength)          *pdwBytesReturned = 0;
                 *RxLength = 0;  
937    
938          return IFD_NOT_SUPPORTED;          if (IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE == dwControlCode)
939            {
940                    if (FALSE == (DriverOptions & DRIVER_OPTION_CCID_EXCHANGE_AUTHORIZED))
941                    {
942                            DEBUG_INFO("ifd exchange (Escape command) not allowed");
943                            return_value = IFD_COMMUNICATION_ERROR;
944                    }
945                    else
946                    {
947                            unsigned int iBytesReturned;
948    
949                            iBytesReturned = RxLength;
950                            return_value = CmdEscape(reader_index, TxBuffer, TxLength, RxBuffer,
951                                    &iBytesReturned);
952                            *pdwBytesReturned = iBytesReturned;
953                    }
954            }
955    
956            /* Implement the PC/SC v2.1.2 Part 10 IOCTL mechanism */
957    
958            /* Query for features */
959            if (CM_IOCTL_GET_FEATURE_REQUEST == dwControlCode)
960            {
961                    unsigned int iBytesReturned = 0;
962                    PCSC_TLV_STRUCTURE *pcsc_tlv = (PCSC_TLV_STRUCTURE *)RxBuffer;
963    
964                    /* we need room for two records */
965                    if (RxLength < 2 * sizeof(PCSC_TLV_STRUCTURE))
966                            return IFD_COMMUNICATION_ERROR;
967    
968                    /* We can only support direct verify and/or modify currently */
969                    if (get_ccid_descriptor(reader_index) -> bPINSupport
970                            & CCID_CLASS_PIN_VERIFY)
971                    {
972                            pcsc_tlv -> tag = FEATURE_VERIFY_PIN_DIRECT;
973                            pcsc_tlv -> length = 0x04; /* always 0x04 */
974                            pcsc_tlv -> value = IOCTL_FEATURE_VERIFY_PIN_DIRECT;
975    
976                            pcsc_tlv++;
977                            iBytesReturned += sizeof(PCSC_TLV_STRUCTURE);
978                    }
979    
980                    if (get_ccid_descriptor(reader_index) -> bPINSupport
981                            & CCID_CLASS_PIN_MODIFY)
982                    {
983                            pcsc_tlv -> tag = FEATURE_MODIFY_PIN_DIRECT;
984                            pcsc_tlv -> length = 0x04; /* always 0x04 */
985                            pcsc_tlv -> value = IOCTL_FEATURE_MODIFY_PIN_DIRECT;
986    
987                            pcsc_tlv++;
988                            iBytesReturned += sizeof(PCSC_TLV_STRUCTURE);
989                    }
990                    *pdwBytesReturned = iBytesReturned;
991                    return_value = IFD_SUCCESS;
992            }
993    
994            /* Verify a PIN, plain CCID */
995            if (IOCTL_FEATURE_VERIFY_PIN_DIRECT == dwControlCode)
996            {
997                    unsigned int iBytesReturned;
998    
999                    iBytesReturned = RxLength;
1000                    return_value = SecurePINVerify(reader_index, TxBuffer, TxLength,
1001                            RxBuffer, &iBytesReturned);
1002                    *pdwBytesReturned = iBytesReturned;
1003            }
1004    
1005            /* Modify a PIN, plain CCID */
1006            if (IOCTL_FEATURE_MODIFY_PIN_DIRECT == dwControlCode)
1007            {
1008                    unsigned int iBytesReturned;
1009    
1010                    iBytesReturned = RxLength;
1011                    return_value = SecurePINModify(reader_index, TxBuffer, TxLength,
1012                            RxBuffer, &iBytesReturned);
1013                    *pdwBytesReturned = iBytesReturned;
1014            }
1015    
1016            return return_value;
1017  } /* IFDHControl */  } /* IFDHControl */
1018    
1019    
1020  RESPONSECODE IFDHICCPresence(DWORD Lun)  EXTERNAL RESPONSECODE IFDHICCPresence(DWORD Lun)
1021  {  {
1022          /*          /*
1023           * This function returns the status of the card inserted in the           * This function returns the status of the card inserted in the
# Line 521  RESPONSECODE IFDHICCPresence(DWORD Lun) Line 1029  RESPONSECODE IFDHICCPresence(DWORD Lun)
1029    
1030          unsigned char pcbuffer[SIZE_GET_SLOT_STATUS];          unsigned char pcbuffer[SIZE_GET_SLOT_STATUS];
1031          RESPONSECODE return_value = IFD_COMMUNICATION_ERROR;          RESPONSECODE return_value = IFD_COMMUNICATION_ERROR;
1032            int oldLogLevel;
1033            int reader_index;
1034            _ccid_descriptor *ccid_descriptor;
1035            unsigned int oldReadTimeout;
1036    
1037          DEBUG_PERIODIC2("lun: %X", Lun);          DEBUG_PERIODIC2("lun: %X", Lun);
1038    
1039          if (CheckLun(Lun))          if (-1 == (reader_index = LunToReaderIndex(Lun)))
1040                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
1041    
1042          if (CmdGetSlotStatus(Lun, pcbuffer) != IFD_SUCCESS)          ccid_descriptor = get_ccid_descriptor(reader_index);
1043    
1044            /* save the current read timeout computed from card capabilities */
1045            oldReadTimeout = ccid_descriptor->readTimeout;
1046    
1047            /* use default timeout since the reader may not be present anymore */
1048            ccid_descriptor->readTimeout = DEFAULT_COM_READ_TIMEOUT;
1049    
1050            /* if DEBUG_LEVEL_PERIODIC is not set we remove DEBUG_LEVEL_COMM */
1051            oldLogLevel = LogLevel;
1052            if (! (LogLevel & DEBUG_LEVEL_PERIODIC))
1053                    LogLevel &= ~DEBUG_LEVEL_COMM;
1054    
1055            return_value = CmdGetSlotStatus(reader_index, pcbuffer);
1056    
1057            /* set back the old timeout */
1058            ccid_descriptor->readTimeout = oldReadTimeout;
1059    
1060            /* set back the old LogLevel */
1061            LogLevel = oldLogLevel;
1062    
1063            if (return_value != IFD_SUCCESS)
1064                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
1065    
1066          switch (pcbuffer[7])    /* bStatus */          return_value = IFD_COMMUNICATION_ERROR;
1067            switch (pcbuffer[7] & CCID_ICC_STATUS_MASK)     /* bStatus */
1068          {          {
1069                  case 0x00:                  case CCID_ICC_PRESENT_ACTIVE:
1070                    case CCID_ICC_PRESENT_INACTIVE:
1071                          return_value = IFD_ICC_PRESENT;                          return_value = IFD_ICC_PRESENT;
1072                            /* use default slot */
1073                          break;                          break;
1074    
1075                  case 0x01:                  case CCID_ICC_ABSENT:
1076                          return_value = IFD_ICC_PRESENT;                          /* Reset ATR buffer */
1077                          break;                          CcidSlots[reader_index].nATRLength = 0;
1078                            *CcidSlots[reader_index].pcATRBuffer = '\0';
1079    
1080                            /* Reset PowerFlags */
1081                            CcidSlots[reader_index].bPowerFlags = POWERFLAGS_RAZ;
1082    
                 case 0x02:  
1083                          return_value = IFD_ICC_NOT_PRESENT;                          return_value = IFD_ICC_NOT_PRESENT;
1084                          break;                          break;
1085          }          }
1086    
1087            /* SCR331-DI contactless reader */
1088            if (((SCR331DI == ccid_descriptor->readerID)
1089                    || (SDI010 == ccid_descriptor->readerID)
1090                    || (SCR331DINTTCOM == ccid_descriptor->readerID))
1091                    && (ccid_descriptor->bCurrentSlotIndex > 0))
1092            {
1093                    unsigned char cmd[] = { 0x11 };
1094                    /*  command: 11 ??
1095                     * response: 00 11 01 ?? no card
1096                     *           01 04 00 ?? card present */
1097    
1098                    unsigned char res[10];
1099                    unsigned int length_res = sizeof(res);
1100    
1101                    /* if DEBUG_LEVEL_PERIODIC is not set we remove DEBUG_LEVEL_COMM */
1102                    oldLogLevel = LogLevel;
1103                    if (! (LogLevel & DEBUG_LEVEL_PERIODIC))
1104                            LogLevel &= ~DEBUG_LEVEL_COMM;
1105    
1106                    CmdEscape(reader_index, cmd, sizeof(cmd), res, &length_res);
1107    
1108                    /* set back the old LogLevel */
1109                    LogLevel = oldLogLevel;
1110    
1111                    if (0x01 == res[0])
1112                            return_value = IFD_ICC_PRESENT;
1113                    else
1114                    {
1115                            /* Reset ATR buffer */
1116                            CcidSlots[reader_index].nATRLength = 0;
1117                            *CcidSlots[reader_index].pcATRBuffer = '\0';
1118    
1119                            /* Reset PowerFlags */
1120                            CcidSlots[reader_index].bPowerFlags = POWERFLAGS_RAZ;
1121    
1122                            return_value = IFD_ICC_NOT_PRESENT;
1123                    }
1124            }
1125    
1126            DEBUG_PERIODIC2("Card %s",
1127                    IFD_ICC_PRESENT == return_value ? "present" : "absent");
1128    
1129          return return_value;          return return_value;
1130  } /* IFDHICCPresence */  } /* IFDHICCPresence */
1131    
1132    
1133  CcidDesc *get_ccid_slot(int lun)  CcidDesc *get_ccid_slot(unsigned int reader_index)
1134  {  {
1135          return &CcidSlots[LunToReaderIndex(lun)];          return &CcidSlots[reader_index];
1136  } /* get_ccid_slot */  } /* get_ccid_slot */
1137    
1138    
1139    void init_driver(void)
1140    {
1141            char keyValue[TOKEN_MAX_VALUE_SIZE];
1142            char infofile[FILENAME_MAX];
1143    
1144            /* Info.plist full patch filename */
1145            snprintf(infofile, sizeof(infofile), "%s/%s/Contents/Info.plist",
1146                    PCSCLITE_HP_DROPDIR, BUNDLE);
1147    
1148            /* Log level */
1149            if (0 == LTPBundleFindValueWithKey(infofile, "ifdLogLevel", keyValue, 0))
1150            {
1151                    /* convert from hex or dec or octal */
1152                    LogLevel = strtoul(keyValue, NULL, 0);
1153    
1154                    /* print the log level used */
1155                    DEBUG_INFO2("LogLevel: 0x%.4X", LogLevel);
1156            }
1157    
1158            /* Driver options */
1159            if (0 == LTPBundleFindValueWithKey(infofile, "ifdDriverOptions", keyValue, 0))
1160            {
1161                    /* convert from hex or dec or octal */
1162                    DriverOptions = strtoul(keyValue, NULL, 0);
1163    
1164                    /* print the log level used */
1165                    DEBUG_INFO2("DriverOptions: 0x%.4X", DriverOptions);
1166            }
1167    
1168            /* get the voltage parameter */
1169            switch ((DriverOptions >> 4) & 0x03)
1170            {
1171                    case 0:
1172                            PowerOnVoltage = VOLTAGE_5V;
1173                            break;
1174    
1175                    case 1:
1176                            PowerOnVoltage = VOLTAGE_3V;
1177                            break;
1178    
1179                    case 2:
1180                            PowerOnVoltage = VOLTAGE_1_8V;
1181                            break;
1182    
1183                    case 3:
1184                            PowerOnVoltage = VOLTAGE_AUTO;
1185                            break;
1186            }
1187    
1188            /* initialise the Lun to reader_index mapping */
1189            InitReaderIndex();
1190    
1191            DebugInitialized = TRUE;
1192    } /* init_driver */
1193    
1194    
1195    void extra_egt(ATR_t *atr, _ccid_descriptor *ccid_desc, DWORD Protocol)
1196    {
1197            /* This function use an EGT value for cards who comply with followings
1198             * criterias:
1199             * - TA1 > 11
1200             * - current EGT = 0x00 or 0xFF
1201             * - T=0 or (T=1 and CWI >= 2)
1202             *
1203             * Without this larger EGT some non ISO 7816-3 smart cards may not
1204             * communicate with the reader.
1205             *
1206             * This modification is harmless, the reader will just be less restrictive
1207             */
1208    
1209            unsigned int card_baudrate;
1210            unsigned int default_baudrate;
1211            double f, d;
1212            int i;
1213    
1214            /* if TA1 not present */
1215            if (! atr->ib[0][ATR_INTERFACE_BYTE_TA].present)
1216                    return;
1217    
1218            ATR_GetParameter(atr, ATR_PARAMETER_D, &d);
1219            ATR_GetParameter(atr, ATR_PARAMETER_F, &f);
1220    
1221            /* may happen with non ISO cards */
1222            if ((0 == f) || (0 == d))
1223                    return;
1224    
1225            /* Baudrate = f x D/F */
1226            card_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock * d / f);
1227    
1228            default_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock
1229                    * ATR_DEFAULT_D / ATR_DEFAULT_F);
1230    
1231            /* TA1 > 11? */
1232            if (card_baudrate <= default_baudrate)
1233                    return;
1234    
1235            /* Current EGT = 0 or FF? */
1236            if (atr->ib[0][ATR_INTERFACE_BYTE_TC].present &&
1237                    ((0x00 == atr->ib[0][ATR_INTERFACE_BYTE_TC].value) ||
1238                    (0xFF == atr->ib[0][ATR_INTERFACE_BYTE_TC].value)))
1239            {
1240                    if (SCARD_PROTOCOL_T0 == Protocol)
1241                    {
1242                            /* Init TC1 */
1243                            atr->ib[0][ATR_INTERFACE_BYTE_TC].present = TRUE;
1244                            atr->ib[0][ATR_INTERFACE_BYTE_TC].value = 2;
1245                            DEBUG_INFO("Extra EGT patch applied");
1246                    }
1247    
1248                    if (SCARD_PROTOCOL_T1 == Protocol)
1249                    {
1250                            /* TBi (i>2) present? BWI/CWI */
1251                            for (i=2; i<ATR_MAX_PROTOCOLS; i++)
1252                            {
1253                                    /* CWI >= 2 ? */
1254                                    if (atr->ib[i][ATR_INTERFACE_BYTE_TB].present &&
1255                                            ((atr->ib[i][ATR_INTERFACE_BYTE_TB].value & 0x0F) >= 2))
1256                                    {
1257                                            /* Init TC1 */
1258                                            atr->ib[0][ATR_INTERFACE_BYTE_TC].present = TRUE;
1259                                            atr->ib[0][ATR_INTERFACE_BYTE_TC].value = 2;
1260                                            DEBUG_INFO("Extra EGT patch applied");
1261    
1262                                            /* only the first TBi (i>2) must be used */
1263                                            break;
1264                                    }
1265                            }
1266                    }
1267            }
1268    } /* extra_egt */
1269    
1270    
1271    static char find_baud_rate(unsigned int baudrate, unsigned int *list)
1272    {
1273            int i;
1274    
1275            DEBUG_COMM2("Card baud rate: %d", baudrate);
1276    
1277            /* Does the reader support the announced smart card data speed? */
1278            for (i=0;; i++)
1279            {
1280                    /* end of array marker */
1281                    if (0 == list[i])
1282                            break;
1283    
1284                    DEBUG_COMM2("Reader can do: %d", list[i]);
1285    
1286                    /* We must take into account that the card_baudrate integral value
1287                     * is an approximative result, computed from the d/f float result.
1288                     */
1289                    if ((baudrate < list[i] + 2) && (baudrate > list[i] - 2))
1290                            return TRUE;
1291            }
1292    
1293            return FALSE;
1294    } /* find_baud_rate */
1295    
1296    
1297    static unsigned int T0_card_timeout(double f, double d, int TC1, int TC2,
1298            int clock_frequency)
1299    {
1300            unsigned int timeout = DEFAULT_COM_READ_TIMEOUT;
1301            double EGT, WWT;
1302            unsigned int t;
1303    
1304            /* Timeout applied on ISO_IN or ISO_OUT card exchange
1305             * we choose the maximum computed value.
1306             *
1307             * ISO_IN timeout is the sum of:
1308             * Terminal:                                    Smart card:
1309             * 5 bytes header cmd  ->
1310             *                    <-                Procedure byte
1311             * 256 data bytes          ->
1312             *                                        <-            SW1-SW2
1313             * = 261 EGT       + 3 WWT     + 3 WWT
1314             *
1315             * ISO_OUT Timeout is the sum of:
1316             * Terminal:                    Smart card:
1317             * 5 bytes header cmd  ->
1318             *                                        <-        Procedure byte + 256 data bytes + SW1-SW2
1319             * = 5 EGT          + 1 WWT     + 259 WWT
1320             */
1321    
1322            /* clock_frequency is in kHz so the times are in milliseconds and not
1323             * in seconds */
1324    
1325            /* may happen with non ISO cards */
1326            if ((0 == f) || (0 == d) || (0 == clock_frequency))
1327                    return 60;      /* 60 seconds */
1328    
1329            /* EGT */
1330            /* see ch. 6.5.3 Extra Guard Time, page 12 of ISO 7816-3 */
1331            EGT = 12 * f / d / clock_frequency + (f / d) * TC1 / clock_frequency;
1332    
1333            /* card WWT */
1334            /* see ch. 8.2 Character level, page 15 of ISO 7816-3 */
1335            WWT = 960 * TC2 * f / clock_frequency;
1336    
1337            /* ISO in */
1338            t  = 261 * EGT + (3 + 3) * WWT;
1339            /* Convert from milliseonds to seconds rouned to the upper value
1340             * use +1 instead of ceil() to round up to the nearest interger
1341             * so we can avoid a dependency on the math library */
1342            t = t/1000 +1;
1343            if (timeout < t)
1344                    timeout = t;
1345    
1346            /* ISO out */
1347            t = 5 * EGT + (1 + 259) * WWT;
1348            t = t/1000 +1;
1349            if (timeout < t)
1350                    timeout = t;
1351    
1352            return timeout;
1353    } /* T0_card_timeout  */
1354    
1355    
1356    static unsigned int T1_card_timeout(double f, double d, int TC1,
1357            int BWI, int CWI, int clock_frequency)
1358    {
1359            double EGT, BWT, CWT, etu;
1360            unsigned int timeout;
1361    
1362            /* Timeout applied on ISO in + ISO out card exchange
1363             *
1364         * Timeout is the sum of:
1365             * - ISO in delay between leading edge of the first character sent by the
1366             *   interface device and the last one (NAD PCB LN APDU CKS) = 260 EGT,
1367             * - delay between ISO in and ISO out = BWT,
1368             * - ISO out delay between leading edge of the first character sent by the
1369             *   card and the last one (NAD PCB LN DATAS CKS) = 260 CWT.
1370             */
1371    
1372            /* clock_frequency is in kHz so the times are in milliseconds and not
1373             * in seconds */
1374    
1375            /* may happen with non ISO cards */
1376            if ((0 == f) || (0 == d) || (0 == clock_frequency))
1377                    return 60;      /* 60 seconds */
1378    
1379            /* see ch. 6.5.2 Transmission factors F and D, page 12 of ISO 7816-3 */
1380            etu = f / d / clock_frequency;
1381    
1382            /* EGT */
1383            /* see ch. 6.5.3 Extra Guard Time, page 12 of ISO 7816-3 */
1384            EGT = 12 * etu + (f / d) * TC1 / clock_frequency;
1385    
1386            /* card BWT */
1387            /* see ch. 9.5.3.2 Block Waiting Time, page 20 of ISO 7816-3 */
1388            BWT = 11 * etu + (1<<BWI) * 960 * 372 / clock_frequency;
1389    
1390            /* card CWT */
1391            /* see ch. 9.5.3.1 Caracter Waiting Time, page 20 of ISO 7816-3 */
1392            CWT = (11 + (1<<CWI)) * etu;
1393    
1394            timeout = 260*EGT + BWT + 260*CWT;
1395    
1396            /* Convert from milliseonds to seconds rounded to the upper value
1397             * we use +1 instead of ceil() to round up to the nearest greater interger
1398             * so we can avoid a dependency on the math library */
1399            timeout = timeout/1000 +1;
1400    
1401            return timeout;
1402    } /* T1_card_timeout  */
1403    

Legend:
Removed from v.663  
changed lines
  Added in v.2109

  ViewVC Help
Powered by ViewVC 1.1.5