/[pcsclite]/trunk/Drivers/ccid/src/commands.c
ViewVC logotype

Diff of /trunk/Drivers/ccid/src/commands.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1076 by rousseau, Fri Jul 16 06:31:15 2004 UTC revision 2406 by rousseau, Tue Feb 20 13:34:44 2007 UTC
# Line 1  Line 1 
1  /*  /*
2      commands.c: Commands sent to the card      commands.c: Commands sent to the card
3      Copyright (C) 2003   Ludovic Rousseau      Copyright (C) 2003-2004   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  /*  /*
# Line 23  Line 23 
23    
24  #include <string.h>  #include <string.h>
25  #include <stdlib.h>  #include <stdlib.h>
26  #include <PCSC/pcsclite.h>  #include <pcsclite.h>
27  #include <PCSC/ifdhandler.h>  #include <ifdhandler.h>
28    #include <reader.h>
29    
30  #include "commands.h"  #include "commands.h"
31  #include "openct/proto-t1.h"  #include "openct/proto-t1.h"
# Line 34  Line 35 
35  #include "config.h"  #include "config.h"
36  #include "debug.h"  #include "debug.h"
37    
38  /*  /* All the pinpad readers I used are more or less bogus
39   * Possible values :   * I use code to change the user command and make the firmware happy */
40   * 3 -> 1.8V, 3V, 5V  #define BOGUS_PINPAD_FIRMWARE
41   * 2 -> 3V, 5V  
42   * 1 -> 5V only  #define max( a, b )   ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) )
43   */  #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
44  /*  #define IFD_ERROR_INSUFFICIENT_BUFFER 700
  * To be safe we only use 5V  
  * otherwise we would have to parse the ATR and get the value of TAi (i>2) when  
  * in T=15  
  */  
 #define DEFAULT_VOLTAGE 1 /* start with 5 volts */  
45    
46  /* internal functions */  /* internal functions */
47  static RESPONSECODE CmdXfrBlockTPDU_T0(unsigned int lun, unsigned int tx_length,  static RESPONSECODE CmdXfrBlockAPDU_extended(unsigned int reader_index,
48          unsigned char tx_buffer[], unsigned int *rx_length,          unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
49          unsigned char rx_buffer[]);          unsigned char rx_buffer[]);
50    
51  static RESPONSECODE CmdXfrBlockTPDU_T1(unsigned int lun, unsigned int tx_length,  static RESPONSECODE CmdXfrBlockTPDU_T0(unsigned int reader_index,
52          unsigned char tx_buffer[], unsigned int *rx_length,          unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
53            unsigned char rx_buffer[]);
54    
55    static RESPONSECODE CmdXfrBlockCHAR_T0(unsigned int reader_index, unsigned int
56            tx_length, unsigned char tx_buffer[], unsigned int *rx_length, unsigned
57            char rx_buffer[]);
58    
59    static RESPONSECODE CmdXfrBlockTPDU_T1(unsigned int reader_index,
60            unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
61          unsigned char rx_buffer[]);          unsigned char rx_buffer[]);
62    
63  static void i2dw(int value, unsigned char *buffer);  static void i2dw(int value, unsigned char *buffer);
# Line 64  static void i2dw(int value, unsigned cha Line 68  static void i2dw(int value, unsigned cha
68   *                                      CmdPowerOn   *                                      CmdPowerOn
69   *   *
70   ****************************************************************************/   ****************************************************************************/
71  RESPONSECODE CmdPowerOn(unsigned int lun, unsigned int * nlength,  RESPONSECODE CmdPowerOn(unsigned int reader_index, unsigned int * nlength,
72          unsigned char buffer[])          unsigned char buffer[], int voltage)
73  {  {
74          unsigned char cmd[10];          unsigned char cmd[10];
75          status_t res;          status_t res;
76          int atr_len, length, count = 1;          int length, count = 1;
77            unsigned int atr_len;
78          RESPONSECODE return_value = IFD_SUCCESS;          RESPONSECODE return_value = IFD_SUCCESS;
79          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(lun);          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
         char voltage;  
80    
81          /* store length of buffer[] */          /* store length of buffer[] */
82          length = *nlength;          length = *nlength;
83    
84          if (ccid_descriptor->dwFeatures & CCID_CLASS_AUTO_VOLTAGE)          if (ccid_descriptor->dwFeatures & CCID_CLASS_AUTO_VOLTAGE)
85                  voltage = 0;    /* automatic voltage selection */                  voltage = 0;    /* automatic voltage selection */
         else  
                 voltage = DEFAULT_VOLTAGE;  
86    
87  again:  again:
88          cmd[0] = 0x62; /* IccPowerOn */          cmd[0] = 0x62; /* IccPowerOn */
89          cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0;  /* dwLength */          cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0;  /* dwLength */
90          cmd[5] = 0;     /* slot number */          cmd[5] = ccid_descriptor->bCurrentSlotIndex;    /* slot number */
91          cmd[6] = ccid_descriptor->bSeq++;          cmd[6] = (*ccid_descriptor->pbSeq)++;
92          cmd[7] = voltage;          cmd[7] = voltage;
93          cmd[8] = cmd[9] = 0; /* RFU */          cmd[8] = cmd[9] = 0; /* RFU */
94    
95          res = WritePort(lun, sizeof(cmd), cmd);          res = WritePort(reader_index, sizeof(cmd), cmd);
96          if (res != STATUS_SUCCESS)          if (res != STATUS_SUCCESS)
97                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
98    
# Line 98  again: Line 100  again:
100          /* needed if we go back after a switch to ISO mode */          /* needed if we go back after a switch to ISO mode */
101          *nlength = length;          *nlength = length;
102    
103          res = ReadPort(lun, nlength, buffer);          res = ReadPort(reader_index, nlength, buffer);
104          if (res != STATUS_SUCCESS)          if (res != STATUS_SUCCESS)
105                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
106    
107            if (*nlength < STATUS_OFFSET+1)
108            {
109                    DEBUG_CRITICAL2("Not enough data received: %d bytes", *nlength);
110                    return IFD_COMMUNICATION_ERROR;
111            }
112    
113          if (buffer[STATUS_OFFSET] & CCID_COMMAND_FAILED)          if (buffer[STATUS_OFFSET] & CCID_COMMAND_FAILED)
114          {          {
115                  ccid_error(buffer[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__);    /* bError */                  ccid_error(buffer[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__);    /* bError */
116    
117                  /* Protocol error in EMV mode */                  if (0xBB == buffer[ERROR_OFFSET] &&     /* Protocol error in EMV mode */
118                  if (buffer[ERROR_OFFSET] == 0xBB &&                          ((GEMPC433 == ccid_descriptor->readerID)
119                          ccid_descriptor->readerID == GEMPC433)                          || (CHERRYXX33 == ccid_descriptor->readerID)))
120                  {                  {
121                          unsigned char cmd[] = "\x1F\x01";                          unsigned char cmd[] = {0x1F, 0x01};
122                          unsigned char res[1];                          unsigned char res[1];
123                          unsigned int res_length = sizeof(res);                          unsigned int res_length = sizeof(res);
124    
125                          if ((return_value = CmdEscape(lun, cmd, sizeof(cmd)-1, res,                          if ((return_value = CmdEscape(reader_index, cmd, sizeof(cmd), res,
126                                  &res_length)) != IFD_SUCCESS)                                  &res_length)) != IFD_SUCCESS)
127                                  return return_value;                                  return return_value;
128    
# Line 128  again: Line 136  again:
136                  /* continue with 3 volts and 5 volts */                  /* continue with 3 volts and 5 volts */
137                  if (voltage > 1)                  if (voltage > 1)
138                  {                  {
139                            const char *voltage_code[] = { "auto", "5V", "3V", "1.8V" };
140    
141                            DEBUG_INFO3("Power up with %s failed. Try with %s.",
142                                    voltage_code[voltage], voltage_code[voltage-1]);
143                          voltage--;                          voltage--;
144                          goto again;                          goto again;
145                  }                  }
# Line 150  again: Line 162  again:
162    
163  /*****************************************************************************  /*****************************************************************************
164   *   *
165   *                                      SecurePIN   *                                      SecurePINVerify
166   *   *
167   ****************************************************************************/   ****************************************************************************/
168  RESPONSECODE SecurePIN(unsigned int lun, const unsigned char TxBuffer[],  RESPONSECODE SecurePINVerify(unsigned int reader_index,
169          unsigned int TxLength, unsigned char RxBuffer[], unsigned int *RxLength)          unsigned char TxBuffer[], unsigned int TxLength,
170            unsigned char RxBuffer[], unsigned int *RxLength)
171  {  {
172          unsigned char cmd[11+14+CMD_BUF_SIZE];          unsigned char cmd[11+14+CMD_BUF_SIZE];
173          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(lun);          unsigned int a, b;
174          int length = 0;          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
175            int old_read_timeout;
176            RESPONSECODE ret;
177    
178            cmd[0] = 0x69;  /* Secure */
179            cmd[5] = ccid_descriptor->bCurrentSlotIndex;    /* slot number */
180            cmd[6] = (*ccid_descriptor->pbSeq)++;
181            cmd[7] = 0;             /* bBWI */
182            cmd[8] = 0;             /* wLevelParameter */
183            cmd[9] = 0;
184            cmd[10] = 0;    /* bPINOperation: PIN Verification */
185    
186            /* 19 is the size of the PCSCv2 PIN verify structure
187             * The equivalent CCID structure is only 14-bytes long */
188            if (TxLength > 19+CMD_BUF_SIZE) /* command too large? */
189            {
190                    DEBUG_INFO3("Command too long: %d > %d", TxLength, 19+CMD_BUF_SIZE);
191                    *RxLength = 0;
192                    return IFD_NOT_SUPPORTED;
193            }
194    
195            if (TxLength < 19+4 /* 4 = APDU size */)        /* command too short? */
196            {
197                    DEBUG_INFO3("Command too short: %d < %d", TxLength, 19+4);
198                    *RxLength = 0;
199                    return IFD_NOT_SUPPORTED;
200            }
201    
202          /* PIN verification data structure WITHOUT TeoPrologue */          if (dw2i(TxBuffer, 15) + 19 != TxLength) /* ulDataLength field coherency */
         if (TxBuffer[4] /* Lc */  
                 + 5 /* CLA, INS, P1, P2, Lc */  
                 + 11 /* CCID PIN verification data structure */ == TxLength)  
203          {          {
204                  i2dw(TxLength+3+1, cmd+1);      /* command length */                  DEBUG_INFO3("Wrong lengths: %d %d", dw2i(TxBuffer, 15) + 19, TxLength);
205                    *RxLength = 0;
206                    return IFD_NOT_SUPPORTED;
207            }
208    
209                  /* copy the CCID data structure */          /* make sure bEntryValidationCondition is valid
210                  memcpy(cmd +11, TxBuffer + TxBuffer[4] + 5, 11);           * The Cherry XX44 reader crashes with a wrong value */
211            if ((0x00 == TxBuffer[7]) || (TxBuffer[7] > 0x07))
212            {
213                    DEBUG_INFO2("Correct bEntryValidationCondition (was 0x%02X)",
214                            TxBuffer[7]);
215                    TxBuffer[7] = 0x02;
216            }
217    
218                  /* TeoPrologue not used */  #ifdef BOGUS_PINPAD_FIRMWARE
219                  memset(cmd +11 +11, 0, 3);          /* bug circumvention for the GemPC Pinpad */
220            if (GEMPCPINPAD == ccid_descriptor->readerID)
221            {
222                    /* the firmware reject the cases: 00h No string and FFh default
223                     * CCID message. The only value supported is 01h (display 1 message) */
224                    if (0x01 != TxBuffer[8])
225                    {
226                            DEBUG_INFO2("Correct bNumberMessage for GemPC Pinpad (was %d)",
227                                    TxBuffer[8]);
228                            TxBuffer[8] = 0x01;
229                    }
230    
231                  /* copy the APDU */                  /* The reader does not support, and actively reject, "max size reached"
232                  memcpy(cmd +11 +14, TxBuffer, TxLength-11);                   * and "timeout occured" validation conditions */
233                    if (0x02 != TxBuffer[7])
234                    {
235                            DEBUG_INFO2("Correct bEntryValidationCondition for GemPC Pinpad (was %d)",
236                                    TxBuffer[7]);
237                            TxBuffer[7] = 0x02;     /* validation key pressed */
238                    }
239    
                 length = 14 + TxLength;  
240          }          }
241          /* PIN verification data structure WITH TeoPrologue */  #endif
242          else if (TxBuffer[4] /* Lc */  
243                  + 5 /* CLA, INS, P1, P2, Lc */          /* T=1 Protocol Management for a TPDU reader */
244                  + 14 /* CCID PIN verification data structure */ == TxLength)          if ((SCARD_PROTOCOL_T1 == ccid_descriptor->cardProtocol)
245                    && (CCID_CLASS_TPDU == (ccid_descriptor->dwFeatures & CCID_CLASS_EXCHANGE_MASK)))
246          {          {
247                  i2dw(TxLength+1, cmd+1);        /* command length */                  ct_buf_t sbuf;
248                    unsigned char sdata[T1_BUFFER_SIZE];
249    
250                  /* copy the CCID data structure */                  /* Initialize send buffer with the APDU */
251                  memcpy(cmd +11, TxBuffer + TxBuffer[4] + 5, 14);                  ct_buf_set(&sbuf,
252                            (void *)(TxBuffer + offsetof(PIN_VERIFY_STRUCTURE, abData)),
253                            TxLength - offsetof(PIN_VERIFY_STRUCTURE, abData));
254    
255                    /* Create T=1 block */
256                    ret = t1_build(&((get_ccid_slot(reader_index))->t1),
257                            sdata, 0, T1_I_BLOCK, &sbuf, NULL);
258    
259                    /* Increment the sequence numbers  */
260                    get_ccid_slot(reader_index)->t1.ns ^= 1;
261                    get_ccid_slot(reader_index)->t1.nr ^= 1;
262    
263                    /* Copy the generated T=1 block prologue into the teoprologue
264                     * of the CCID command */
265                    memcpy(TxBuffer + offsetof(PIN_VERIFY_STRUCTURE, bTeoPrologue),
266                            sdata, 3);
267            }
268    
269                  /* copy the APDU */          /* Build a CCID block from a PC/SC V2.1.2 Part 10 block */
270                  memcpy(cmd +11 +14, TxBuffer, TxLength-14);          for (a = 11, b = 0; b < TxLength; b++)
271            {
272                    if (1 == b) /* bTimeOut2 field */
273                            /* Ignore the second timeout as there's nothing we can do with
274                             * it currently */
275                            continue;
276    
277                    if ((b >= 15) && (b <= 18)) /* ulDataLength field (4 bytes) */
278                            /* the ulDataLength field is not present in the CCID frame
279                             * so do not copy */
280                            continue;
281    
282                    /* copy the CCID block 'verbatim' */
283                    cmd[a] = TxBuffer[b];
284                    a++;
285            }
286    
287                  length = 11 + TxLength;          /* SPR532 and Case 1 APDU */
288            if ((SPR532 == ccid_descriptor->readerID) && (TxBuffer[15] == 4))
289            {
290                    RESPONSECODE return_value;
291                    unsigned char cmd[] = { 0x80, 0x02, 0x00 };
292                    unsigned char res[1];
293                    unsigned int res_length = sizeof(res);
294    
295                    /* the SPR532 will append the PIN code without any padding */
296                    return_value = CmdEscape(reader_index, cmd, sizeof(cmd), res,
297                            &res_length);
298                    if (return_value != IFD_SUCCESS)
299                    {
300                            ccid_error(res[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__);
301                            return return_value;
302                    }
303          }          }
304          else  
305            i2dw(a - 10, cmd + 1);  /* CCID message length */
306    
307            old_read_timeout = ccid_descriptor -> readTimeout;
308            ccid_descriptor -> readTimeout = max(30, TxBuffer[0]+10);       /* at least 30 seconds */
309    
310            if (WritePort(reader_index, a, cmd) != STATUS_SUCCESS)
311          {          {
312                  *RxLength = 0;                  *RxLength = 0;
313                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
314          }          }
315    
316            ret = CCID_Receive(reader_index, RxLength, RxBuffer, NULL);
317    
318            /* T=1 Protocol Management for a TPDU reader */
319            if ((IFD_SUCCESS == ret)
320                    && (SCARD_PROTOCOL_T1 == ccid_descriptor->cardProtocol)
321                    && (CCID_CLASS_TPDU == (ccid_descriptor->dwFeatures & CCID_CLASS_EXCHANGE_MASK)))
322            {
323                    /* timeout and cancel cases are faked by CCID_Receive() */
324                    if (2 == *RxLength)
325                    {
326                            /* Decrement the sequence numbers since no TPDU was sent */
327                            get_ccid_slot(reader_index)->t1.ns ^= 1;
328                            get_ccid_slot(reader_index)->t1.nr ^= 1;
329                    }
330                    else
331                    {
332                            /* get only the T=1 data */
333                            /* FIXME: manage T=1 error blocks */
334                            memmove(RxBuffer, RxBuffer+3, *RxLength -4);
335                            *RxLength -= 4; /* remove NAD, PCB, LEN and CRC */
336                    }
337            }
338    
339            ccid_descriptor -> readTimeout = old_read_timeout;
340            return ret;
341    } /* SecurePINVerify */
342    
343    
344    /*****************************************************************************
345     *
346     *                                      SecurePINModify
347     *
348     ****************************************************************************/
349    RESPONSECODE SecurePINModify(unsigned int reader_index,
350            unsigned char TxBuffer[], unsigned int TxLength,
351            unsigned char RxBuffer[], unsigned int *RxLength)
352    {
353            unsigned char cmd[11+19+CMD_BUF_SIZE];
354            unsigned int a, b;
355            _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
356            int old_read_timeout;
357            RESPONSECODE ret;
358    #ifdef BOGUS_PINPAD_FIRMWARE
359            int bNumberMessages = 0; /* for GemPC Pinpad */
360    #endif
361    
362          cmd[0] = 0x69;  /* Secure */          cmd[0] = 0x69;  /* Secure */
363          cmd[5] = 0;             /* slot number */          cmd[5] = ccid_descriptor->bCurrentSlotIndex;    /* slot number */
364          cmd[6] = ccid_descriptor->bSeq++;          cmd[6] = (*ccid_descriptor->pbSeq)++;
365          cmd[7] = 0;             /* bBWI */          cmd[7] = 0;             /* bBWI */
366          cmd[8] = 0;             /* wLevelParameter */          cmd[8] = 0;             /* wLevelParameter */
367          cmd[9] = 0;          cmd[9] = 0;
368          cmd[10] = 0;    /* bPINOperation: PIN Verification */          cmd[10] = 1;    /* bPINOperation: PIN Modification */
369    
370          if (WritePort(lun, length, cmd) != STATUS_SUCCESS)          /* 24 is the size of the PCSC PIN modify structure
371                  return IFD_COMMUNICATION_ERROR;           * The equivalent CCID structure is only 18 or 19-bytes long */
372            if (TxLength > 24+CMD_BUF_SIZE) /* command too large? */
373            {
374                    DEBUG_INFO3("Command too long: %d > %d", TxLength, 24+CMD_BUF_SIZE);
375                    *RxLength = 0;
376                    return IFD_NOT_SUPPORTED;
377            }
378    
379            if (TxLength < 24+4 /* 4 = APDU size */) /* command too short? */
380            {
381                    DEBUG_INFO3("Command too short: %d < %d", TxLength, 24+4);
382                    *RxLength = 0;
383                    return IFD_NOT_SUPPORTED;
384            }
385    
386            if (dw2i(TxBuffer, 20) + 24 != TxLength) /* ulDataLength field coherency */
387            {
388                    DEBUG_INFO3("Wrong lengths: %d %d", dw2i(TxBuffer, 20) + 24, TxLength);
389                    *RxLength = 0;
390                    return IFD_NOT_SUPPORTED;
391            }
392    
393            /* Make sure in the beginning if bNumberMessage is valid or not */
394            if (TxBuffer[11] > 3)
395            {
396                    DEBUG_INFO2("Wrong bNumberMessage: %d", TxBuffer[11]);
397                    *RxLength = 0;
398                    return IFD_NOT_SUPPORTED;
399            }
400    
401            /* Make sure bEntryValidationCondition is valid
402             * The Cherry XX44 reader crashes with a wrong value */
403            if ((0x00 == TxBuffer[10]) || (TxBuffer[10] > 0x07))
404            {
405                    DEBUG_INFO2("Correct bEntryValidationCondition (was 0x%02X)",
406                            TxBuffer[10]);
407                    TxBuffer[10] = 0x02;
408            }
409    
410    #ifdef BOGUS_PINPAD_FIRMWARE
411            /* some firmwares are buggy so we try to "correct" the frame */
412            /*
413             * SPR 532 and Cherry ST 2000C has no display but requires _all_
414             * bMsgIndex fields with bNumberMessage set to 0.
415             */
416            if ((SPR532 == ccid_descriptor->readerID)
417                    || (CHERRYST2000 == ccid_descriptor->readerID))
418            {
419                    TxBuffer[11] = 0x03; /* set bNumberMessages to 3 so that
420                                                                    all bMsgIndex123 are filled */
421                    TxBuffer[14] = TxBuffer[15] = TxBuffer[16] = 0; /* bMsgIndex123 */
422            }
423    
424            /* the bug is a bit different than for the Cherry ST 2000C
425             * with bNumberMessages < 3 the command seems to be accepted
426             * and the card sends 6B 80 */
427            if (CHERRYXX44 == ccid_descriptor->readerID)
428            {
429                    TxBuffer[11] = 0x03; /* set bNumberMessages to 3 so that
430                                                                    all bMsgIndex123 are filled */
431            }
432    
433          return CCID_Receive(lun, RxLength, RxBuffer);          /* bug circumvention for the GemPC Pinpad */
434  } /* SecurePIN */          if (GEMPCPINPAD == ccid_descriptor->readerID)
435            {
436                    /* The reader does not support, and actively reject, "max size reached"
437                     * and "timeout occured" validation conditions */
438                    if (0x02 != TxBuffer[10])
439                    {
440                            DEBUG_INFO2("Correct bEntryValidationCondition for GemPC Pinpad (was %d)",
441                                    TxBuffer[10]);
442                            TxBuffer[10] = 0x02;    /* validation key pressed */
443                    }
444    
445                    /* the reader does not support any other value than 3 for the number
446                     * of messages */
447                    bNumberMessages = TxBuffer[11];
448                    if (0x03 != TxBuffer[11])
449                    {
450                            DEBUG_INFO2("Correct bNumberMessages for GemPC Pinpad (was %d)",
451                                    TxBuffer[11]);
452                            TxBuffer[11] = 0x03; /* 3 messages */
453                    }
454            }
455    #endif
456    
457            /* T=1 Protocol Management for a TPDU reader */
458            if ((SCARD_PROTOCOL_T1 == ccid_descriptor->cardProtocol)
459                    && (CCID_CLASS_TPDU == (ccid_descriptor->dwFeatures & CCID_CLASS_EXCHANGE_MASK)))
460            {
461                    ct_buf_t sbuf;
462                    unsigned char sdata[T1_BUFFER_SIZE];
463    
464                    /* Initialize send buffer with the APDU */
465                    ct_buf_set(&sbuf,
466                            (void *)(TxBuffer + offsetof(PIN_MODIFY_STRUCTURE, abData)),
467                            TxLength - offsetof(PIN_MODIFY_STRUCTURE, abData));
468    
469                    /* Create T=1 block */
470                    ret = t1_build(&((get_ccid_slot(reader_index))->t1),
471                            sdata, 0, T1_I_BLOCK, &sbuf, NULL);
472    
473                    /* Increment the sequence numbers  */
474                    get_ccid_slot(reader_index)->t1.ns ^= 1;
475                    get_ccid_slot(reader_index)->t1.nr ^= 1;
476    
477                    /* Copy the generated T=1 block prologue into the teoprologue
478                     * of the CCID command */
479                    memcpy(TxBuffer + offsetof(PIN_MODIFY_STRUCTURE, bTeoPrologue),
480                            sdata, 3);
481            }
482    
483            /* Build a CCID block from a PC/SC V2.1.2 Part 10 block */
484    
485            /* Do adjustments as needed - CCID spec is not exact with some
486             * details in the format of the structure, per-reader adaptions
487             * might be needed.
488             */
489            for (a = 11, b = 0; b < TxLength; b++)
490            {
491                    if (1 == b) /* bTimeOut2 */
492                            /* Ignore the second timeout as there's nothing we can do with it
493                             * currently */
494                            continue;
495    
496                    if (15 == b) /* bMsgIndex2 */
497                    {
498                            /* in CCID the bMsgIndex2 is present only if bNumberMessage != 0 */
499                            if (0 == TxBuffer[11])
500                                    continue;
501                    }
502    
503                    if (16 == b) /* bMsgIndex3 */
504                    {
505                            /* in CCID the bMsgIndex3 is present only if bNumberMessage == 3 */
506                            if (TxBuffer[11] < 3)
507                                    continue;
508                    }
509    
510                    if ((b >= 20) && (b <= 23)) /* ulDataLength field (4 bytes) */
511                            /* the ulDataLength field is not present in the CCID frame
512                             * so do not copy */
513                            continue;
514    
515                    /* copy to the CCID block 'verbatim' */
516                    cmd[a] = TxBuffer[b];
517                    a++;
518            }
519    
520    #ifdef BOGUS_PINPAD_FIRMWARE
521            if ((SPR532 == ccid_descriptor->readerID)
522                    || (CHERRYST2000 == ccid_descriptor->readerID))
523            {
524                    cmd[21] = 0x00; /* set bNumberMessages to 0 */
525            }
526    
527            if (GEMPCPINPAD == ccid_descriptor->readerID)
528                    cmd[21] = bNumberMessages;      /* restore the real value */
529    #endif
530    
531            /* We know the size of the CCID message now */
532            i2dw(a - 10, cmd + 1);  /* command length (includes bPINOperation) */
533    
534            old_read_timeout = ccid_descriptor -> readTimeout;
535            ccid_descriptor -> readTimeout = max(30, TxBuffer[0]+10);       /* at least 30 seconds */
536    
537            if (WritePort(reader_index, a, cmd) != STATUS_SUCCESS)
538            {
539                    *RxLength = 0;
540                    return IFD_COMMUNICATION_ERROR;
541            }
542    
543            ret = CCID_Receive(reader_index, RxLength, RxBuffer, NULL);
544    
545            /* T=1 Protocol Management for a TPDU reader */
546            if ((IFD_SUCCESS == ret)
547                    && (SCARD_PROTOCOL_T1 == ccid_descriptor->cardProtocol)
548                    && (CCID_CLASS_TPDU == (ccid_descriptor->dwFeatures & CCID_CLASS_EXCHANGE_MASK)))
549            {
550                    /* timeout and cancel cases are faked by CCID_Receive() */
551                    if (2 == *RxLength)
552                    {
553                            /* Decrement the sequence numbers since no TPDU was sent */
554                            get_ccid_slot(reader_index)->t1.ns ^= 1;
555                            get_ccid_slot(reader_index)->t1.nr ^= 1;
556                    }
557                    else
558                    {
559                            /* get only the T=1 data */
560                            /* FIXME: manage T=1 error blocks */
561                            memmove(RxBuffer, RxBuffer+3, *RxLength -4);
562                            *RxLength -= 4; /* remove NAD, PCB, LEN and CRC */
563                    }
564            }
565    
566            ccid_descriptor -> readTimeout = old_read_timeout;
567            return ret;
568    } /* SecurePINModify */
569    
570    
571  /*****************************************************************************  /*****************************************************************************
# Line 219  RESPONSECODE SecurePIN(unsigned int lun, Line 573  RESPONSECODE SecurePIN(unsigned int lun,
573   *                                      Escape   *                                      Escape
574   *   *
575   ****************************************************************************/   ****************************************************************************/
576  RESPONSECODE CmdEscape(unsigned int lun, const unsigned char TxBuffer[],  RESPONSECODE CmdEscape(unsigned int reader_index,
577          unsigned int TxLength, unsigned char RxBuffer[], unsigned int *RxLength)          const unsigned char TxBuffer[], unsigned int TxLength,
578            unsigned char RxBuffer[], unsigned int *RxLength)
579  {  {
580          unsigned char *cmd_in, *cmd_out;          unsigned char *cmd_in, *cmd_out;
581          status_t res;          status_t res;
582          unsigned int length_in, length_out;          unsigned int length_in, length_out;
583          RESPONSECODE return_value = IFD_SUCCESS;          RESPONSECODE return_value = IFD_SUCCESS;
584          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(lun);          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
585    
586    again:
587          /* allocate buffers */          /* allocate buffers */
588          length_in = 10 + TxLength;          length_in = 10 + TxLength;
589          if (NULL == (cmd_in = malloc(length_in)))          if (NULL == (cmd_in = malloc(length_in)))
# Line 242  RESPONSECODE CmdEscape(unsigned int lun, Line 598  RESPONSECODE CmdEscape(unsigned int lun,
598    
599          cmd_in[0] = 0x6B; /* PC_to_RDR_Escape */          cmd_in[0] = 0x6B; /* PC_to_RDR_Escape */
600          i2dw(length_in - 10, cmd_in+1); /* dwLength */          i2dw(length_in - 10, cmd_in+1); /* dwLength */
601          cmd_in[5] = 0;  /* slot number */          cmd_in[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
602          cmd_in[6] = ccid_descriptor->bSeq++;          cmd_in[6] = (*ccid_descriptor->pbSeq)++;
603          cmd_in[7] = cmd_in[8] = cmd_in[9] = 0; /* RFU */          cmd_in[7] = cmd_in[8] = cmd_in[9] = 0; /* RFU */
604    
605          /* copy the command */          /* copy the command */
606          memcpy(&cmd_in[10], TxBuffer, TxLength);          memcpy(&cmd_in[10], TxBuffer, TxLength);
607    
608          res = WritePort(lun, length_in, cmd_in);          res = WritePort(reader_index, length_in, cmd_in);
609          free(cmd_in);          free(cmd_in);
610          if (res != STATUS_SUCCESS)          if (res != STATUS_SUCCESS)
611          {          {
# Line 257  RESPONSECODE CmdEscape(unsigned int lun, Line 613  RESPONSECODE CmdEscape(unsigned int lun,
613                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
614          }          }
615    
616          res = ReadPort(lun, &length_out, cmd_out);          res = ReadPort(reader_index, &length_out, cmd_out);
617    
618            /* replay the command if NAK
619             * This (generally) happens only for the first command sent to the reader
620             * with the serial protocol so it is not really needed for all the other
621             * ReadPort() calls */
622            if (STATUS_COMM_NAK == res)
623            {
624                    free(cmd_out);
625                    goto again;
626            }
627    
628          if (res != STATUS_SUCCESS)          if (res != STATUS_SUCCESS)
629          {          {
630                  free(cmd_out);                  free(cmd_out);
631                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
632          }          }
633    
634            if (length_out < STATUS_OFFSET+1)
635            {
636                    DEBUG_CRITICAL2("Not enough data received: %d bytes", length_out);
637                    return IFD_COMMUNICATION_ERROR;
638            }
639    
640          if (cmd_out[STATUS_OFFSET] & CCID_COMMAND_FAILED)          if (cmd_out[STATUS_OFFSET] & CCID_COMMAND_FAILED)
641          {          {
642                  ccid_error(cmd_out[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__);    /* bError */                  ccid_error(cmd_out[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__);    /* bError */
# Line 288  RESPONSECODE CmdEscape(unsigned int lun, Line 661  RESPONSECODE CmdEscape(unsigned int lun,
661   *                                      CmdPowerOff   *                                      CmdPowerOff
662   *   *
663   ****************************************************************************/   ****************************************************************************/
664  RESPONSECODE CmdPowerOff(unsigned int lun)  RESPONSECODE CmdPowerOff(unsigned int reader_index)
665  {  {
666          unsigned char cmd[10];          unsigned char cmd[10];
667          status_t res;          status_t res;
668          unsigned int length;          unsigned int length;
669          RESPONSECODE return_value = IFD_SUCCESS;          RESPONSECODE return_value = IFD_SUCCESS;
670          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(lun);          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
671    
672          cmd[0] = 0x63; /* IccPowerOff */          cmd[0] = 0x63; /* IccPowerOff */
673          cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0;  /* dwLength */          cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0;  /* dwLength */
674          cmd[5] = 0;     /* slot number */          cmd[5] = ccid_descriptor->bCurrentSlotIndex;    /* slot number */
675          cmd[6] = ccid_descriptor->bSeq++;          cmd[6] = (*ccid_descriptor->pbSeq)++;
676          cmd[7] = cmd[8] = cmd[9] = 0; /* RFU */          cmd[7] = cmd[8] = cmd[9] = 0; /* RFU */
677    
678          res = WritePort(lun, sizeof(cmd), cmd);          res = WritePort(reader_index, sizeof(cmd), cmd);
679          if (res != STATUS_SUCCESS)          if (res != STATUS_SUCCESS)
680                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
681    
682          length = sizeof(cmd);          length = sizeof(cmd);
683          res = ReadPort(lun, &length, cmd);          res = ReadPort(reader_index, &length, cmd);
684          if (res != STATUS_SUCCESS)          if (res != STATUS_SUCCESS)
685                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
686    
687            if (length < STATUS_OFFSET+1)
688            {
689                    DEBUG_CRITICAL2("Not enough data received: %d bytes", length);
690                    return IFD_COMMUNICATION_ERROR;
691            }
692    
693          if (cmd[STATUS_OFFSET] & CCID_COMMAND_FAILED)          if (cmd[STATUS_OFFSET] & CCID_COMMAND_FAILED)
694          {          {
695                  ccid_error(cmd[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__);    /* bError */                  ccid_error(cmd[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__);    /* bError */
# Line 326  RESPONSECODE CmdPowerOff(unsigned int lu Line 705  RESPONSECODE CmdPowerOff(unsigned int lu
705   *                                      CmdGetSlotStatus   *                                      CmdGetSlotStatus
706   *   *
707   ****************************************************************************/   ****************************************************************************/
708  RESPONSECODE CmdGetSlotStatus(unsigned int lun, unsigned char buffer[])  RESPONSECODE CmdGetSlotStatus(unsigned int reader_index, unsigned char buffer[])
709  {  {
710          unsigned char cmd[10];          unsigned char cmd[10];
711          status_t res;          status_t res;
712          unsigned int length;          unsigned int length;
713          RESPONSECODE return_value = IFD_SUCCESS;          RESPONSECODE return_value = IFD_SUCCESS;
714          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(lun);          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
715    
716          cmd[0] = 0x65; /* GetSlotStatus */          cmd[0] = 0x65; /* GetSlotStatus */
717          cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0;  /* dwLength */          cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0;  /* dwLength */
718          cmd[5] = 0;     /* slot number */          cmd[5] = ccid_descriptor->bCurrentSlotIndex;    /* slot number */
719          cmd[6] = ccid_descriptor->bSeq++;          cmd[6] = (*ccid_descriptor->pbSeq)++;
720          cmd[7] = cmd[8] = cmd[9] = 0; /* RFU */          cmd[7] = cmd[8] = cmd[9] = 0; /* RFU */
721    
722          res = WritePort(lun, sizeof(cmd), cmd);          res = WritePort(reader_index, sizeof(cmd), cmd);
723          if (res != STATUS_SUCCESS)          if (res != STATUS_SUCCESS)
724            {
725                    if (STATUS_NO_SUCH_DEVICE == res)
726                            return IFD_NO_SUCH_DEVICE;
727                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
728            }
729    
730          length = SIZE_GET_SLOT_STATUS;          length = SIZE_GET_SLOT_STATUS;
731          res = ReadPort(lun, &length, buffer);          res = ReadPort(reader_index, &length, buffer);
732          if (res != STATUS_SUCCESS)          if (res != STATUS_SUCCESS)
733                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
734    
735            if (length < STATUS_OFFSET+1)
736            {
737                    DEBUG_CRITICAL2("Not enough data received: %d bytes", length);
738                    return IFD_COMMUNICATION_ERROR;
739            }
740    
741          if (buffer[STATUS_OFFSET] & CCID_COMMAND_FAILED)          if (buffer[STATUS_OFFSET] & CCID_COMMAND_FAILED)
742          {          {
743    #ifdef O2MICRO_OZ776_PATCH
744                    /* the O2MICRO OZ 776 reader sends card absent or mute errors
745                     * when no card is inserted */
746                    if (! ((OZ776 == ccid_descriptor->readerID)
747                            && (buffer[ERROR_OFFSET] == 0xFE)))
748    #endif
749                  ccid_error(buffer[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__);    /* bError */                  ccid_error(buffer[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__);    /* bError */
750                  return_value = IFD_COMMUNICATION_ERROR;  
751                    /* card absent or mute is not an communication error */
752                    if (buffer[ERROR_OFFSET] != 0xFE)
753                            return_value = IFD_COMMUNICATION_ERROR;
754          }          }
755    
756          return return_value;          return return_value;
# Line 364  RESPONSECODE CmdGetSlotStatus(unsigned i Line 762  RESPONSECODE CmdGetSlotStatus(unsigned i
762   *                                      CmdXfrBlock   *                                      CmdXfrBlock
763   *   *
764   ****************************************************************************/   ****************************************************************************/
765  RESPONSECODE CmdXfrBlock(unsigned int lun, unsigned int tx_length,  RESPONSECODE CmdXfrBlock(unsigned int reader_index, unsigned int tx_length,
766          unsigned char tx_buffer[], unsigned int *rx_length,          unsigned char tx_buffer[], unsigned int *rx_length,
767          unsigned char rx_buffer[], int protocol)          unsigned char rx_buffer[], int protocol)
768  {  {
769          RESPONSECODE return_value = IFD_SUCCESS;          RESPONSECODE return_value = IFD_SUCCESS;
770          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(lun);          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
   
         /* command length too big for CCID reader? */  
         if (tx_length > ccid_descriptor->dwMaxCCIDMessageLength)  
         {  
                 DEBUG_CRITICAL3("Command too long (%d bytes) for max: %d bytes",  
                         tx_length, ccid_descriptor->dwMaxCCIDMessageLength);  
                 return_value = IFD_COMMUNICATION_ERROR;  
                 goto clean_up_and_return;  
         }  
   
         /* command length too big for CCID driver? */  
         if (tx_length > CMD_BUF_SIZE)  
         {  
                 DEBUG_CRITICAL3("Command too long (%d bytes) for max: %d bytes",  
                         tx_length, CMD_BUF_SIZE);  
                 return_value = IFD_COMMUNICATION_ERROR;  
                 goto clean_up_and_return;  
         }  
771    
772          /* APDU or TPDU? */          /* APDU or TPDU? */
773          switch (ccid_descriptor->dwFeatures & CCID_CLASS_EXCHANGE_MASK)          switch (ccid_descriptor->dwFeatures & CCID_CLASS_EXCHANGE_MASK)
774          {          {
775                  case CCID_CLASS_TPDU:                  case CCID_CLASS_TPDU:
776                          if (protocol == T_0)                          if (protocol == T_0)
777                                  return_value = CmdXfrBlockTPDU_T0(lun, tx_length, tx_buffer,                                  return_value = CmdXfrBlockTPDU_T0(reader_index,
778                                          rx_length, rx_buffer);                                          tx_length, tx_buffer, rx_length, rx_buffer);
779                          else                          else
780                                  if (protocol == T_1)                                  if (protocol == T_1)
781                                          return_value = CmdXfrBlockTPDU_T1(lun, tx_length,                                          return_value = CmdXfrBlockTPDU_T1(reader_index, tx_length,
782                                                  tx_buffer, rx_length, rx_buffer);                                                  tx_buffer, rx_length, rx_buffer);
783                                  else                                  else
784                                          return_value = IFD_PROTOCOL_NOT_SUPPORTED;                                          return_value = IFD_PROTOCOL_NOT_SUPPORTED;
785                          break;                          break;
786    
787                  case CCID_CLASS_SHORT_APDU:                  case CCID_CLASS_SHORT_APDU:
788                            return_value = CmdXfrBlockTPDU_T0(reader_index,
789                                    tx_length, tx_buffer, rx_length, rx_buffer);
790                            break;
791    
792                  case CCID_CLASS_EXTENDED_APDU:                  case CCID_CLASS_EXTENDED_APDU:
793                          /* We only support extended APDU if the reader can support the                          return_value = CmdXfrBlockAPDU_extended(reader_index,
794                           * command length. See test above */                                  tx_length, tx_buffer, rx_length, rx_buffer);
795                          return_value = CmdXfrBlockTPDU_T0(lun, tx_length, tx_buffer,                          if (return_value != IFD_SUCCESS)
796                                  rx_length, rx_buffer);                                  *rx_length = 0;
797                            break;
798    
799                    case CCID_CLASS_CHARACTER:
800                            if (protocol == T_0)
801                                    return_value = CmdXfrBlockCHAR_T0(reader_index, tx_length,
802                                            tx_buffer, rx_length, rx_buffer);
803                            else
804                                    if (protocol == T_1)
805                                            return_value = CmdXfrBlockTPDU_T1(reader_index, tx_length,
806                                                    tx_buffer, rx_length, rx_buffer);
807                                    else
808                                            return_value = IFD_PROTOCOL_NOT_SUPPORTED;
809                          break;                          break;
810    
811                  default:                  default:
# Line 417  RESPONSECODE CmdXfrBlock(unsigned int lu Line 813  RESPONSECODE CmdXfrBlock(unsigned int lu
813                          return_value = IFD_COMMUNICATION_ERROR;                          return_value = IFD_COMMUNICATION_ERROR;
814          }          }
815    
 clean_up_and_return:  
816          return return_value;          return return_value;
817  } /* CmdXfrBlock */  } /* CmdXfrBlock */
818    
# Line 427  clean_up_and_return: Line 822  clean_up_and_return:
822   *                                      CCID_Transmit   *                                      CCID_Transmit
823   *   *
824   ****************************************************************************/   ****************************************************************************/
825  RESPONSECODE CCID_Transmit(unsigned int lun, unsigned int tx_length,  RESPONSECODE CCID_Transmit(unsigned int reader_index, unsigned int tx_length,
826          const unsigned char tx_buffer[], unsigned char bBWI)          const unsigned char tx_buffer[], unsigned short rx_length, unsigned char bBWI)
827  {  {
828          unsigned char cmd[10+CMD_BUF_SIZE];     /* CCID + APDU buffer */          unsigned char cmd[10+CMD_BUF_SIZE];     /* CCID + APDU buffer */
829          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(lun);          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
830            status_t ret;
831    
832          cmd[0] = 0x6F; /* XfrBlock */          cmd[0] = 0x6F; /* XfrBlock */
833          i2dw(tx_length, cmd+1); /* APDU length */          i2dw(tx_length, cmd+1); /* APDU length */
834          cmd[5] = 0;     /* slot number */          cmd[5] = ccid_descriptor->bCurrentSlotIndex;    /* slot number */
835          cmd[6] = ccid_descriptor->bSeq++;          cmd[6] = (*ccid_descriptor->pbSeq)++;
836          cmd[7] = bBWI;  /* extend block waiting timeout */          cmd[7] = bBWI;  /* extend block waiting timeout */
837          cmd[8] = cmd[9] = 0; /* RFU */          cmd[8] = rx_length & 0xFF;      /* Expected length, in character mode only */
838            cmd[9] = (rx_length >> 8) & 0xFF;
839    
840            /* check that the command is not too large */
841            if (tx_length > CMD_BUF_SIZE)
842            {
843                    DEBUG_CRITICAL2("TX Length too big: %d", tx_length);
844                    return IFD_NOT_SUPPORTED;
845            }
846    
847          memcpy(cmd+10, tx_buffer, tx_length);          memcpy(cmd+10, tx_buffer, tx_length);
848    
849          if (WritePort(lun, 10+tx_length, cmd) != STATUS_SUCCESS)          ret = WritePort(reader_index, 10+tx_length, cmd);
850            if (STATUS_NO_SUCH_DEVICE == ret)
851                    return IFD_NO_SUCH_DEVICE;
852            if (ret != STATUS_SUCCESS)
853                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
854    
855          return IFD_SUCCESS;          return IFD_SUCCESS;
# Line 453  RESPONSECODE CCID_Transmit(unsigned int Line 861  RESPONSECODE CCID_Transmit(unsigned int
861   *                                      CCID_Receive   *                                      CCID_Receive
862   *   *
863   ****************************************************************************/   ****************************************************************************/
864  RESPONSECODE CCID_Receive(unsigned int lun, unsigned int *rx_length,  RESPONSECODE CCID_Receive(unsigned int reader_index, unsigned int *rx_length,
865          unsigned char rx_buffer[])          unsigned char rx_buffer[], unsigned char *chain_parameter)
866  {  {
867          unsigned char cmd[10+CMD_BUF_SIZE];     /* CCID + APDU buffer */          unsigned char cmd[10+CMD_BUF_SIZE];     /* CCID + APDU buffer */
868          unsigned int length;          unsigned int length;
869            RESPONSECODE return_value = IFD_SUCCESS;
870            status_t ret;
871    
872  time_request:  time_request:
873          length = sizeof(cmd);          length = sizeof(cmd);
874          if (ReadPort(lun, &length, cmd) != STATUS_SUCCESS)          ret = ReadPort(reader_index, &length, cmd);
875            if (ret != STATUS_SUCCESS)
876          {          {
877                  *rx_length = 0;                  *rx_length = 0;
878                    if (STATUS_NO_SUCH_DEVICE == ret)
879                            return IFD_NO_SUCH_DEVICE;
880                    return IFD_COMMUNICATION_ERROR;
881            }
882    
883            if (length < STATUS_OFFSET+1)
884            {
885                    DEBUG_CRITICAL2("Not enough data received: %d bytes", length);
886                    *rx_length = 0;
887                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
888          }          }
889    
890          if (cmd[STATUS_OFFSET] & CCID_COMMAND_FAILED)          if (cmd[STATUS_OFFSET] & CCID_COMMAND_FAILED)
891          {          {
892                  ccid_error(cmd[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__);    /* bError */                  ccid_error(cmd[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__);    /* bError */
893                  *rx_length = 0; /* nothing received */                  switch (cmd[ERROR_OFFSET])
894                  if (0xFD == cmd[ERROR_OFFSET]) /* Parity error during exchange */                  {
895                          return IFD_PARITY_ERROR;                          case 0xEF:      /* cancel */
896                  else                                  if (*rx_length < 2)
897                          return IFD_COMMUNICATION_ERROR;                                          return IFD_COMMUNICATION_ERROR;
898                                    rx_buffer[0]= 0x64;
899                                    rx_buffer[1]= 0x01;
900                                    *rx_length = 2;
901                                    return IFD_SUCCESS;
902    
903                            case 0xF0:      /* timeout */
904                                    if (*rx_length < 2)
905                                            return IFD_COMMUNICATION_ERROR;
906                                    rx_buffer[0]= 0x64;
907                                    rx_buffer[1]= 0x00;
908                                    *rx_length = 2;
909                                    return IFD_SUCCESS;
910    
911                            case 0xFD:      /* Parity error during exchange */
912                                    *rx_length = 0; /* nothing received */
913                                    return IFD_PARITY_ERROR;
914    
915                            default:
916                                    *rx_length = 0; /* nothing received */
917                                    return IFD_COMMUNICATION_ERROR;
918                    }
919          }          }
920    
921          if (cmd[STATUS_OFFSET] & CCID_TIME_EXTENSION)          if (cmd[STATUS_OFFSET] & CCID_TIME_EXTENSION)
922          {          {
923                  DEBUG_CRITICAL2("Time extension requested: 0x%02X", cmd[ERROR_OFFSET]);                  DEBUG_COMM2("Time extension requested: 0x%02X", cmd[ERROR_OFFSET]);
924                  goto time_request;                  goto time_request;
925          }          }
926    
927          length = dw2i(cmd, 1);          length = dw2i(cmd, 1);
928          if (length < *rx_length)          if (length <= *rx_length)
929                  *rx_length = length;                  *rx_length = length;
930          else          else
931            {
932                    DEBUG_CRITICAL2("overrun by %d bytes", length - *rx_length);
933                  length = *rx_length;                  length = *rx_length;
934                    return_value = IFD_ERROR_INSUFFICIENT_BUFFER;
935            }
936          memcpy(rx_buffer, cmd+10, length);          memcpy(rx_buffer, cmd+10, length);
937    
938          return IFD_SUCCESS;          /* Extended case?
939             * Only valid for RDR_to_PC_DataBlock frames */
940            if (chain_parameter)
941                    *chain_parameter = cmd[CHAIN_PARAMETER_OFFSET];
942    
943            return return_value;
944  } /* CCID_Receive */  } /* CCID_Receive */
945    
946    
947  /*****************************************************************************  /*****************************************************************************
948   *   *
949     *                                      CmdXfrBlockAPDU_extended
950     *
951     ****************************************************************************/
952    static RESPONSECODE CmdXfrBlockAPDU_extended(unsigned int reader_index,
953            unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
954            unsigned char rx_buffer[])
955    {
956            RESPONSECODE return_value;
957            _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
958            unsigned char chain_parameter;
959            unsigned int local_tx_length, sent_length;
960            unsigned int local_rx_length, received_length;
961            int buffer_overflow = 0;
962    
963            DEBUG_COMM2("T=0 (extended): %d bytes", tx_length);
964    
965            /* send the APDU */
966            sent_length = 0;
967    
968            /* we suppose one command is enough */
969            chain_parameter = 0x00;
970    
971            local_tx_length = tx_length - sent_length;
972            if (local_tx_length > CMD_BUF_SIZE)
973            {
974                    local_tx_length = CMD_BUF_SIZE;
975                    /* the command APDU begins with this command, and continue in the next
976                     * PC_to_RDR_XfrBlock */
977                    chain_parameter = 0x01;
978            }
979            if (local_tx_length > ccid_descriptor->dwMaxCCIDMessageLength-10)
980            {
981                    local_tx_length = ccid_descriptor->dwMaxCCIDMessageLength-10;
982                    chain_parameter = 0x01;
983            }
984    
985    send_next_block:
986            return_value = CCID_Transmit(reader_index, local_tx_length, tx_buffer,
987                    chain_parameter, 0);
988            if (return_value != IFD_SUCCESS)
989                    return return_value;
990    
991            sent_length += local_tx_length;
992            tx_buffer += local_tx_length;
993    
994            /* we just sent the last block (0x02) or only one block was needded (0x00) */
995            if ((0x02 == chain_parameter) || (0x00 == chain_parameter))
996                    goto receive_block;
997    
998            /* read a nul block */
999            return_value = CCID_Receive(reader_index, &local_rx_length, NULL, NULL);
1000            if (return_value != IFD_SUCCESS)
1001                    return return_value;
1002    
1003            /* size of the next block */
1004            if (tx_length - sent_length > local_tx_length)
1005            {
1006                    /* the abData field continues a command APDU and
1007                     * another block is to follow */
1008                    chain_parameter = 0x03;
1009            }
1010            else
1011            {
1012                    /* this abData field continues a command APDU and ends
1013                     * the APDU command */
1014                    chain_parameter = 0x02;
1015    
1016                    /* last (smaller) block */
1017                    local_tx_length = tx_length - sent_length;
1018            }
1019    
1020            goto send_next_block;
1021    
1022    receive_block:
1023            /* receive the APDU */
1024            received_length = 0;
1025    
1026    receive_next_block:
1027            local_rx_length = *rx_length - received_length;
1028            return_value = CCID_Receive(reader_index, &local_rx_length, rx_buffer,
1029                    &chain_parameter);
1030            if (IFD_ERROR_INSUFFICIENT_BUFFER == return_value)
1031            {
1032                    buffer_overflow = 1;
1033    
1034                    /* we continue to read all the response APDU */
1035                    return_value = IFD_SUCCESS;
1036            }
1037    
1038            if (return_value != IFD_SUCCESS)
1039                    return return_value;
1040    
1041            /* advance in the reiceiving buffer */
1042            rx_buffer += local_rx_length;
1043            received_length += local_rx_length;
1044    
1045            switch (chain_parameter)
1046            {
1047                    /* the response APDU begins and ends in this command */
1048                    case 0x00:
1049                    /* this abData field continues the response APDU and ends the response
1050                     * APDU */
1051                    case 0x02:
1052                            break;
1053    
1054                    /* the response APDU begins with this command and is to continue */
1055                    case 0x01:
1056                    /* this abData field continues the response APDU and another block is
1057                     * to follow */
1058                    case 0x03:
1059                    /* empty abData field, continuation of the command APDU is expected in
1060                     * next PC_to_RDR_XfrBlock command */
1061                    case 0x10:
1062                            /* send a nul block */
1063                            return_value = CCID_Transmit(reader_index, 0, NULL, 0, 0);
1064                            if (return_value != IFD_SUCCESS)
1065                                    return return_value;
1066    
1067                            goto receive_next_block;
1068            }
1069    
1070            *rx_length = received_length;
1071    
1072            /* generate an overflow detected by pcscd */
1073            if (buffer_overflow)
1074                    (*rx_length)++;
1075    
1076            return IFD_SUCCESS;
1077    } /* CmdXfrBlockAPDU_extended */
1078    
1079    
1080    /*****************************************************************************
1081     *
1082   *                                      CmdXfrBlockTPDU_T0   *                                      CmdXfrBlockTPDU_T0
1083   *   *
1084   ****************************************************************************/   ****************************************************************************/
1085  static RESPONSECODE CmdXfrBlockTPDU_T0(unsigned int lun, unsigned int tx_length,  static RESPONSECODE CmdXfrBlockTPDU_T0(unsigned int reader_index,
1086          unsigned char tx_buffer[], unsigned int *rx_length,          unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
1087          unsigned char rx_buffer[])          unsigned char rx_buffer[])
1088  {  {
1089          RESPONSECODE return_value = IFD_SUCCESS;          RESPONSECODE return_value = IFD_SUCCESS;
1090            _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
1091    
1092          DEBUG_COMM2("T=0: %d bytes", tx_length);          DEBUG_COMM2("T=0: %d bytes", tx_length);
1093    
1094          return_value = CCID_Transmit(lun, tx_length, tx_buffer, 0);          /* command length too big for CCID reader? */
1095            if (tx_length > ccid_descriptor->dwMaxCCIDMessageLength-10)
1096            {
1097                    DEBUG_CRITICAL3("Command too long (%d bytes) for max: %d bytes",
1098                                    tx_length, ccid_descriptor->dwMaxCCIDMessageLength-10);
1099                    return IFD_COMMUNICATION_ERROR;
1100            }
1101    
1102            /* command length too big for CCID driver? */
1103            if (tx_length > CMD_BUF_SIZE)
1104            {
1105                    DEBUG_CRITICAL3("Command too long (%d bytes) for max: %d bytes",
1106                                    tx_length, CMD_BUF_SIZE);
1107                    return IFD_COMMUNICATION_ERROR;
1108            }
1109    
1110            return_value = CCID_Transmit(reader_index, tx_length, tx_buffer, 0, 0);
1111          if (return_value != IFD_SUCCESS)          if (return_value != IFD_SUCCESS)
1112                  return return_value;                  return return_value;
1113    
1114          return CCID_Receive(lun, rx_length, rx_buffer);          return CCID_Receive(reader_index, rx_length, rx_buffer, NULL);
1115  } /* CmdXfrBlockTPDU_T0 */  } /* CmdXfrBlockTPDU_T0 */
1116    
1117    
1118  /*****************************************************************************  /*****************************************************************************
1119   *   *
1120     *                                      T0CmdParsing
1121     *
1122     ****************************************************************************/
1123    static RESPONSECODE T0CmdParsing(unsigned char *cmd, unsigned int cmd_len,
1124            unsigned int *exp_len)
1125    {
1126            *exp_len = 0;
1127    
1128            /* Ref: 7816-4 Annex A */
1129            switch (cmd_len)
1130            {
1131                    case 4: /* Case 1 */
1132                            *exp_len = 2; /* SW1 and SW2 only */
1133                            break;
1134    
1135                    case 5: /* Case 2 */
1136                            if (cmd[4] != 0)
1137                                    *exp_len = cmd[4] + 2;
1138                            else
1139                                    *exp_len = 256 + 2;
1140                            break;
1141    
1142                    default: /* Case 3 */
1143                            if (cmd_len > 5 && cmd_len == (unsigned int)(cmd[4] + 5))
1144                                    *exp_len = 2; /* SW1 and SW2 only */
1145                            else
1146                                    return IFD_COMMUNICATION_ERROR; /* situation not supported */
1147                            break;
1148            }
1149    
1150            return IFD_SUCCESS;
1151    } /* T0CmdParsing */
1152    
1153    
1154    /*****************************************************************************
1155     *
1156     *                                      T0ProcACK
1157     *
1158     ****************************************************************************/
1159    static RESPONSECODE T0ProcACK(unsigned int reader_index,
1160            unsigned char **snd_buf, unsigned int *snd_len,
1161            unsigned char **rcv_buf, unsigned int *rcv_len,
1162            unsigned char **in_buf, unsigned int *in_len,
1163            unsigned int proc_len, int is_rcv)
1164    {
1165            RESPONSECODE return_value;
1166            unsigned int remain_len;
1167            unsigned char tmp_buf[512];
1168            unsigned int ret_len;
1169    
1170            DEBUG_COMM2("Enter, is_rcv = %d", is_rcv);
1171    
1172            if (is_rcv == 1)
1173            {       /* Receiving mode */
1174                    if (*in_len > 0)
1175                    {       /* There are still available data in our buffer */
1176                            if (*in_len >= proc_len)
1177                            {
1178                                    /* We only need to get the data from our buffer */
1179                                    memcpy(*rcv_buf, *in_buf, proc_len);
1180                                    *rcv_buf += proc_len;
1181                                    *in_buf += proc_len;
1182                                    *rcv_len += proc_len;
1183                                    *in_len -= proc_len;
1184    
1185                                    return IFD_SUCCESS;
1186                            }
1187                            else
1188                            {
1189                                    /* Move all data in the input buffer to the reply buffer */
1190                                    remain_len = proc_len - *in_len;
1191                                    memcpy(*rcv_buf, *in_buf, *in_len);
1192                                    *rcv_buf += *in_len;
1193                                    *in_buf += *in_len;
1194                                    *rcv_len += *in_len;
1195                                    *in_len = 0;
1196                            }
1197                    }
1198                    else
1199                            /* There is no data in our tmp_buf,
1200                             * we have to read all data we needed */
1201                            remain_len = proc_len;
1202    
1203                    /* Read the expected data from the smartcard */
1204                    if (*in_len != 0)
1205                    {
1206                            DEBUG_CRITICAL("*in_len != 0");
1207                            return IFD_COMMUNICATION_ERROR;
1208                    }
1209    
1210                    memset(tmp_buf, 0, sizeof(tmp_buf));
1211    
1212    #ifdef O2MICRO_OZ776_PATCH
1213                    if((0 != remain_len) && (0 == (remain_len + 10) % 64))
1214            {
1215                            /* special hack to avoid a command of size modulo 64
1216                             * we send two commands instead */
1217                ret_len = 1;
1218                return_value = CCID_Transmit(reader_index, 0, *snd_buf, ret_len, 0);
1219                if (return_value != IFD_SUCCESS)
1220                    return return_value;
1221                return_value = CCID_Receive(reader_index, &ret_len, tmp_buf, NULL);
1222                if (return_value != IFD_SUCCESS)
1223                    return return_value;
1224    
1225                ret_len = remain_len - 1;
1226                return_value = CCID_Transmit(reader_index, 0, *snd_buf, ret_len, 0);
1227                if (return_value != IFD_SUCCESS)
1228                    return return_value;
1229                return_value = CCID_Receive(reader_index, &ret_len, &tmp_buf[1],
1230                                    NULL);
1231                if (return_value != IFD_SUCCESS)
1232                    return return_value;
1233    
1234                ret_len += 1;
1235            }
1236            else
1237    #endif
1238                    {
1239                            ret_len = remain_len;
1240                            return_value = CCID_Transmit(reader_index, 0, *snd_buf, ret_len, 0);
1241                            if (return_value != IFD_SUCCESS)
1242                                    return return_value;
1243    
1244                            return_value = CCID_Receive(reader_index, &ret_len, tmp_buf, NULL);
1245                            if (return_value != IFD_SUCCESS)
1246                                    return return_value;
1247                    }
1248                    memcpy(*rcv_buf, tmp_buf, remain_len);
1249                    *rcv_buf += remain_len, *rcv_len += remain_len;
1250    
1251                    /* If ret_len != remain_len, our logic is erroneous */
1252                    if (ret_len != remain_len)
1253                    {
1254                            DEBUG_CRITICAL("ret_len != remain_len");
1255                            return IFD_COMMUNICATION_ERROR;
1256                    }
1257            }
1258            else
1259            {       /* Sending mode */
1260    
1261                    return_value = CCID_Transmit(reader_index, proc_len, *snd_buf, 1, 0);
1262                    if (return_value != IFD_SUCCESS)
1263                            return return_value;
1264    
1265                    *snd_len -= proc_len;
1266                    *snd_buf += proc_len;
1267            }
1268    
1269            DEBUG_COMM("Exit");
1270    
1271            return IFD_SUCCESS;
1272    } /* T0ProcACK */
1273    
1274    
1275    /*****************************************************************************
1276     *
1277     *                                      T0ProcSW1
1278     *
1279     ****************************************************************************/
1280    static RESPONSECODE T0ProcSW1(unsigned int reader_index,
1281            unsigned char *rcv_buf, unsigned int *rcv_len,
1282            unsigned char *in_buf, unsigned int in_len)
1283    {
1284            RESPONSECODE return_value = IFD_SUCCESS;
1285            UCHAR tmp_buf[512];
1286            unsigned char *rcv_buf_tmp = rcv_buf;
1287            const unsigned int rcv_len_tmp = *rcv_len;
1288            unsigned char sw1, sw2;
1289    
1290            /* store the SW1 */
1291            sw1 = *rcv_buf = *in_buf;
1292            rcv_buf++;
1293            in_buf++;
1294            in_len--;
1295            (*rcv_len)++;
1296    
1297            /* store the SW2 */
1298            if (0 == in_len)
1299            {
1300                    return_value = CCID_Transmit(reader_index, 0, rcv_buf, 1, 0);
1301                    if (return_value != IFD_SUCCESS)
1302                            return return_value;
1303    
1304                    in_len = 1;
1305    
1306                    return_value = CCID_Receive(reader_index, &in_len, tmp_buf, NULL);
1307                    if (return_value != IFD_SUCCESS)
1308                            return return_value;
1309    
1310                    in_buf = tmp_buf;
1311            }
1312            sw2 = *rcv_buf = *in_buf;
1313            rcv_buf++;
1314            in_buf++;
1315            in_len--;
1316            (*rcv_len)++;
1317    
1318            if (return_value != IFD_SUCCESS)
1319            {
1320                    rcv_buf_tmp[0] = rcv_buf_tmp[1] = 0;
1321                    *rcv_len = rcv_len_tmp;
1322            }
1323    
1324            DEBUG_COMM3("Exit: SW=%02X %02X", sw1, sw2);
1325    
1326            return return_value;
1327    } /* T0ProcSW1 */
1328    
1329    
1330    /*****************************************************************************
1331     *
1332     *                                      CmdXfrBlockCHAR_T0
1333     *
1334     ****************************************************************************/
1335    static RESPONSECODE CmdXfrBlockCHAR_T0(unsigned int reader_index,
1336            unsigned int snd_len, unsigned char snd_buf[], unsigned int *rcv_len,
1337            unsigned char rcv_buf[])
1338    {
1339            int is_rcv;
1340            unsigned char cmd[5];
1341            unsigned char tmp_buf[512];
1342            unsigned int exp_len, in_len;
1343            unsigned char ins, *in_buf;
1344            RESPONSECODE return_value = IFD_SUCCESS;
1345    
1346            DEBUG_COMM2("T=0: %d bytes", snd_len);
1347    
1348            in_buf = tmp_buf;
1349            in_len = 0;
1350            *rcv_len = 0;
1351    
1352            return_value = T0CmdParsing(snd_buf, snd_len, &exp_len);
1353            if (return_value != IFD_SUCCESS)
1354            {
1355                    DEBUG_CRITICAL("T0CmdParsing failed");
1356                    return IFD_COMMUNICATION_ERROR;
1357            }
1358    
1359            if (snd_len == 5 || snd_len == 4)
1360                    is_rcv = 1;
1361            else
1362                    is_rcv = 0;
1363    
1364            /* Command to send to the smart card (must be 5 bytes, from 7816 p.15) */
1365            memset(cmd, 0, sizeof(cmd));
1366            if (snd_len == 4)
1367            {
1368                    memcpy(cmd, snd_buf, 4);
1369                    snd_buf += 4;
1370                    snd_len -= 4;
1371            }
1372            else
1373            {
1374                    memcpy(cmd, snd_buf, 5);
1375                    snd_buf += 5;
1376                    snd_len -= 5;
1377            }
1378    
1379            /* Make sure this is a valid command by checking the INS field */
1380            ins = cmd[1];
1381            if ((ins & 0xF0) == 0x60 ||     /* 7816-3 8.3.2 */
1382                    (ins & 0xF0) == 0x90)
1383            {
1384                    DEBUG_CRITICAL2("fatal: INS (0x%02X) = 0x6X or 0x9X", ins);
1385                    return IFD_COMMUNICATION_ERROR;
1386            }
1387    
1388            return_value = CCID_Transmit(reader_index, 5, cmd, 1, 0);
1389            if (return_value != IFD_SUCCESS)
1390                    return return_value;
1391    
1392            while (1)
1393            {
1394                    if (in_len == 0)
1395                    {
1396                            in_len = 1;
1397                            return_value = CCID_Receive(reader_index, &in_len, tmp_buf, NULL);
1398                            if (return_value != IFD_SUCCESS)
1399                            {
1400                                    DEBUG_CRITICAL("CCID_Receive failed");
1401                                    return return_value;
1402                            }
1403                            in_buf = tmp_buf;
1404                    }
1405                    if (in_len == 0)
1406                    {
1407                            /* Suppose we should be able to get data.
1408                             * If not, error. Set the time-out error */
1409                            DEBUG_CRITICAL("error: in_len = 0");
1410                            return IFD_RESPONSE_TIMEOUT;
1411                    }
1412    
1413                    /* Start to process the procedure bytes */
1414                    if (*in_buf == 0x60)
1415                    {
1416                            in_len = 0;
1417                            return_value = CCID_Transmit(reader_index, 0, cmd, 1, 0);
1418    
1419                            if (return_value != IFD_SUCCESS)
1420                                    return return_value;
1421    
1422                            continue;
1423                    }
1424                    else if (*in_buf == ins || *in_buf == (ins ^ 0x01))
1425                    {
1426                            /* ACK => To transfer all remaining data bytes */
1427                            in_buf++, in_len--;
1428                            if (is_rcv)
1429                                    return_value = T0ProcACK(reader_index, &snd_buf, &snd_len,
1430                                            &rcv_buf, rcv_len, &in_buf, &in_len, exp_len - *rcv_len, 1);
1431                            else
1432                                    return_value = T0ProcACK(reader_index, &snd_buf, &snd_len,
1433                                            &rcv_buf, rcv_len, &in_buf, &in_len, snd_len, 0);
1434    
1435                            if (*rcv_len == exp_len)
1436                                    return return_value;
1437    
1438                            continue;
1439                    }
1440                    else if (*in_buf == (ins ^ 0xFF) || *in_buf == (ins ^ 0xFE))
1441                    {
1442                            /* ACK => To transfer 1 remaining bytes */
1443                            in_buf++, in_len--;
1444                            return_value = T0ProcACK(reader_index, &snd_buf, &snd_len,
1445                                    &rcv_buf, rcv_len, &in_buf, &in_len, 1, is_rcv);
1446    
1447                            if (return_value != IFD_SUCCESS)
1448                                    return return_value;
1449    
1450                            continue;
1451                    }
1452                    else if ((*in_buf & 0xF0) == 0x60 || (*in_buf & 0xF0) == 0x90)
1453                            /* SW1 */
1454                            return T0ProcSW1(reader_index, rcv_buf, rcv_len, in_buf, in_len);
1455    
1456                    /* Error, unrecognized situation found */
1457                    DEBUG_CRITICAL2("Unrecognized Procedure byte (0x%02X) found!", *in_buf);
1458                    return return_value;
1459            }
1460    
1461            return return_value;
1462    } /* CmdXfrBlockCHAR_T0 */
1463    
1464    
1465    /*****************************************************************************
1466     *
1467   *                                      CmdXfrBlockTPDU_T1   *                                      CmdXfrBlockTPDU_T1
1468   *   *
1469   ****************************************************************************/   ****************************************************************************/
1470  static RESPONSECODE CmdXfrBlockTPDU_T1(unsigned int lun, unsigned int tx_length,  static RESPONSECODE CmdXfrBlockTPDU_T1(unsigned int reader_index,
1471          unsigned char tx_buffer[], unsigned int *rx_length,          unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
1472          unsigned char rx_buffer[])          unsigned char rx_buffer[])
1473  {  {
1474          RESPONSECODE return_value = IFD_SUCCESS;          RESPONSECODE return_value = IFD_SUCCESS;
1475          int ret;          int ret;
1476    
1477          DEBUG_COMM2("T=1: %d bytes", tx_length);          DEBUG_COMM3("T=1: %d and %d bytes", tx_length, *rx_length);
1478    
1479          ret = t1_transceive(&((get_ccid_slot(lun)) -> t1), 0, tx_buffer, tx_length, rx_buffer, *rx_length);          ret = t1_transceive(&((get_ccid_slot(reader_index)) -> t1), 0,
1480                    tx_buffer, tx_length, rx_buffer, *rx_length);
1481    
1482          if (ret < 0)          if (ret < 0)
1483          {          {
# Line 548  static RESPONSECODE CmdXfrBlockTPDU_T1(u Line 1496  static RESPONSECODE CmdXfrBlockTPDU_T1(u
1496   *                                      SetParameters   *                                      SetParameters
1497   *   *
1498   ****************************************************************************/   ****************************************************************************/
1499  RESPONSECODE SetParameters(unsigned int lun, char protocol, unsigned int length,  RESPONSECODE SetParameters(unsigned int reader_index, char protocol,
1500          unsigned char buffer[])          unsigned int length, unsigned char buffer[])
1501  {  {
1502          unsigned char cmd[10+CMD_BUF_SIZE];     /* CCID + APDU buffer */          unsigned char cmd[10+CMD_BUF_SIZE];     /* CCID + APDU buffer */
1503          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(lun);          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
1504    
1505          DEBUG_COMM2("length: %d bytes", length);          DEBUG_COMM2("length: %d bytes", length);
1506    
1507          cmd[0] = 0x61; /* SetParameters */          cmd[0] = 0x61; /* SetParameters */
1508          i2dw(length, cmd+1);    /* APDU length */          i2dw(length, cmd+1);    /* APDU length */
1509          cmd[5] = 0;     /* slot number */          cmd[5] = ccid_descriptor->bCurrentSlotIndex;    /* slot number */
1510          cmd[6] = ccid_descriptor->bSeq++;          cmd[6] = (*ccid_descriptor->pbSeq)++;
1511          cmd[7] = protocol;      /* bProtocolNum */          cmd[7] = protocol;      /* bProtocolNum */
1512          cmd[8] = cmd[9] = 0; /* RFU */          cmd[8] = cmd[9] = 0; /* RFU */
1513    
1514            /* check that the command is not too large */
1515            if (length > CMD_BUF_SIZE)
1516                    return IFD_NOT_SUPPORTED;
1517    
1518          memcpy(cmd+10, buffer, length);          memcpy(cmd+10, buffer, length);
1519    
1520          if (WritePort(lun, 10+length, cmd) != STATUS_SUCCESS)          if (WritePort(reader_index, 10+length, cmd) != STATUS_SUCCESS)
1521                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
1522    
1523          length = sizeof(cmd);          length = sizeof(cmd);
1524          if (ReadPort(lun, &length, cmd) != STATUS_SUCCESS)          if (ReadPort(reader_index, &length, cmd) != STATUS_SUCCESS)
1525                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
1526    
1527            if (length < STATUS_OFFSET+1)
1528            {
1529                    DEBUG_CRITICAL2("Not enough data received: %d bytes", length);
1530                    return IFD_COMMUNICATION_ERROR;
1531            }
1532    
1533          if (cmd[STATUS_OFFSET] & CCID_COMMAND_FAILED)          if (cmd[STATUS_OFFSET] & CCID_COMMAND_FAILED)
1534          {          {
1535                  ccid_error(cmd[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__);    /* bError */                  ccid_error(cmd[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__);    /* bError */
1536                  return IFD_COMMUNICATION_ERROR;                  if (0x00 == cmd[ERROR_OFFSET])  /* command not supported */
1537                            return IFD_NOT_SUPPORTED;
1538                    else
1539                            if ((cmd[ERROR_OFFSET] >= 1) && (cmd[ERROR_OFFSET] <= 127))
1540                                    /* a parameter is not changeable */
1541                                    return IFD_SUCCESS;
1542                            else
1543                                    return IFD_COMMUNICATION_ERROR;
1544          }          }
1545    
1546          return IFD_SUCCESS;          return IFD_SUCCESS;
# Line 582  RESPONSECODE SetParameters(unsigned int Line 1548  RESPONSECODE SetParameters(unsigned int
1548    
1549    
1550  /*****************************************************************************  /*****************************************************************************
1551     *
1552     *                                      isCharLevel
1553     *
1554     ****************************************************************************/
1555    int isCharLevel(int reader_index)
1556    {
1557            return CCID_CLASS_CHARACTER == (get_ccid_descriptor(reader_index)->dwFeatures & CCID_CLASS_EXCHANGE_MASK);
1558    } /* isCharLevel */
1559    
1560    
1561    /*****************************************************************************
1562   *   *
1563   *                                      i2dw   *                                      i2dw
1564   *   *

Legend:
Removed from v.1076  
changed lines
  Added in v.2406

  ViewVC Help
Powered by ViewVC 1.1.5