/[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 269 by rousseau, Tue Aug 12 12:40:23 2003 UTC revision 1630 by rousseau, Thu Sep 1 09:11:30 2005 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  #ifdef HAVE_PTHREAD_H  #include <stdlib.h>
25  #include <pthread.h>  #include <PCSC/pcsclite.h>
26  #endif  #include <PCSC/ifdhandler.h>
27    #include <PCSC/reader.h>
28    
29  #include "pcscdefines.h"  #include "ccid.h"
30  #include "ifdhandler.h"  #include "defs.h"
31    #include "ccid_ifdhandler.h"
32  #include "config.h"  #include "config.h"
33  #include "debug.h"  #include "debug.h"
 #include "defs.h"  
34  #include "utils.h"  #include "utils.h"
 #include "ccid_usb.h"  
35  #include "commands.h"  #include "commands.h"
36    #include "towitoko/atr.h"
37    #include "towitoko/pps.h"
38    #include "parser.h"
39    
40    #ifdef HAVE_PTHREAD
41    #include <pthread.h>
42    #endif
43    
44    /* Array of structures to hold the ATR and other state value of each slot */
45    static CcidDesc CcidSlots[CCID_DRIVER_MAX_READERS];
46    
47    /* global mutex */
48    #ifdef HAVE_PTHREAD
49    static pthread_mutex_t ifdh_context_mutex = PTHREAD_MUTEX_INITIALIZER;
50    #endif
51    
52    int LogLevel = DEBUG_LEVEL_CRITICAL | DEBUG_LEVEL_INFO;
53    int DriverOptions = 0;
54    static int DebugInitialized = FALSE;
55    
56    /* local functions */
57    static void init_driver(void);
58    static void extra_egt(ATR_t *atr, _ccid_descriptor *ccid_desc, DWORD Protocol);
59    static char find_baud_rate(unsigned int baudrate, unsigned int *list);
60    static unsigned int T0_card_timeout(double f, double d, int TC1, int TC2,
61            int clock_frequency);
62    static unsigned int T1_card_timeout(double f, double d, int TC1, int BWI,
63            int CWI, int clock_frequency);
64    
65  // Array of structures to hold the ATR and other state value of each slot  
66  static CcidDesc CcidSlots[PCSCLITE_MAX_CHANNELS];  RESPONSECODE IFDHCreateChannelByName(DWORD Lun, LPTSTR lpcDevice)
67    {
68            RESPONSECODE return_value = IFD_SUCCESS;
69            int reader_index;
70    
71            if (! DebugInitialized)
72                    init_driver();
73    
74            DEBUG_INFO3("lun: %X, device: %s", Lun, lpcDevice);
75    
76            if (-1 == (reader_index = GetNewReaderIndex(Lun)))
77                    return IFD_COMMUNICATION_ERROR;
78    
79            /* Reset ATR buffer */
80            CcidSlots[reader_index].nATRLength = 0;
81            *CcidSlots[reader_index].pcATRBuffer = '\0';
82    
83            /* Reset PowerFlags */
84            CcidSlots[reader_index].bPowerFlags = POWERFLAGS_RAZ;
85    
86    #ifdef HAVE_PTHREAD
87            pthread_mutex_lock(&ifdh_context_mutex);
88    #endif
89    
90            if (OpenPortByName(reader_index, lpcDevice) != STATUS_SUCCESS)
91            {
92                    DEBUG_CRITICAL("failed");
93                    return_value = IFD_COMMUNICATION_ERROR;
94    
95                    /* release the allocated reader_index */
96                    ReleaseReaderIndex(reader_index);
97            }
98            else
99                    /* Maybe we have a special treatment for this reader */
100                    ccid_open_hack(reader_index);
101    
102    #ifdef HAVE_PTHREAD
103            pthread_mutex_unlock(&ifdh_context_mutex);
104    #endif
105    
106            return return_value;
107    } /* IFDHCreateChannelByName */
108    
109    
110  RESPONSECODE IFDHCreateChannel(DWORD Lun, DWORD Channel)  RESPONSECODE IFDHCreateChannel(DWORD Lun, DWORD Channel)
# Line 72  RESPONSECODE IFDHCreateChannel(DWORD Lun Line 143  RESPONSECODE IFDHCreateChannel(DWORD Lun
143           * IFD_SUCCESS IFD_COMMUNICATION_ERROR           * IFD_SUCCESS IFD_COMMUNICATION_ERROR
144           */           */
145          RESPONSECODE return_value = IFD_SUCCESS;          RESPONSECODE return_value = IFD_SUCCESS;
146            int reader_index;
147    
148            if (! DebugInitialized)
149                    init_driver();
150    
151          DEBUG_INFO2("Entering IFDHCreateChannel (lun: %X)", Lun);          DEBUG_INFO2("lun: %X", Lun);
152    
153          if (CheckLun(Lun))          if (-1 == (reader_index = GetNewReaderIndex(Lun)))
154                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
155    
156          // Reset ATR buffer          /* Reset ATR buffer */
157          CcidSlots[LunToReaderIndex(Lun)].nATRLength = 0;          CcidSlots[reader_index].nATRLength = 0;
158          *CcidSlots[LunToReaderIndex(Lun)].pcATRBuffer = '\0';          *CcidSlots[reader_index].pcATRBuffer = '\0';
159    
160          // Reset PowerFlags          /* Reset PowerFlags */
161          CcidSlots[LunToReaderIndex(Lun)].bPowerFlags = POWERFLAGS_RAZ;          CcidSlots[reader_index].bPowerFlags = POWERFLAGS_RAZ;
162    
163    #ifdef HAVE_PTHREAD
164            pthread_mutex_lock(&ifdh_context_mutex);
165    #endif
166    
167          if (OpenUSB(Lun, Channel) != STATUS_SUCCESS)          if (OpenPort(reader_index, Channel) != STATUS_SUCCESS)
168          {          {
169                  DEBUG_CRITICAL("OpenReader failed");                  DEBUG_CRITICAL("failed");
170                  return_value = IFD_COMMUNICATION_ERROR;                  return_value = IFD_COMMUNICATION_ERROR;
171    
172                    /* release the allocated reader_index */
173                    ReleaseReaderIndex(reader_index);
174          }          }
175            else
176                    /* Maybe we have a special treatment for this reader */
177                    ccid_open_hack(reader_index);
178    
179    #ifdef HAVE_PTHREAD
180            pthread_mutex_unlock(&ifdh_context_mutex);
181    #endif
182    
183          return return_value;          return return_value;
184  } /* IFDHCreateChannel */  } /* IFDHCreateChannel */
# Line 107  RESPONSECODE IFDHCloseChannel(DWORD Lun) Line 196  RESPONSECODE IFDHCloseChannel(DWORD Lun)
196           *           *
197           * IFD_SUCCESS IFD_COMMUNICATION_ERROR           * IFD_SUCCESS IFD_COMMUNICATION_ERROR
198           */           */
199            int reader_index;
200    
201          DEBUG_INFO2("entering IFDHCloseChannel (lun: %X)", Lun);          DEBUG_INFO2("lun: %X", Lun);
202    
203          if (CheckLun(Lun))          if (-1 == (reader_index = LunToReaderIndex(Lun)))
204                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
205    
206          CmdPowerOff(Lun);          /* Restore the default timeout
207          // No reader status check, if it failed, what can you do ? :)           * No need to wait too long if the reader disapeared */
208            get_ccid_descriptor(reader_index)->readTimeout = DEFAULT_COM_READ_TIMEOUT;
209    
210          CloseUSB(Lun);          (void)CmdPowerOff(reader_index);
211            /* No reader status check, if it failed, what can you do ? :) */
212    
213    #ifdef HAVE_PTHREAD
214            pthread_mutex_lock(&ifdh_context_mutex);
215    #endif
216    
217            (void)ClosePort(reader_index);
218            ReleaseReaderIndex(reader_index);
219    
220    #ifdef HAVE_PTHREAD
221            pthread_mutex_unlock(&ifdh_context_mutex);
222    #endif
223    
224          return IFD_SUCCESS;          return IFD_SUCCESS;
225  } /* IFDHCloseChannel */  } /* IFDHCloseChannel */
# Line 142  RESPONSECODE IFDHGetCapabilities(DWORD L Line 245  RESPONSECODE IFDHGetCapabilities(DWORD L
245           *           *
246           * IFD_SUCCESS IFD_ERROR_TAG           * IFD_SUCCESS IFD_ERROR_TAG
247           */           */
248            int reader_index;
249    
250          DEBUG_INFO2("entering IFDHGetCapabilities (lun: %X)", Lun);          DEBUG_INFO3("lun: %X, tag: 0x%X", Lun, Tag);
251    
252          if (CheckLun(Lun))          if (-1 == (reader_index = LunToReaderIndex(Lun)))
253                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
254    
255          switch (Tag)          switch (Tag)
256          {          {
257                  case TAG_IFD_ATR:                  case TAG_IFD_ATR:
258                          // If Length is not zero, powerICC has been performed.                  case SCARD_ATTR_ATR_STRING:
259                          // Otherwise, return NULL pointer                          /* If Length is not zero, powerICC has been performed.
260                          // Buffer size is stored in *Length                           * Otherwise, return NULL pointer
261                          *Length = (*Length < CcidSlots[LunToReaderIndex(Lun)]                           * Buffer size is stored in *Length */
262                                  .nATRLength) ?                          *Length = (*Length < CcidSlots[reader_index].nATRLength) ?
263                                  *Length : CcidSlots[LunToReaderIndex(Lun)]                                  *Length : CcidSlots[reader_index].nATRLength;
                                 .nATRLength;  
264    
265                          if (*Length)                          if (*Length)
266                                  memcpy(Value, CcidSlots[LunToReaderIndex(Lun)]                                  memcpy(Value, CcidSlots[reader_index].pcATRBuffer, *Length);
                                         .pcATRBuffer, *Length);  
267                          break;                          break;
268    
269    #ifdef HAVE_PTHREAD
270                  case TAG_IFD_SIMULTANEOUS_ACCESS:                  case TAG_IFD_SIMULTANEOUS_ACCESS:
271                          if (*Length >= 1)                          if (*Length >= 1)
272                          {                          {
273                                  *Length = 1;                                  *Length = 1;
274                                  *Value = PCSCLITE_MAX_CHANNELS;                                  *Value = CCID_DRIVER_MAX_READERS;
275                            }
276                            break;
277    
278                    case TAG_IFD_THREAD_SAFE:
279                            if (*Length >= 1)
280                            {
281                                    *Length = 1;
282                                    *Value = 1; /* Can talk to multiple readers at the same time */
283                          }                          }
284                          break;                          break;
285    #endif
286    
287                  case TAG_IFD_SLOTS_NUMBER:                  case TAG_IFD_SLOTS_NUMBER:
288                          if (*Length >= 1)                          if (*Length >= 1)
289                          {                          {
290                                  *Length = 1;                                  *Length = 1;
291                                  *Value = 1; /* One slot only */                                  *Value = 1 + get_ccid_descriptor(reader_index) -> bMaxSlotIndex;
292                                    DEBUG_COMM2("Reader supports %d slots", *Value);
293                            }
294                            break;
295    
296                    case TAG_IFD_SLOT_THREAD_SAFE:
297                            if (*Length >= 1)
298                            {
299                                    *Length = 1;
300                                    *Value = 0; /* Can NOT talk to multiple slots at the same time */
301                          }                          }
302                          break;                          break;
303    
304                  default:                  default:
305                          return IFD_ERROR_TAG;                          return IFD_ERROR_TAG;
306          }          }
307    
308          return IFD_SUCCESS;          return IFD_SUCCESS;
309  } /* IFDHGetCapabilities */  } /* IFDHGetCapabilities */
310    
311    
312  RESPONSECODE IFDHSetCapabilities(DWORD Lun, DWORD Tag,  RESPONSECODE IFDHSetCapabilities(DWORD Lun, DWORD Tag,
313          DWORD Length, PUCHAR Value)          /*@unused@*/ DWORD Length, /*@unused@*/ PUCHAR Value)
314  {  {
315          /*          /*
316           * This function should set the slot/card capabilities for a           * This function should set the slot/card capabilities for a
# Line 207  RESPONSECODE IFDHSetCapabilities(DWORD L Line 329  RESPONSECODE IFDHSetCapabilities(DWORD L
329           * IFD_ERROR_VALUE_READ_ONLY           * IFD_ERROR_VALUE_READ_ONLY
330           */           */
331    
332          // By default, say it worked          /* By default, say it worked */
333    
334          DEBUG_PERIODIC2("entering IFDHSetCapabilities (lun: %X)", Lun);          DEBUG_INFO3("lun: %X, tag: 0x%X", Lun, Tag);
335    
336          /* if (CheckLun(Lun))          /* if (CheckLun(Lun))
337                  return IFD_COMMUNICATION_ERROR; */                  return IFD_COMMUNICATION_ERROR; */
338    
339          return IFD_SUCCESS;          return IFD_NOT_SUPPORTED;
340  } /* IFDHSetCapabilities */  } /* IFDHSetCapabilities */
341    
342    
# Line 225  RESPONSECODE IFDHSetProtocolParameters(D Line 347  RESPONSECODE IFDHSetProtocolParameters(D
347           * This function should set the PTS of a particular card/slot using           * This function should set the PTS of a particular card/slot using
348           * the three PTS parameters sent           * the three PTS parameters sent
349           *           *
350           * Protocol - 0 .... 14 T=0 .... T=14 Flags - Logical OR of possible           * Protocol - 0 .... 14 T=0 .... T=14
351           * values: IFD_NEGOTIATE_PTS1 IFD_NEGOTIATE_PTS2 IFD_NEGOTIATE_PTS3 to           * Flags - Logical OR of possible values:
352           * determine which PTS values to negotiate. PTS1,PTS2,PTS3 - PTS           *  IFD_NEGOTIATE_PTS1
353           * Values.           *  IFD_NEGOTIATE_PTS2
354             *  IFD_NEGOTIATE_PTS3
355             * to determine which PTS values to negotiate.
356             * PTS1,PTS2,PTS3 - PTS Values.
357           *           *
358           * returns:           * returns:
359           *           *  IFD_SUCCESS
360           * IFD_SUCCESS IFD_ERROR_PTS_FAILURE IFD_COMMUNICATION_ERROR           *  IFD_ERROR_PTS_FAILURE
361           * IFD_PROTOCOL_NOT_SUPPORTED           *  IFD_COMMUNICATION_ERROR
362             *  IFD_PROTOCOL_NOT_SUPPORTED
363           */           */
364    
365          DEBUG_INFO2("entering IFDHSetProtocolParameters (lun: %X)", Lun);          BYTE pps[PPS_MAX_LENGTH];
366            ATR_t atr;
367            unsigned int len;
368            int convention;
369            int reader_index;
370    
371            /* Set ccid desc params */
372            CcidDesc *ccid_slot;
373            _ccid_descriptor *ccid_desc;
374    
375          /* if (CheckLun(Lun))          DEBUG_INFO3("lun: %X, protocol T=%d", Lun, Protocol-1);
376                  return IFD_COMMUNICATION_ERROR; */  
377            if (-1 == (reader_index = LunToReaderIndex(Lun)))
378                    return IFD_COMMUNICATION_ERROR;
379    
380            /* Set to zero buffer */
381            memset(pps, 0, sizeof(pps));
382            memset(&atr, 0, sizeof(atr));
383    
384            /* Get ccid params */
385            ccid_slot = get_ccid_slot(reader_index);
386            ccid_desc = get_ccid_descriptor(reader_index);
387    
388            /* Do not send CCID command SetParameters or PPS to the CCID
389             * The CCID will do this himself */
390            if (ccid_desc->dwFeatures & CCID_CLASS_AUTO_PPS_PROP)
391                    return IFD_SUCCESS;
392    
393            /* Get ATR of the card */
394            ATR_InitFromArray(&atr, ccid_slot->pcATRBuffer, ccid_slot->nATRLength);
395    
396            /* Apply Extra EGT patch for bogus cards */
397            extra_egt(&atr, ccid_desc, Protocol);
398    
399            if (SCARD_PROTOCOL_T0 == Protocol)
400                    pps[1] |= ATR_PROTOCOL_TYPE_T0;
401            else
402                    if (SCARD_PROTOCOL_T1 == Protocol)
403                            pps[1] |= ATR_PROTOCOL_TYPE_T1;
404                    else
405                            return IFD_PROTOCOL_NOT_SUPPORTED;
406    
407            /* TA2 present -> specific mode */
408            if (atr.ib[1][ATR_INTERFACE_BYTE_TA].present)
409            {
410                    if (pps[1] != (atr.ib[1][ATR_INTERFACE_BYTE_TA].value & 0x0F))
411                    {
412                            /* wrong protocol */
413                            DEBUG_COMM3("Specific mode in T=%d and T=%d requested",
414                                    atr.ib[1][ATR_INTERFACE_BYTE_TA].value & 0x0F, pps[1]);
415    
416                            return IFD_PROTOCOL_NOT_SUPPORTED;
417                    }
418            }
419    
420            /* TCi (i>2) indicates CRC instead of LRC */
421            if (SCARD_PROTOCOL_T1 == Protocol)
422            {
423                    t1_state_t *t1 = &(ccid_slot -> t1);
424                    int i;
425    
426                    /* TCi (i>2) present? */
427                    for (i=2; i<ATR_MAX_PROTOCOLS; i++)
428                            if (atr.ib[i][ATR_INTERFACE_BYTE_TC].present)
429                            {
430                                    if (0 == atr.ib[i][ATR_INTERFACE_BYTE_TC].value)
431                                    {
432                                            DEBUG_COMM("Use LRC");
433                                            t1_set_param(t1, IFD_PROTOCOL_T1_CHECKSUM_LRC, 0);
434                                    }
435                                    else
436                                            if (1 == atr.ib[i][ATR_INTERFACE_BYTE_TC].value)
437                                            {
438                                                    DEBUG_COMM("Use CRC");
439                                                    t1_set_param(t1, IFD_PROTOCOL_T1_CHECKSUM_CRC, 0);
440                                            }
441                                            else
442                                                    DEBUG_COMM2("Wrong value for TCi: %d",
443                                                            atr.ib[i][ATR_INTERFACE_BYTE_TC].value);
444    
445                                    /* only the first TCi (i>2) must be used */
446                                    break;
447                            }
448            }
449    
450            /* PTS1? */
451            if (Flags & IFD_NEGOTIATE_PTS1)
452            {
453                    /* just use the value passed in argument */
454                    pps[1] |= 0x10; /* PTS1 presence */
455                    pps[2] = PTS1;
456            }
457            else
458            {
459                    /* TA1 present */
460                    if (atr.ib[0][ATR_INTERFACE_BYTE_TA].present)
461                    {
462                            unsigned int card_baudrate;
463                            unsigned int default_baudrate;
464                            double f, d;
465    
466                            ATR_GetParameter(&atr, ATR_PARAMETER_D, &d);
467                            ATR_GetParameter(&atr, ATR_PARAMETER_F, &f);
468    
469                            /* Baudrate = f x D/F */
470                            card_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock
471                                    * d / f);
472    
473                            default_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock
474                                    * ATR_DEFAULT_D / ATR_DEFAULT_F);
475    
476                            /* if the card does not try to lower the default speed */
477                            if ((card_baudrate > default_baudrate)
478                                    /* and the reader is fast enough */
479                                    && (card_baudrate <= ccid_desc->dwMaxDataRate))
480                            {
481                                    /* the reader has no baud rates table */
482                                    if ((NULL == ccid_desc->arrayOfSupportedDataRates)
483                                            /* or explicitely support it */
484                                            || find_baud_rate(card_baudrate,
485                                                    ccid_desc->arrayOfSupportedDataRates))
486                                    {
487                                            pps[1] |= 0x10; /* PTS1 presence */
488                                            pps[2] = atr.ib[0][ATR_INTERFACE_BYTE_TA].value;
489    
490                                            DEBUG_COMM2("Set speed to %d bauds", card_baudrate);
491                                    }
492                                    else
493                                            DEBUG_COMM2("Reader does not support %d bauds",
494                                                    card_baudrate);
495                            }
496                    }
497            }
498    
499            /* PTS2? */
500            if (Flags & IFD_NEGOTIATE_PTS2)
501            {
502                    pps[1] |= 0x20; /* PTS2 presence */
503                    pps[3] = PTS2;
504            }
505    
506            /* PTS3? */
507            if (Flags & IFD_NEGOTIATE_PTS3)
508            {
509                    pps[1] |= 0x40; /* PTS3 presence */
510                    pps[4] = PTS3;
511            }
512    
513            /* Generate PPS */
514            pps[0] = 0xFF;
515    
516            /* Automatic PPS made by the ICC? */
517            if ((! (ccid_desc->dwFeatures & CCID_CLASS_AUTO_PPS_CUR))
518                    /* TA2 absent: negociable mode */
519                    && (! atr.ib[1][ATR_INTERFACE_BYTE_TA].present))
520            {
521                    int default_protocol;
522    
523                    if (ATR_MALFORMED == ATR_GetDefaultProtocol(&atr, &default_protocol))
524                            return IFD_PROTOCOL_NOT_SUPPORTED;
525    
526                    /* if the requested protocol is not the default one
527                     * or a TA1/PPS1 is present */
528                    if (((pps[1] & 0x0F) != default_protocol) || (PPS_HAS_PPS1(pps)))
529                            if (PPS_Exchange(reader_index, pps, &len, &pps[2]) != PPS_OK)
530                            {
531                                    DEBUG_INFO("PPS_Exchange Failed");
532    
533                                    return IFD_ERROR_PTS_FAILURE;
534                            }
535            }
536    
537            /* Now we must set the reader parameters */
538            ATR_GetConvention(&atr, &convention);
539    
540            /* specific mode and implicit parameters? (b5 of TA2) */
541            if (atr.ib[1][ATR_INTERFACE_BYTE_TA].present
542                    && (atr.ib[1][ATR_INTERFACE_BYTE_TA].value & 0x10))
543                    return IFD_COMMUNICATION_ERROR;
544    
545            /* T=1 */
546            if (SCARD_PROTOCOL_T1 == Protocol)
547            {
548                    BYTE param[] = {
549                            0x11,   /* Fi/Di                */
550                            0x10,   /* TCCKS                */
551                            0x00,   /* GuardTime    */
552                            0x4D,   /* BWI/CWI              */
553                            0x00,   /* ClockStop    */
554                            0x20,   /* IFSC                 */
555                            0x00    /* NADValue             */
556                    };
557                    int i;
558                    t1_state_t *t1 = &(ccid_slot -> t1);
559                    RESPONSECODE ret;
560                    double f, d;
561    
562                    /* TA1 is not default */
563                    if (PPS_HAS_PPS1(pps))
564                            param[0] = pps[2];
565    
566                    /* CRC checksum? */
567                    if (2 == t1->rc_bytes)
568                            param[1] |= 0x01;
569    
570                    /* the CCID should ignore this bit */
571                    if (ATR_CONVENTION_INVERSE == convention)
572                            param[1] |= 0x02;
573    
574                    /* get TC1 Extra guard time */
575                    if (atr.ib[0][ATR_INTERFACE_BYTE_TC].present)
576                            param[2] = atr.ib[0][ATR_INTERFACE_BYTE_TC].value;
577    
578                    /* TBi (i>2) present? BWI/CWI */
579                    for (i=2; i<ATR_MAX_PROTOCOLS; i++)
580                            if (atr.ib[i][ATR_INTERFACE_BYTE_TB].present)
581                            {
582                                    DEBUG_COMM3("BWI/CWI (TB%d) present: 0x%02X", i+1,
583                                            atr.ib[i][ATR_INTERFACE_BYTE_TB].value);
584                                    param[3] = atr.ib[i][ATR_INTERFACE_BYTE_TB].value;
585    
586                                    /* only the first TBi (i>2) must be used */
587                                    break;
588                            }
589    
590                    /* compute communication timeout */
591                    ATR_GetParameter(&atr, ATR_PARAMETER_F, &f);
592                    ATR_GetParameter(&atr, ATR_PARAMETER_D, &d);
593                    ccid_desc->readTimeout = T1_card_timeout(f, d, param[2],
594                            (param[3] & 0xF0) >> 4 /* BWI */, param[3] & 0x0F /* CWI */,
595                            ccid_desc->dwDefaultClock);
596    
597                    DEBUG_COMM2("Timeout: %d seconds", ccid_desc->readTimeout);
598    
599                    ret = SetParameters(reader_index, 1, sizeof(param), param);
600                    if (IFD_SUCCESS != ret)
601                            return ret;
602            }
603            else
604            /* T=0 */
605            {
606                    BYTE param[] = {
607                            0x11,   /* Fi/Di                        */
608                            0x00,   /* TCCKS                        */
609                            0x00,   /* GuardTime            */
610                            0x0A,   /* WaitingInteger       */
611                            0x00    /* ClockStop            */
612                    };
613                    RESPONSECODE ret;
614                    double f, d;
615    
616                    /* TA1 is not default */
617                    if (PPS_HAS_PPS1(pps))
618                            param[0] = pps[2];
619    
620                    if (ATR_CONVENTION_INVERSE == convention)
621                            param[1] |= 0x02;
622    
623                    /* get TC1 Extra guard time */
624                    if (atr.ib[0][ATR_INTERFACE_BYTE_TC].present)
625                            param[2] = atr.ib[0][ATR_INTERFACE_BYTE_TC].value;
626    
627                    /* TC2 WWT */
628                    if (atr.ib[1][ATR_INTERFACE_BYTE_TC].present)
629                            param[3] = atr.ib[1][ATR_INTERFACE_BYTE_TC].value;
630    
631                    /* compute communication timeout */
632                    ATR_GetParameter(&atr, ATR_PARAMETER_F, &f);
633                    ATR_GetParameter(&atr, ATR_PARAMETER_D, &d);
634    
635                    ccid_desc->readTimeout = T0_card_timeout(f, d, param[2] /* TC1 */,
636                            param[3] /* TC2 */, ccid_desc->dwDefaultClock);
637    
638                    DEBUG_COMM2("Communication timeout: %d seconds",
639                            ccid_desc->readTimeout);
640    
641                    ret = SetParameters(reader_index, 0, sizeof(param), param);
642                    if (IFD_SUCCESS != ret)
643                            return ret;
644            }
645    
646            /* set IFSC & IFSD in T=1 */
647            if (SCARD_PROTOCOL_T1 == Protocol)
648            {
649                    t1_state_t *t1 = &(ccid_slot -> t1);
650                    int i;
651    
652                    /* TAi (i>2) present? */
653                    for (i=2; i<ATR_MAX_PROTOCOLS; i++)
654                            if (atr.ib[i][ATR_INTERFACE_BYTE_TA].present)
655                            {
656                                    DEBUG_COMM3("IFSC (TA%d) present: %d", i+1,
657                                            atr.ib[i][ATR_INTERFACE_BYTE_TA].value);
658                                    t1_set_param(t1, IFD_PROTOCOL_T1_IFSC,
659                                            atr.ib[i][ATR_INTERFACE_BYTE_TA].value);
660    
661                                    /* only the first TAi (i>2) must be used */
662                                    break;
663                            }
664    
665                    /* IFSD not negociated by the reader? */
666                    if (! (ccid_desc->dwFeatures & CCID_CLASS_AUTO_IFSD))
667                    {
668                            DEBUG_COMM2("Negociate IFSD at %d", ccid_desc -> dwMaxIFSD);
669                            if (t1_negociate_ifsd(t1, 0, ccid_desc -> dwMaxIFSD) < 0)
670                                    return IFD_COMMUNICATION_ERROR;
671                    }
672                    t1_set_param(t1, IFD_PROTOCOL_T1_IFSD, ccid_desc -> dwMaxIFSD);
673    
674                    DEBUG_COMM3("T=1: IFSC=%d, IFSD=%d", t1->ifsc, t1->ifsd);
675            }
676    
677          return IFD_SUCCESS;          return IFD_SUCCESS;
678  } /* IFDHSetProtocolParameters */  } /* IFDHSetProtocolParameters */
# Line 284  RESPONSECODE IFDHPowerICC(DWORD Lun, DWO Line 717  RESPONSECODE IFDHPowerICC(DWORD Lun, DWO
717           * IFD_NOT_SUPPORTED           * IFD_NOT_SUPPORTED
718           */           */
719    
720          int nlength;          unsigned int nlength;
721          RESPONSECODE return_value = IFD_SUCCESS;          RESPONSECODE return_value = IFD_SUCCESS;
722          unsigned char pcbuffer[RESP_BUF_SIZE];          unsigned char pcbuffer[RESP_BUF_SIZE];
723            int reader_index;
724    
725          DEBUG_INFO2("entering IFDHPowerICC (lun: %X)", Lun);          DEBUG_INFO2("lun: %X", Lun);
726    
727          // By default, assume it won't work :)          /* By default, assume it won't work :) */
728          *AtrLength = 0;          *AtrLength = 0;
729    
730          if (CheckLun(Lun))          if (-1 == (reader_index = LunToReaderIndex(Lun)))
731                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
732    
733          switch (Action)          switch (Action)
734          {          {
735                    case IFD_POWER_DOWN:
736                            /* Clear ATR buffer */
737                            CcidSlots[reader_index].nATRLength = 0;
738                            *CcidSlots[reader_index].pcATRBuffer = '\0';
739    
740                            /* Memorise the request */
741                            CcidSlots[reader_index].bPowerFlags |= MASK_POWERFLAGS_PDWN;
742    
743                            /* send the command */
744                            if (IFD_SUCCESS != CmdPowerOff(reader_index))
745                            {
746                                    DEBUG_CRITICAL("PowerDown failed");
747                                    return_value = IFD_ERROR_POWER_ACTION;
748                                    goto end;
749                            }
750    
751                            /* clear T=1 context */
752                            t1_release(&(get_ccid_slot(reader_index) -> t1));
753                            break;
754    
755                  case IFD_POWER_UP:                  case IFD_POWER_UP:
756                  case IFD_RESET:                  case IFD_RESET:
757                          nlength = sizeof(pcbuffer);                          nlength = sizeof(pcbuffer);
758                          if (CmdPowerOn(Lun, &nlength, pcbuffer) != IFD_SUCCESS)                          if (CmdPowerOn(reader_index, &nlength, pcbuffer) != IFD_SUCCESS)
759                          {                          {
760                                  DEBUG_CRITICAL("PowerUp failed");                                  DEBUG_CRITICAL("PowerUp failed");
761                                  return_value = IFD_ERROR_POWER_ACTION;                                  return_value = IFD_ERROR_POWER_ACTION;
762                                  goto end;                                  goto end;
763                          }                          }
764    
765                          // Power up successful, set state variable to memorise it                          /* Power up successful, set state variable to memorise it */
766                          CcidSlots[LunToReaderIndex(Lun)].bPowerFlags |=                          CcidSlots[reader_index].bPowerFlags |= MASK_POWERFLAGS_PUP;
767                                  MASK_POWERFLAGS_PUP;                          CcidSlots[reader_index].bPowerFlags &= ~MASK_POWERFLAGS_PDWN;
                         CcidSlots[LunToReaderIndex(Lun)].bPowerFlags &=  
                                 ~MASK_POWERFLAGS_PDWN;  
768    
769                          // Reset is returned, even if TCK is wrong                          /* Reset is returned, even if TCK is wrong */
770                          CcidSlots[LunToReaderIndex(Lun)].nATRLength = *AtrLength =                          CcidSlots[reader_index].nATRLength = *AtrLength =
771                                  (nlength < MAX_ATR_SIZE) ? nlength : MAX_ATR_SIZE;                                  (nlength < MAX_ATR_SIZE) ? nlength : MAX_ATR_SIZE;
772                          memcpy(Atr, pcbuffer, *AtrLength);                          memcpy(Atr, pcbuffer, *AtrLength);
773                          memcpy(CcidSlots[LunToReaderIndex(Lun)].pcATRBuffer,                          memcpy(CcidSlots[reader_index].pcATRBuffer, pcbuffer, *AtrLength);
                                 pcbuffer, *AtrLength);  
                         break;  
774    
775                  case IFD_POWER_DOWN:                          /* initialise T=1 context */
776                          // Clear ATR buffer                          t1_init(&(get_ccid_slot(reader_index) -> t1), reader_index);
                         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);  
777                          break;                          break;
778    
779                  default:                  default:
780                          DEBUG_CRITICAL("IFDHPowerICC Action not supported");                          DEBUG_CRITICAL("Action not supported");
781                          return_value = IFD_NOT_SUPPORTED;                          return_value = IFD_NOT_SUPPORTED;
782          }          }
783  end:  end:
# Line 346  end: Line 788  end:
788    
789  RESPONSECODE IFDHTransmitToICC(DWORD Lun, SCARD_IO_HEADER SendPci,  RESPONSECODE IFDHTransmitToICC(DWORD Lun, SCARD_IO_HEADER SendPci,
790          PUCHAR TxBuffer, DWORD TxLength,          PUCHAR TxBuffer, DWORD TxLength,
791          PUCHAR RxBuffer, PDWORD RxLength, PSCARD_IO_HEADER RecvPci)          PUCHAR RxBuffer, PDWORD RxLength, /*@unused@*/ PSCARD_IO_HEADER RecvPci)
792  {  {
793          /*          /*
794           * This function performs an APDU exchange with the card/slot           * This function performs an APDU exchange with the card/slot
# Line 382  RESPONSECODE IFDHTransmitToICC(DWORD Lun Line 824  RESPONSECODE IFDHTransmitToICC(DWORD Lun
824           * IFD_ICC_NOT_PRESENT IFD_PROTOCOL_NOT_SUPPORTED           * IFD_ICC_NOT_PRESENT IFD_PROTOCOL_NOT_SUPPORTED
825           */           */
826    
827          RESPONSECODE return_value = IFD_SUCCESS;        // Assume it will work          RESPONSECODE return_value;
828          char protocol;          unsigned int rx_length;
829            int reader_index;
830    
831          DEBUG_INFO2("entering IFDHTransmitToICC (lun: %X)", Lun);          DEBUG_INFO2("lun: %X", Lun);
832    
833          if (CheckLun(Lun))          if (-1 == (reader_index = LunToReaderIndex(Lun)))
834                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
835    
836          protocol = SendPci.Protocol;          rx_length = *RxLength;
837            return_value = CmdXfrBlock(reader_index, TxLength, TxBuffer, &rx_length,
838          // if the reader is in EMV mode use ISO_EXCHANGE instead of ISO_INPUT                  RxBuffer, SendPci.Protocol);
839          // and ISO_OUTPUT. This is done with T=1 protocol          *RxLength = rx_length;
         if (CcidSlots[LunToReaderIndex(Lun)].bPowerFlags & MASK_POWERFLAGS_EMV)  
                 protocol = T_1;  
   
         // Check if command is going to fit in buffer  
         if (TxLength > CMD_BUF_SIZE)  
         {  
                 // Buffer too small, send an error  
                 return_value = IFD_COMMUNICATION_ERROR;  
                 goto clean_up_and_return;  
         }  
   
         switch (protocol)  
         {  
                 case T_0:  
                         // Size should be command + one byte of length for  
                         // an outgoing TPDU (CLA, INS, P1, P2, P3)  
                         if (TxLength == (ISO_CMD_SIZE + ISO_LENGTH_SIZE))  
                         {  
 printf("%s %d\n", __FILE__, __LINE__);  
                                 return_value = CmdXfrBlock(Lun, TxLength, TxBuffer, RxLength,  
                                         RxBuffer);  
                         }  
                         else  
                         {  
                                 // just (CLA, INS, P1, P2) for an APDU  
                                 if (TxLength == ISO_CMD_SIZE)  
                                 {  
 printf("%s %d\n", __FILE__, __LINE__);  
                                         return_value = CmdXfrBlock(Lun, TxLength, TxBuffer,  
                                                         RxLength, RxBuffer);  
                                 }  
                                 else  
                                 {  
                                         DWORD ntestlength;  
   
 printf("%s %d %ld %d\n", __FILE__, __LINE__, TxLength, ISO_CMD_SIZE + ISO_LENGTH_SIZE);  
                                         if (TxLength > (ISO_CMD_SIZE + ISO_LENGTH_SIZE))  
                                         {  
                                                 // Check length to see if it is a full APDU or a TPDU  
                                                 ntestlength = TxBuffer[ISO_OFFSET_LENGTH] +  
                                                         ISO_CMD_SIZE + ISO_LENGTH_SIZE;  
   
 printf("%s %d %ld\n", __FILE__, __LINE__, ntestlength);  
                                                 if (TxLength == (ntestlength + ISO_LENGTH_SIZE))  
                                                 {  
                                                         DWORD old_RxLength = *RxLength;  
   
                                                         // TxBuffer holds a proper APDU  
                                                         return_value = CmdXfrBlock(Lun, TxLength, TxBuffer, RxLength, RxBuffer);  
   
                                                         // Get Response  
                                                         if ((return_value == IFD_SUCCESS) &&  
                                                                 (*RxLength == 2))  
                                                         {  
                                                                 TxBuffer[0] = 0x00;  
                                                                 TxBuffer[1] = 0xC0;  
                                                                 TxBuffer[2] = 0x00;  
                                                                 TxBuffer[3] = 0x00;  
                                                                 TxBuffer[4] = RxBuffer[1];  
                                                                 *RxLength = old_RxLength;  
                                                                 TxLength = 5;  
   
                                                                 return_value = CmdXfrBlock(Lun, TxLength, TxBuffer, RxLength, RxBuffer);  
                                                         }  
                                                 }  
                                                 else  
                                                 {  
                                                         if (TxLength > (ntestlength + ISO_LENGTH_SIZE))  
                                                         {  
 printf("%s %d\n", __FILE__, __LINE__);  
                                                                 // Data are too long  
                                                                 return_value = IFD_COMMUNICATION_ERROR;  
   
                                                                 goto clean_up_and_return;  
                                                         }  
                                                         else  
                                                         {  
 printf("%s %d\n", __FILE__, __LINE__);  
                                                                 // TxBuffer holds a proper TPDU  
                                                                 return_value = CmdXfrBlock(Lun, TxLength, TxBuffer, RxLength, RxBuffer);  
                                                         }  
                                                 }  
                                         }  
                                         else  
                                         {  
 printf("%s %d\n", __FILE__, __LINE__);  
                                                 // TxBuffer holds too little data to form an APDU+length  
                                                 return_value = IFD_COMMUNICATION_ERROR;  
   
                                                 goto clean_up_and_return;  
                                         }  
                                 }  
                         }  
                         break;  
   
                 case T_1:  
                         return_value = CmdXfrBlock(Lun, TxLength, TxBuffer, RxLength,  
                                 RxBuffer);  
                         break;  
   
                 default:  
                         return_value = IFD_PROTOCOL_NOT_SUPPORTED;  
         }  
   
 clean_up_and_return:  
         if (return_value != IFD_SUCCESS)  
                 *RxLength = 0;  
840    
841          return return_value;          return return_value;
842  } /* IFDHTransmitToICC */  } /* IFDHTransmitToICC */
843    
844    
845  RESPONSECODE IFDHControl(DWORD Lun, PUCHAR TxBuffer,  RESPONSECODE IFDHControl(DWORD Lun, DWORD dwControlCode, PUCHAR TxBuffer,
846          DWORD TxLength, PUCHAR RxBuffer, PDWORD RxLength)          DWORD TxLength, PUCHAR RxBuffer, DWORD RxLength, PDWORD pdwBytesReturned)
847  {  {
848          /*          /*
849           * This function performs a data exchange with the reader (not the           * This function performs a data exchange with the reader (not the
# Line 523  RESPONSECODE IFDHControl(DWORD Lun, PUCH Line 859  RESPONSECODE IFDHControl(DWORD Lun, PUCH
859           *           *
860           * Notes: RxLength should be zero on error.           * Notes: RxLength should be zero on error.
861           */           */
862            RESPONSECODE return_value = IFD_COMMUNICATION_ERROR;
863            int reader_index;
864    
865          DEBUG_INFO2("entering IFDHControl (lun: %X)", Lun);          DEBUG_INFO3("lun: %X, ControlCode: 0x%X", Lun, dwControlCode);
866    
867          /* if (CheckLun(Lun))          reader_index = LunToReaderIndex(Lun);
868                  return IFD_COMMUNICATION_ERROR; */          if ((-1 == reader_index) || (NULL == pdwBytesReturned))
869                    return return_value;
870    
871          return IFD_SUCCESS;          /* Set the return length to 0 to avoid problems */
872            *pdwBytesReturned = 0;
873    
874            if (IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE == dwControlCode)
875            {
876                    if (FALSE == (DriverOptions & DRIVER_OPTION_CCID_EXCHANGE_AUTHORIZED))
877                    {
878                            DEBUG_INFO("ifd exchange (Escape command) not allowed");
879                            return_value = IFD_COMMUNICATION_ERROR;
880                    }
881                    else
882                    {
883                            unsigned int iBytesReturned;
884    
885                            iBytesReturned = RxLength;
886                            return_value = CmdEscape(reader_index, TxBuffer, TxLength, RxBuffer,
887                                    &iBytesReturned);
888                            *pdwBytesReturned = iBytesReturned;
889                    }
890            }
891    
892            /* Implement the PC/SC v2.1.2 Part 10 IOCTL mechanism */
893    
894            /* Query for features */
895            if (CM_IOCTL_GET_FEATURE_REQUEST == dwControlCode)
896            {
897                    unsigned int iBytesReturned = 0;
898                    PCSC_TLV_STRUCTURE *pcsc_tlv = (PCSC_TLV_STRUCTURE *)RxBuffer;
899    
900                    /* we need room for two records */
901                    if (RxLength < 2 * sizeof(PCSC_TLV_STRUCTURE))
902                            return IFD_COMMUNICATION_ERROR;
903    
904                    /* We can only support direct verify and/or modify currently */
905                    if (get_ccid_descriptor(reader_index) -> bPINSupport
906                            & CCID_CLASS_PIN_VERIFY)
907                    {
908                            pcsc_tlv -> tag = FEATURE_VERIFY_PIN_DIRECT;
909                            pcsc_tlv -> length = 0x04; /* always 0x04 */
910                            pcsc_tlv -> value = IOCTL_FEATURE_VERIFY_PIN_DIRECT;
911    
912                            pcsc_tlv++;
913                            iBytesReturned += 6;
914                    }
915    
916                    if (get_ccid_descriptor(reader_index) -> bPINSupport
917                            & CCID_CLASS_PIN_MODIFY)
918                    {
919                            pcsc_tlv -> tag = FEATURE_MODIFY_PIN_DIRECT;
920                            pcsc_tlv -> length = 0x04; /* always 0x04 */
921                            pcsc_tlv -> value = IOCTL_FEATURE_MODIFY_PIN_DIRECT;
922    
923                            pcsc_tlv++;
924                            iBytesReturned += 6;
925                    }
926                    *pdwBytesReturned = iBytesReturned;
927                    return_value = IFD_SUCCESS;
928            }
929    
930            /* Verify a PIN, plain CCID */
931            if (IOCTL_FEATURE_VERIFY_PIN_DIRECT == dwControlCode)
932            {
933                    unsigned int iBytesReturned;
934    
935                    iBytesReturned = RxLength;
936                    return_value = SecurePINVerify(reader_index, TxBuffer, TxLength,
937                            RxBuffer, &iBytesReturned);
938                    *pdwBytesReturned = iBytesReturned;
939            }
940    
941            /* Modify a PIN, plain CCID */
942            if (IOCTL_FEATURE_MODIFY_PIN_DIRECT == dwControlCode)
943            {
944                    unsigned int iBytesReturned;
945    
946                    iBytesReturned = RxLength;
947                    return_value = SecurePINModify(reader_index, TxBuffer, TxLength,
948                            RxBuffer, &iBytesReturned);
949                    *pdwBytesReturned = iBytesReturned;
950            }
951    
952            return return_value;
953  } /* IFDHControl */  } /* IFDHControl */
954    
955    
# Line 545  RESPONSECODE IFDHICCPresence(DWORD Lun) Line 965  RESPONSECODE IFDHICCPresence(DWORD Lun)
965    
966          unsigned char pcbuffer[SIZE_GET_SLOT_STATUS];          unsigned char pcbuffer[SIZE_GET_SLOT_STATUS];
967          RESPONSECODE return_value = IFD_COMMUNICATION_ERROR;          RESPONSECODE return_value = IFD_COMMUNICATION_ERROR;
968            int oldLogLevel;
969            int reader_index;
970            _ccid_descriptor *ccid_descriptor;
971            unsigned int oldReadTimeout;
972    
973          DEBUG_PERIODIC2("entering IFDHICCPresence (lun: %X)", Lun);          DEBUG_PERIODIC2("lun: %X", Lun);
974    
975          if (CheckLun(Lun))          if (-1 == (reader_index = LunToReaderIndex(Lun)))
976                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
977    
978          if (CmdGetSlotStatus(Lun, pcbuffer) != IFD_SUCCESS)          ccid_descriptor = get_ccid_descriptor(reader_index);
979    
980            /* save the current read timeout computed from card capabilities */
981            oldReadTimeout = ccid_descriptor->readTimeout;
982    
983            /* use default timeout since the reader may not be present anymore */
984            ccid_descriptor->readTimeout = DEFAULT_COM_READ_TIMEOUT;
985    
986            /* if DEBUG_LEVEL_PERIODIC is not set we remove DEBUG_LEVEL_COMM */
987            oldLogLevel = LogLevel;
988            if (! (LogLevel & DEBUG_LEVEL_PERIODIC))
989                    LogLevel &= ~DEBUG_LEVEL_COMM;
990    
991            return_value = CmdGetSlotStatus(reader_index, pcbuffer);
992    
993            /* set back the old timeout */
994            ccid_descriptor->readTimeout = oldReadTimeout;
995    
996            /* set back the old LogLevel */
997            LogLevel = oldLogLevel;
998    
999            if (return_value != IFD_SUCCESS)
1000                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
1001    
1002          switch (pcbuffer[7])    /* bStatus */          return_value = IFD_COMMUNICATION_ERROR;
1003            switch (pcbuffer[7] & CCID_ICC_STATUS_MASK)     /* bStatus */
1004          {          {
1005                  case 0x00:                  case CCID_ICC_PRESENT_ACTIVE:
1006                    case CCID_ICC_PRESENT_INACTIVE:
1007                          return_value = IFD_ICC_PRESENT;                          return_value = IFD_ICC_PRESENT;
1008                            /* use default slot */
1009                          break;                          break;
1010    
1011                  case 0x01:                  case CCID_ICC_ABSENT:
1012                          return_value = IFD_ICC_PRESENT;                          /* Reset ATR buffer */
1013                          break;                          CcidSlots[reader_index].nATRLength = 0;
1014                            *CcidSlots[reader_index].pcATRBuffer = '\0';
1015    
1016                            /* Reset PowerFlags */
1017                            CcidSlots[reader_index].bPowerFlags = POWERFLAGS_RAZ;
1018    
                 case 0x02:  
1019                          return_value = IFD_ICC_NOT_PRESENT;                          return_value = IFD_ICC_NOT_PRESENT;
1020                          break;                          break;
1021          }          }
1022    
1023            /* SCR331-DI contactless reader */
1024            if (((SCR331DI == ccid_descriptor->readerID)
1025                    || (SCR331DINTTCOM == ccid_descriptor->readerID))
1026                    && (ccid_descriptor->bCurrentSlotIndex > 0))
1027            {
1028                    unsigned char cmd[] = { 0x11 };
1029                    /*  command: 11 ??
1030                     * response: 00 11 01 ?? no card
1031                     *           01 04 00 ?? card present */
1032    
1033                    unsigned char res[10];
1034                    unsigned int length_res = sizeof(res);
1035    
1036                    /* if DEBUG_LEVEL_PERIODIC is not set we remove DEBUG_LEVEL_COMM */
1037                    oldLogLevel = LogLevel;
1038                    if (! (LogLevel & DEBUG_LEVEL_PERIODIC))
1039                            LogLevel &= ~DEBUG_LEVEL_COMM;
1040    
1041                    CmdEscape(reader_index, cmd, sizeof(cmd), res, &length_res);
1042    
1043                    /* set back the old LogLevel */
1044                    LogLevel = oldLogLevel;
1045    
1046                    if (0x01 == res[0])
1047                            return_value = IFD_ICC_PRESENT;
1048                    else
1049                    {
1050                            /* Reset ATR buffer */
1051                            CcidSlots[reader_index].nATRLength = 0;
1052                            *CcidSlots[reader_index].pcATRBuffer = '\0';
1053    
1054                            /* Reset PowerFlags */
1055                            CcidSlots[reader_index].bPowerFlags = POWERFLAGS_RAZ;
1056    
1057                            return_value = IFD_ICC_NOT_PRESENT;
1058                    }
1059            }
1060    
1061            DEBUG_PERIODIC2("Card %s",
1062                    IFD_ICC_PRESENT == return_value ? "present" : "absent");
1063    
1064          return return_value;          return return_value;
1065  } /* IFDHICCPresence */  } /* IFDHICCPresence */
1066    
1067  void IFDSetEmv(DWORD lun)  
1068    CcidDesc *get_ccid_slot(unsigned int reader_index)
1069  {  {
1070          CcidSlots[LunToReaderIndex(lun)].bPowerFlags |= MASK_POWERFLAGS_EMV;          return &CcidSlots[reader_index];
1071  } /* IFDSetEmv */  } /* get_ccid_slot */
1072    
1073    
1074    void init_driver(void)
1075    {
1076            char keyValue[TOKEN_MAX_VALUE_SIZE];
1077            char infofile[FILENAME_MAX];
1078    
1079            /* Info.plist full patch filename */
1080            snprintf(infofile, sizeof(infofile), "%s/%s/Contents/Info.plist",
1081                    PCSCLITE_HP_DROPDIR, BUNDLE);
1082    
1083            /* Log level */
1084            if (0 == LTPBundleFindValueWithKey(infofile, "ifdLogLevel", keyValue, 0))
1085            {
1086                    /* convert from hex or dec or octal */
1087                    LogLevel = strtoul(keyValue, NULL, 0);
1088    
1089                    /* print the log level used */
1090                    DEBUG_INFO2("LogLevel: 0x%.4X", LogLevel);
1091            }
1092    
1093            /* Driver options */
1094            if (0 == LTPBundleFindValueWithKey(infofile, "ifdDriverOptions", keyValue, 0))
1095            {
1096                    /* convert from hex or dec or octal */
1097                    DriverOptions = strtoul(keyValue, NULL, 0);
1098    
1099                    /* print the log level used */
1100                    DEBUG_INFO2("DriverOptions: 0x%.4X", DriverOptions);
1101            }
1102    
1103            /* initialise the Lun to reader_index mapping */
1104            InitReaderIndex();
1105    
1106            DebugInitialized = TRUE;
1107    } /* init_driver */
1108    
1109    
1110    void extra_egt(ATR_t *atr, _ccid_descriptor *ccid_desc, DWORD Protocol)
1111    {
1112            /* This function use an EGT value for cards who comply with followings
1113             * criterias:
1114             * - TA1 > 11
1115             * - current EGT = 0x00 or 0xFF
1116             * - T=0 or (T=1 and CWI >= 2)
1117             *
1118             * Without this larger EGT some non ISO 7816-3 smart cards may not
1119             * communicate with the reader.
1120             *
1121             * This modification is harmless, the reader will just be less restrictive
1122             */
1123    
1124            unsigned int card_baudrate;
1125            unsigned int default_baudrate;
1126            double f, d;
1127            int i;
1128    
1129            /* if TA1 not present */
1130            if (! atr->ib[0][ATR_INTERFACE_BYTE_TA].present)
1131                    return;
1132    
1133            ATR_GetParameter(atr, ATR_PARAMETER_D, &d);
1134            ATR_GetParameter(atr, ATR_PARAMETER_F, &f);
1135    
1136            /* Baudrate = f x D/F */
1137            card_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock * d / f);
1138    
1139            default_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock
1140                    * ATR_DEFAULT_D / ATR_DEFAULT_F);
1141    
1142            /* TA1 > 11? */
1143            if (card_baudrate <= default_baudrate)
1144                    return;
1145    
1146            /* Current EGT = 0 or FF? */
1147            if (atr->ib[0][ATR_INTERFACE_BYTE_TC].present &&
1148                    ((0x00 == atr->ib[0][ATR_INTERFACE_BYTE_TC].value) ||
1149                    (0xFF == atr->ib[0][ATR_INTERFACE_BYTE_TC].value)))
1150            {
1151                    if (SCARD_PROTOCOL_T0 == Protocol)
1152                    {
1153                            /* Init TC1 */
1154                            atr->ib[0][ATR_INTERFACE_BYTE_TC].present = TRUE;
1155                            atr->ib[0][ATR_INTERFACE_BYTE_TC].value = 2;
1156                            DEBUG_INFO("Extra EGT patch applied");
1157                    }
1158    
1159                    if (SCARD_PROTOCOL_T1 == Protocol)
1160                    {
1161                            /* TBi (i>2) present? BWI/CWI */
1162                            for (i=2; i<ATR_MAX_PROTOCOLS; i++)
1163                            {
1164                                    /* CWI >= 2 ? */
1165                                    if (atr->ib[i][ATR_INTERFACE_BYTE_TB].present &&
1166                                            ((atr->ib[i][ATR_INTERFACE_BYTE_TB].value & 0x0F) >= 2))
1167                                    {
1168                                            /* Init TC1 */
1169                                            atr->ib[0][ATR_INTERFACE_BYTE_TC].present = TRUE;
1170                                            atr->ib[0][ATR_INTERFACE_BYTE_TC].value = 2;
1171                                            DEBUG_INFO("Extra EGT patch applied");
1172    
1173                                            /* only the first TBi (i>2) must be used */
1174                                            break;
1175                                    }
1176                            }
1177                    }
1178            }
1179    } /* extra_egt */
1180    
1181    
1182    static char find_baud_rate(unsigned int baudrate, unsigned int *list)
1183    {
1184            int i;
1185    
1186            DEBUG_COMM2("Card baud rate: %d", baudrate);
1187    
1188            /* Does the reader support the annonced smart card data speed? */
1189            for (i=0;; i++)
1190            {
1191                    /* end of array marker */
1192                    if (0 == list[i])
1193                            break;
1194    
1195                    DEBUG_COMM2("Reader can do: %d", list[i]);
1196    
1197                    /* We must take into account that the card_baudrate integral value
1198                     * is an approximative result, computed from the d/f float result.
1199                     */
1200                    if ((baudrate < list[i] + 2) && (baudrate > list[i] - 2))
1201                            return TRUE;
1202            }
1203    
1204            return FALSE;
1205    } /* find_baud_rate */
1206    
1207    
1208    static unsigned int T0_card_timeout(double f, double d, int TC1, int TC2,
1209            int clock_frequency)
1210    {
1211            unsigned int timeout = DEFAULT_COM_READ_TIMEOUT;
1212            double EGT, WWT;
1213            unsigned int t;
1214    
1215            /* Timeout applied on ISO_IN or ISO_OUT card exchange
1216             * we choose the maximum computed value.
1217             *
1218             * ISO_IN timeout is the sum of:
1219             * Terminal:                                    Smart card:
1220             * 5 bytes header cmd  ->
1221             *                    <-                Procedure byte
1222             * 256 data bytes          ->
1223             *                                        <-            SW1-SW2
1224             * = 261 EGT       + 3 WWT     + 3 WWT
1225             *
1226             * ISO_OUT Timeout is the sum of:
1227             * Terminal:                    Smart card:
1228             * 5 bytes header cmd  ->
1229             *                                        <-        Procedure byte + 256 data bytes + SW1-SW2
1230             * = 5 EGT          + 1 WWT     + 259 WWT
1231             */
1232    
1233            /* clock_frequency is in kHz so the times are in milliseconds and not
1234             * in seconds */
1235    
1236            /* EGT */
1237            /* see ch. 6.5.3 Extra Guard Time, page 12 of ISO 7816-3 */
1238            EGT = 12 * f / d / clock_frequency + (f / d) * TC1 / clock_frequency;
1239    
1240            /* card WWT */
1241            /* see ch. 8.2 Character level, page 15 of ISO 7816-3 */
1242            WWT = 960 * TC2 * f / clock_frequency;
1243    
1244            /* ISO in */
1245            t  = 261 * EGT + (3 + 3) * WWT;
1246            /* Convert from milliseonds to seconds rouned to the upper value
1247             * use +1 instead of ceil() to round up to the nearest interger
1248             * so we can avoid a dependency on the math library */
1249            t = t/1000 +1;
1250            if (timeout < t)
1251                    timeout = t;
1252    
1253            /* ISO out */
1254            t = 5 * EGT + (1 + 259) * WWT;
1255            t = t/1000 +1;
1256            if (timeout < t)
1257                    timeout = t;
1258    
1259            return timeout;
1260    } /* T0_card_timeout  */
1261    
1262    
1263    static unsigned int T1_card_timeout(double f, double d, int TC1,
1264            int BWI, int CWI, int clock_frequency)
1265    {
1266            double EGT, BWT, CWT, etu;
1267            unsigned int timeout;
1268    
1269            /* Timeout applied on ISO in + ISO out card exchange
1270             *
1271         * Timeout is the sum of:
1272             * - ISO in delay between leading edge of the first character sent by the
1273             *   interface device and the last one (NAD PCB LN APDU CKS) = 260 EGT,
1274             * - delay between ISO in and ISO out = BWT,
1275             * - ISO out delay between leading edge of the first character sent by the
1276             *   card and the last one (NAD PCB LN DATAS CKS) = 260 CWT.
1277             */
1278    
1279            /* clock_frequency is in kHz so the times are in milliseconds and not
1280             * in seconds */
1281    
1282            /* see ch. 6.5.2 Transmission factors F and D, page 12 of ISO 7816-3 */
1283            etu = f / d / clock_frequency;
1284    
1285            /* EGT */
1286            /* see ch. 6.5.3 Extra Guard Time, page 12 of ISO 7816-3 */
1287            EGT = 12 * etu + (f / d) * TC1 / clock_frequency;
1288    
1289            /* card BWT */
1290            /* see ch. 9.5.3.2 Block Waiting Time, page 20 of ISO 7816-3 */
1291            BWT = 11 * etu + (1<<BWI) * 960 * 372 / clock_frequency;
1292    
1293            /* card CWT */
1294            /* see ch. 9.5.3.1 Caracter Waiting Time, page 20 of ISO 7816-3 */
1295            CWT = (11 + (1<<CWI)) * etu;
1296    
1297            timeout = 260*EGT + BWT + 260*CWT;
1298    
1299            /* Convert from milliseonds to seconds rounded to the upper value
1300             * we use +1 instead of ceil() to round up to the nearest greater interger
1301             * so we can avoid a dependency on the math library */
1302            timeout = timeout/1000 +1;
1303    
1304            return timeout;
1305    } /* T1_card_timeout  */
1306    

Legend:
Removed from v.269  
changed lines
  Added in v.1630

  ViewVC Help
Powered by ViewVC 1.1.5