/[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 904 by rousseau, Wed May 26 07:50:07 2004 UTC revision 1675 by rousseau, Mon Sep 26 14:42:26 2005 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 <pcsclite.h>  #include <PCSC/pcsclite.h>
27  #include <ifdhandler.h>  #include <PCSC/ifdhandler.h>
28    
29  #include "commands.h"  #include "commands.h"
30  #include "protocol_t1/protocol_t1.h"  #include "openct/proto-t1.h"
31  #include "ccid.h"  #include "ccid.h"
32  #include "defs.h"  #include "defs.h"
33  #include "ccid_ifdhandler.h"  #include "ccid_ifdhandler.h"
34  #include "config.h"  #include "config.h"
35  #include "debug.h"  #include "debug.h"
36    
37    /*
38     * Possible values :
39     * 3 -> 1.8V, 3V, 5V
40     * 2 -> 3V, 5V
41     * 1 -> 5V only
42     */
43    /*
44     * To be safe we only use 5V
45     * otherwise we would have to parse the ATR and get the value of TAi (i>2) when
46     * in T=15
47     */
48    #define DEFAULT_VOLTAGE 1 /* start with 5 volts */
49    
50    #define max( a, b )   ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) )
51    
52    /* internal functions */
53    static RESPONSECODE CmdXfrBlockTPDU_T0(unsigned int reader_index,
54            unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
55            unsigned char rx_buffer[]);
56    
57    static RESPONSECODE CmdXfrBlockCHAR_T0(unsigned int reader_index, unsigned int
58            tx_length, unsigned char tx_buffer[], unsigned int *rx_length, unsigned
59            char rx_buffer[]);
60    
61    static RESPONSECODE CmdXfrBlockTPDU_T1(unsigned int reader_index,
62            unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
63            unsigned char rx_buffer[]);
64    
65    static void i2dw(int value, unsigned char *buffer);
66    
67    
68  /*****************************************************************************  /*****************************************************************************
69   *   *
70   *                                      CmdPowerOn   *                                      CmdPowerOn
71   *   *
72   ****************************************************************************/   ****************************************************************************/
73  RESPONSECODE CmdPowerOn(int lun, unsigned int * nlength, unsigned char buffer[])  RESPONSECODE CmdPowerOn(unsigned int reader_index, unsigned int * nlength,
74            unsigned char buffer[])
75  {  {
76          unsigned char cmd[10];          unsigned char cmd[10];
77          status_t res;          status_t res;
78          int atr_len, length, count = 1;          int length, count = 1;
79            unsigned int atr_len;
80          RESPONSECODE return_value = IFD_SUCCESS;          RESPONSECODE return_value = IFD_SUCCESS;
81          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(lun);          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
82            char voltage;
83    
84          /* store length of buffer[] */          /* store length of buffer[] */
85          length = *nlength;          length = *nlength;
86    
87            if (ccid_descriptor->dwFeatures & CCID_CLASS_AUTO_VOLTAGE)
88                    voltage = 0;    /* automatic voltage selection */
89            else
90                    voltage = DEFAULT_VOLTAGE;
91    
92  again:  again:
93          cmd[0] = 0x62; /* IccPowerOn */          cmd[0] = 0x62; /* IccPowerOn */
94          cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0;  /* dwLength */          cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0;  /* dwLength */
95          cmd[5] = 0;     /* slot number */          cmd[5] = ccid_descriptor->bCurrentSlotIndex;    /* slot number */
96          cmd[6] = ccid_descriptor->bSeq++;          cmd[6] = (*ccid_descriptor->pbSeq)++;
97          if (ccid_descriptor->dwFeatures & CCID_CLASS_AUTO_VOLTAGE)          cmd[7] = voltage;
                 cmd[7] = 0x00;  /* Automatic voltage selection */  
         else  
                 cmd[7] = 0x01;  /* 5.0V */  
98          cmd[8] = cmd[9] = 0; /* RFU */          cmd[8] = cmd[9] = 0; /* RFU */
99    
100          res = WritePort(lun, sizeof(cmd), cmd);          res = WritePort(reader_index, sizeof(cmd), cmd);
101          if (res != STATUS_SUCCESS)          if (res != STATUS_SUCCESS)
102                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
103    
# Line 69  again: Line 105  again:
105          /* needed if we go back after a switch to ISO mode */          /* needed if we go back after a switch to ISO mode */
106          *nlength = length;          *nlength = length;
107    
108          res = ReadPort(lun, nlength, buffer);          res = ReadPort(reader_index, nlength, buffer);
109          if (res != STATUS_SUCCESS)          if (res != STATUS_SUCCESS)
110                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
111    
112          if (buffer[STATUS_OFFSET] & CCID_COMMAND_FAILED)          if (buffer[STATUS_OFFSET] & CCID_COMMAND_FAILED)
113          {          {
114                  ccid_error(buffer[ERROR_OFFSET], __FILE__, __LINE__);    /* bError */                  ccid_error(buffer[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__);    /* bError */
115    
116                  /* Protocol error in EMV mode */                  if (0xBB == buffer[ERROR_OFFSET] &&     /* Protocol error in EMV mode */
117                  if (buffer[ERROR_OFFSET] == 0xBB &&                          ((GEMPC433 == ccid_descriptor->readerID)
118                          ccid_descriptor->readerID == GEMPC433)                          || (CHERRYXX33 == ccid_descriptor->readerID)))
119                  {                  {
120                          unsigned char cmd[] = "\x1F\x01";                          unsigned char cmd[] = {0x1F, 0x01};
121                          unsigned char res[1];                          unsigned char res[1];
122                          unsigned int res_length = sizeof(res);                          unsigned int res_length = sizeof(res);
123    
124                          if ((return_value = CmdEscape(lun, cmd, sizeof(cmd)-1, res,                          if ((return_value = CmdEscape(reader_index, cmd, sizeof(cmd), res,
125                                  &res_length)) != IFD_SUCCESS)                                  &res_length)) != IFD_SUCCESS)
126                                  return return_value;                                  return return_value;
127    
# Line 96  again: Line 132  again:
132                                  DEBUG_CRITICAL("Can't set reader in ISO mode");                                  DEBUG_CRITICAL("Can't set reader in ISO mode");
133                  }                  }
134    
135                    /* continue with 3 volts and 5 volts */
136                    if (voltage > 1)
137                    {
138                            voltage--;
139                            goto again;
140                    }
141    
142                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
143          }          }
144    
# Line 106  again: Line 149  again:
149          else          else
150                  *nlength = atr_len;                  *nlength = atr_len;
151    
152          memcpy(buffer, buffer+10, atr_len);          memmove(buffer, buffer+10, atr_len);
153    
154          return return_value;          return return_value;
155  } /* CmdPowerOn */  } /* CmdPowerOn */
# Line 114  again: Line 157  again:
157    
158  /*****************************************************************************  /*****************************************************************************
159   *   *
160   *                                      SecurePIN   *                                      SecurePINVerify
161   *   *
162   ****************************************************************************/   ****************************************************************************/
163  RESPONSECODE SecurePIN(int lun, const unsigned char TxBuffer[],  RESPONSECODE SecurePINVerify(unsigned int reader_index,
164          unsigned int TxLength, unsigned char RxBuffer[], unsigned int *RxLength)          const unsigned char TxBuffer[], unsigned int TxLength,
165            unsigned char RxBuffer[], unsigned int *RxLength)
166  {  {
167          unsigned char cmd[11+14+CMD_BUF_SIZE];          unsigned char cmd[11+14+CMD_BUF_SIZE];
168          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(lun);          unsigned int a, b;
169          int length = 0;          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
170            int old_read_timeout;
171            RESPONSECODE ret;
172    
173          /* PIN verification data structure WITHOUT TeoPrologue */          cmd[0] = 0x69;  /* Secure */
174          if (TxBuffer[4] /* Lc */          cmd[5] = ccid_descriptor->bCurrentSlotIndex;    /* slot number */
175                  + 5 /* CLA, INS, P1, P2, Lc */          cmd[6] = (*ccid_descriptor->pbSeq)++;
176                  + 11 /* CCID PIN verification data structure */ == TxLength)          cmd[7] = 0;             /* bBWI */
177          {          cmd[8] = 0;             /* wLevelParameter */
178                  i2dw(TxLength+3+1, cmd+1);      /* command length */          cmd[9] = 0;
179            cmd[10] = 0;    /* bPINOperation: PIN Verification */
180    
181                  /* copy the CCID data structure */          /* 19 is the size of the PCSCv2 PIN verify structure
182                  memcpy(cmd +11, TxBuffer + TxBuffer[4] + 5, 11);           * The equivalent CCID structure is only 14-bytes long */
183            if (TxLength > 19+CMD_BUF_SIZE) /* command too large? */
184            {
185                    DEBUG_INFO3("Command too long: %d > %d", TxLength, 16+CMD_BUF_SIZE);
186                    *RxLength = 0;
187                    return IFD_NOT_SUPPORTED;
188            }
189    
190                  /* TeoPrologue not used */          if (TxLength < 19+4 /* 4 = APDU size */)        /* command too short? */
191                  memset(cmd +11 +11, 0, 3);          {
192                    DEBUG_INFO3("Command too short: %d < %d", TxLength, 19+4);
193                    *RxLength = 0;
194                    return IFD_NOT_SUPPORTED;
195            }
196    
197                  /* copy the APDU */          if (dw2i(TxBuffer, 15) + 19 != TxLength) /* ulDataLength field coherency */
198                  memcpy(cmd +11 +14, TxBuffer, TxLength-11);          {
199                    DEBUG_INFO3("Wrong lengths: %d %d", TxBuffer[15] + 19, TxLength);
200                    *RxLength = 0;
201                    return IFD_NOT_SUPPORTED;
202            }
203    
204                  length = 14 + TxLength;          /* Build a CCID block from a PC/SC V2.1.2 Part 10 block */
205            for (a = 11, b = 0; b < TxLength; b++)
206            {
207                    if (1 == b) /* bTimeOut2 field */
208                            /* Ignore the second timeout as there's nothing we can do with
209                             * it currently */
210                            continue;
211    
212                    if ((b >= 15) && (b <= 18)) /* ulDataLength field (4 bytes) */
213                            /* the ulDataLength field is not present in the CCID frame
214                             * so do not copy */
215                            continue;
216    
217                    /* copy the CCID block 'verbatim' */
218                    cmd[a] = TxBuffer[b];
219                    a++;
220          }          }
221          /* PIN verification data structure WITH TeoPrologue */  
222          else if (TxBuffer[4] /* Lc */          /* SPR532 and Case 1 APDU */
223                  + 5 /* CLA, INS, P1, P2, Lc */          if ((SPR532 == ccid_descriptor->readerID) && (TxBuffer[15] == 4))
                 + 14 /* CCID PIN verification data structure */ == TxLength)  
224          {          {
225                  i2dw(TxLength+1, cmd+1);        /* command length */                  RESPONSECODE return_value;
226                    unsigned char cmd[] = { 0x80, 0x02, 0x00 };
227                    unsigned char res[1];
228                    unsigned int res_length = sizeof(res);
229    
230                    /* the SPR532 will append the PIN code without any padding */
231                    return_value = CmdEscape(reader_index, cmd, sizeof(cmd), res,
232                            &res_length);
233                    if (return_value != IFD_SUCCESS)
234                    {
235                            ccid_error(res[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__);
236                            return return_value;
237                    }
238            }
239    
240                  /* copy the CCID data structure */          i2dw(a - 10, cmd + 1);  /* CCID message length */
                 memcpy(cmd +11, TxBuffer + TxBuffer[4] + 5, 14);  
241    
242                  /* copy the APDU */          old_read_timeout = ccid_descriptor -> readTimeout;
243                  memcpy(cmd +11 +14, TxBuffer, TxLength-14);          ccid_descriptor -> readTimeout = max(30, TxBuffer[0]);  /* at least 30 seconds */
244    
245                  length = 11 + TxLength;          if (WritePort(reader_index, a, cmd) != STATUS_SUCCESS)
         }  
         else  
         {  
                 *RxLength = 0;  
246                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
247          }  
248            ret = CCID_Receive(reader_index, RxLength, RxBuffer);
249    
250            ccid_descriptor -> readTimeout = old_read_timeout;
251            return ret;
252    } /* SecurePINVerify */
253    
254    
255    /*****************************************************************************
256     *
257     *                                      SecurePINModify
258     *
259     ****************************************************************************/
260    RESPONSECODE SecurePINModify(unsigned int reader_index,
261            const unsigned char TxBuffer[], unsigned int TxLength,
262            unsigned char RxBuffer[], unsigned int *RxLength)
263    {
264            unsigned char cmd[11+19+CMD_BUF_SIZE];
265            unsigned int a, b;
266            _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
267    
268          cmd[0] = 0x69;  /* Secure */          cmd[0] = 0x69;  /* Secure */
269          cmd[5] = 0;             /* slot number */          cmd[5] = ccid_descriptor->bCurrentSlotIndex;    /* slot number */
270          cmd[6] = ccid_descriptor->bSeq++;          cmd[6] = (*ccid_descriptor->pbSeq)++;
271          cmd[7] = 0;             /* bBWI */          cmd[7] = 0;             /* bBWI */
272          cmd[8] = 0;             /* wLevelParameter */          cmd[8] = 0;             /* wLevelParameter */
273          cmd[9] = 0;          cmd[9] = 0;
274          cmd[10] = 0;    /* bPINOperation: PIN Verification */          cmd[10] = 1;    /* bPINOperation: PIN Modification */
275    
276          if (WritePort(lun, length, cmd) != STATUS_SUCCESS)          /* 24 is the size of the PCSC PIN modify structure
277                  return IFD_COMMUNICATION_ERROR;           * The equivalent CCID structure is only 18 or 19-bytes long */
278            if ((TxLength > 19+CMD_BUF_SIZE) /* command too large? */
279                    || (TxLength < 18+4 /* 4 = APDU size */) /* command too short? */
280                    || (TxBuffer[20] + 24 != TxLength)) /* ulDataLength field coherency */
281                    return IFD_NOT_SUPPORTED;
282    
283            /* Make sure in the beginning if bNumberMessage is valid or not */
284            if (TxBuffer[11] > 3)
285                    return IFD_NOT_SUPPORTED;
286    
287            /* Build a CCID block from a PC/SC V2.1.2 Part 10 block */
288    
289            /* Do adjustments as needed - CCID spec is not exact with some
290             * details in the format of the structure, per-reader adaptions
291             * might be needed.
292             */
293            for (a = 11, b = 0; b < TxLength; b++)
294            {
295                    if (1 == b) /* bTimeOut2 */
296                            /* Ignore the second timeout as there's nothing we can do with it
297                             * currently */
298                            continue;
299    
300          return CCID_Receive(lun, RxLength, RxBuffer);                  if (16 == b) /* bMsgIndex3 */
301  } /* SecurePIN */                  {
302                            /*
303                             * SPR 532 has no display but requires _all_ bMsgIndex
304                             * fields with bNumberMessage set to 0.
305                             */
306                            if (SPR532 == ccid_descriptor->readerID)
307                            {
308                                    cmd[21] = 0x00; /* set bNumberMessages to 0 */
309                                    cmd[a] = cmd[a-1] = cmd[a-2] = 0;       /* bMsgIndex123 */
310                                    a++;
311                                    continue;
312                            }
313    
314                            /* in CCID the bMsgIndex3 is present only if bNumberMessage == 3 */
315                            if (TxBuffer[11] < 3)
316                                    continue;
317                    }
318    
319                    /* copy to the CCID block 'verbatim' */
320                    cmd[a] = TxBuffer[b];
321                    a++;
322            }
323    
324            /* We know the size of the CCID message now */
325            i2dw(a - 10, cmd + 1);  /* command length (includes bPINOperation) */
326    
327            if (WritePort(reader_index, a, cmd) != STATUS_SUCCESS)
328                    return IFD_COMMUNICATION_ERROR;
329    
330            return CCID_Receive(reader_index, RxLength, RxBuffer);
331    } /* SecurePINModify */
332    
333    
334  /*****************************************************************************  /*****************************************************************************
# Line 183  RESPONSECODE SecurePIN(int lun, const un Line 336  RESPONSECODE SecurePIN(int lun, const un
336   *                                      Escape   *                                      Escape
337   *   *
338   ****************************************************************************/   ****************************************************************************/
339  RESPONSECODE CmdEscape(int lun, const unsigned char TxBuffer[],  RESPONSECODE CmdEscape(unsigned int reader_index,
340          unsigned int TxLength, unsigned char RxBuffer[], unsigned int *RxLength)          const unsigned char TxBuffer[], unsigned int TxLength,
341            unsigned char RxBuffer[], unsigned int *RxLength)
342  {  {
343          unsigned char *cmd_in, *cmd_out;          unsigned char *cmd_in, *cmd_out;
344          status_t res;          status_t res;
345          unsigned int length_in, length_out;          unsigned int length_in, length_out;
346          RESPONSECODE return_value = IFD_SUCCESS;          RESPONSECODE return_value = IFD_SUCCESS;
347          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(lun);          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
348    
349    again:
350          /* allocate buffers */          /* allocate buffers */
351          length_in = 10 + TxLength;          length_in = 10 + TxLength;
352          if (NULL == (cmd_in = malloc(length_in)))          if (NULL == (cmd_in = malloc(length_in)))
# Line 206  RESPONSECODE CmdEscape(int lun, const un Line 361  RESPONSECODE CmdEscape(int lun, const un
361    
362          cmd_in[0] = 0x6B; /* PC_to_RDR_Escape */          cmd_in[0] = 0x6B; /* PC_to_RDR_Escape */
363          i2dw(length_in - 10, cmd_in+1); /* dwLength */          i2dw(length_in - 10, cmd_in+1); /* dwLength */
364          cmd_in[5] = 0;  /* slot number */          cmd_in[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
365          cmd_in[6] = ccid_descriptor->bSeq++;          cmd_in[6] = (*ccid_descriptor->pbSeq)++;
366          cmd_in[7] = cmd_in[8] = cmd_in[9] = 0; /* RFU */          cmd_in[7] = cmd_in[8] = cmd_in[9] = 0; /* RFU */
367    
368          /* copy the command */          /* copy the command */
369          memcpy(&cmd_in[10], TxBuffer, TxLength);          memcpy(&cmd_in[10], TxBuffer, TxLength);
370    
371          res = WritePort(lun, length_in, cmd_in);          res = WritePort(reader_index, length_in, cmd_in);
372          free(cmd_in);          free(cmd_in);
373          if (res != STATUS_SUCCESS)          if (res != STATUS_SUCCESS)
374          {          {
# Line 221  RESPONSECODE CmdEscape(int lun, const un Line 376  RESPONSECODE CmdEscape(int lun, const un
376                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
377          }          }
378    
379          res = ReadPort(lun, &length_out, cmd_out);          res = ReadPort(reader_index, &length_out, cmd_out);
380    
381            /* replay the command if NAK
382             * This (generally) happens only for the first command sent to the reader
383             * with the serial protocol so it is not really needed for all the other
384             * ReadPort() calls */
385            if (STATUS_COMM_NAK == res)
386            {
387                    free(cmd_out);
388                    goto again;
389            }
390    
391          if (res != STATUS_SUCCESS)          if (res != STATUS_SUCCESS)
392          {          {
393                  free(cmd_out);                  free(cmd_out);
# Line 230  RESPONSECODE CmdEscape(int lun, const un Line 396  RESPONSECODE CmdEscape(int lun, const un
396    
397          if (cmd_out[STATUS_OFFSET] & CCID_COMMAND_FAILED)          if (cmd_out[STATUS_OFFSET] & CCID_COMMAND_FAILED)
398          {          {
399                  ccid_error(cmd_out[ERROR_OFFSET], __FILE__, __LINE__);    /* bError */                  ccid_error(cmd_out[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__);    /* bError */
400                  return_value = IFD_COMMUNICATION_ERROR;                  return_value = IFD_COMMUNICATION_ERROR;
401          }          }
402    
# Line 252  RESPONSECODE CmdEscape(int lun, const un Line 418  RESPONSECODE CmdEscape(int lun, const un
418   *                                      CmdPowerOff   *                                      CmdPowerOff
419   *   *
420   ****************************************************************************/   ****************************************************************************/
421  RESPONSECODE CmdPowerOff(int lun)  RESPONSECODE CmdPowerOff(unsigned int reader_index)
422  {  {
423          unsigned char cmd[10];          unsigned char cmd[10];
424          status_t res;          status_t res;
425          unsigned int length;          unsigned int length;
426          RESPONSECODE return_value = IFD_SUCCESS;          RESPONSECODE return_value = IFD_SUCCESS;
427          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(lun);          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
428    
429          cmd[0] = 0x63; /* IccPowerOff */          cmd[0] = 0x63; /* IccPowerOff */
430          cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0;  /* dwLength */          cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0;  /* dwLength */
431          cmd[5] = 0;     /* slot number */          cmd[5] = ccid_descriptor->bCurrentSlotIndex;    /* slot number */
432          cmd[6] = ccid_descriptor->bSeq++;          cmd[6] = (*ccid_descriptor->pbSeq)++;
433          cmd[7] = cmd[8] = cmd[9] = 0; /* RFU */          cmd[7] = cmd[8] = cmd[9] = 0; /* RFU */
434    
435          res = WritePort(lun, sizeof(cmd), cmd);          res = WritePort(reader_index, sizeof(cmd), cmd);
436          if (res != STATUS_SUCCESS)          if (res != STATUS_SUCCESS)
437                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
438    
439          length = sizeof(cmd);          length = sizeof(cmd);
440          res = ReadPort(lun, &length, cmd);          res = ReadPort(reader_index, &length, cmd);
441          if (res != STATUS_SUCCESS)          if (res != STATUS_SUCCESS)
442                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
443    
444          if (cmd[STATUS_OFFSET] & CCID_COMMAND_FAILED)          if (cmd[STATUS_OFFSET] & CCID_COMMAND_FAILED)
445          {          {
446                  ccid_error(cmd[ERROR_OFFSET], __FILE__, __LINE__);    /* bError */                  ccid_error(cmd[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__);    /* bError */
447                  return_value = IFD_COMMUNICATION_ERROR;                  return_value = IFD_COMMUNICATION_ERROR;
448          }          }
449    
# Line 290  RESPONSECODE CmdPowerOff(int lun) Line 456  RESPONSECODE CmdPowerOff(int lun)
456   *                                      CmdGetSlotStatus   *                                      CmdGetSlotStatus
457   *   *
458   ****************************************************************************/   ****************************************************************************/
459  RESPONSECODE CmdGetSlotStatus(int lun, unsigned char buffer[])  RESPONSECODE CmdGetSlotStatus(unsigned int reader_index, unsigned char buffer[])
460  {  {
461          unsigned char cmd[10];          unsigned char cmd[10];
462          status_t res;          status_t res;
463          unsigned int length;          unsigned int length;
464          RESPONSECODE return_value = IFD_SUCCESS;          RESPONSECODE return_value = IFD_SUCCESS;
465          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(lun);          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
466    
467          cmd[0] = 0x65; /* GetSlotStatus */          cmd[0] = 0x65; /* GetSlotStatus */
468          cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0;  /* dwLength */          cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0;  /* dwLength */
469          cmd[5] = 0;     /* slot number */          cmd[5] = ccid_descriptor->bCurrentSlotIndex;    /* slot number */
470          cmd[6] = ccid_descriptor->bSeq++;          cmd[6] = (*ccid_descriptor->pbSeq)++;
471          cmd[7] = cmd[8] = cmd[9] = 0; /* RFU */          cmd[7] = cmd[8] = cmd[9] = 0; /* RFU */
472    
473          res = WritePort(lun, sizeof(cmd), cmd);          res = WritePort(reader_index, sizeof(cmd), cmd);
474          if (res != STATUS_SUCCESS)          if (res != STATUS_SUCCESS)
475                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
476    
477          length = SIZE_GET_SLOT_STATUS;          length = SIZE_GET_SLOT_STATUS;
478          res = ReadPort(lun, &length, buffer);          res = ReadPort(reader_index, &length, buffer);
479          if (res != STATUS_SUCCESS)          if (res != STATUS_SUCCESS)
480                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
481    
482          if (buffer[STATUS_OFFSET] & CCID_COMMAND_FAILED)          if (buffer[STATUS_OFFSET] & CCID_COMMAND_FAILED)
483          {          {
484                  ccid_error(buffer[ERROR_OFFSET], __FILE__, __LINE__);    /* bError */                  ccid_error(buffer[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__);    /* bError */
485                  return_value = IFD_COMMUNICATION_ERROR;  
486                    /* card absent or mute is not an communication error */
487                    if (buffer[ERROR_OFFSET] != 0xFE)
488                            return_value = IFD_COMMUNICATION_ERROR;
489          }          }
490    
491          return return_value;          return return_value;
# Line 328  RESPONSECODE CmdGetSlotStatus(int lun, u Line 497  RESPONSECODE CmdGetSlotStatus(int lun, u
497   *                                      CmdXfrBlock   *                                      CmdXfrBlock
498   *   *
499   ****************************************************************************/   ****************************************************************************/
500  RESPONSECODE CmdXfrBlock(int lun, unsigned int tx_length,  RESPONSECODE CmdXfrBlock(unsigned int reader_index, unsigned int tx_length,
501          unsigned char tx_buffer[], unsigned int *rx_length,          unsigned char tx_buffer[], unsigned int *rx_length,
502          unsigned char rx_buffer[], int protocol)          unsigned char rx_buffer[], int protocol)
503  {  {
504          RESPONSECODE return_value = IFD_SUCCESS;          RESPONSECODE return_value = IFD_SUCCESS;
505          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(lun);          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
506    
507          /* command length too big for CCID reader? */          /* command length too big for CCID reader? */
508          if (tx_length > ccid_descriptor->dwMaxCCIDMessageLength)          if (tx_length > ccid_descriptor->dwMaxCCIDMessageLength)
# Line 358  RESPONSECODE CmdXfrBlock(int lun, unsign Line 527  RESPONSECODE CmdXfrBlock(int lun, unsign
527          {          {
528                  case CCID_CLASS_TPDU:                  case CCID_CLASS_TPDU:
529                          if (protocol == T_0)                          if (protocol == T_0)
530                                  return_value = CmdXfrBlockTPDU_T0(lun, tx_length, tx_buffer,                                  return_value = CmdXfrBlockTPDU_T0(reader_index,
531                                          rx_length, rx_buffer);                                          tx_length, tx_buffer, rx_length, rx_buffer);
532                          else                          else
533                                  if (protocol == T_1)                                  if (protocol == T_1)
534                                          return_value = CmdXfrBlockTPDU_T1(lun, tx_length,                                          return_value = CmdXfrBlockTPDU_T1(reader_index, tx_length,
535                                                  tx_buffer, rx_length, rx_buffer);                                                  tx_buffer, rx_length, rx_buffer);
536                                  else                                  else
537                                          return_value = IFD_PROTOCOL_NOT_SUPPORTED;                                          return_value = IFD_PROTOCOL_NOT_SUPPORTED;
# Line 372  RESPONSECODE CmdXfrBlock(int lun, unsign Line 541  RESPONSECODE CmdXfrBlock(int lun, unsign
541                  case CCID_CLASS_EXTENDED_APDU:                  case CCID_CLASS_EXTENDED_APDU:
542                          /* We only support extended APDU if the reader can support the                          /* We only support extended APDU if the reader can support the
543                           * command length. See test above */                           * command length. See test above */
544                          return_value = CmdXfrBlockTPDU_T0(lun, tx_length, tx_buffer,                          return_value = CmdXfrBlockTPDU_T0(reader_index,
545                                  rx_length, rx_buffer);                                  tx_length, tx_buffer, rx_length, rx_buffer);
546                            break;
547    
548                    case CCID_CLASS_CHARACTER:
549                            if (protocol == T_0)
550                                    return_value = CmdXfrBlockCHAR_T0(reader_index, tx_length,
551                                            tx_buffer, rx_length, rx_buffer);
552                            else
553                                    if (protocol == T_1)
554                                            return_value = CmdXfrBlockTPDU_T1(reader_index, tx_length,
555                                                    tx_buffer, rx_length, rx_buffer);
556                                    else
557                                            return_value = IFD_PROTOCOL_NOT_SUPPORTED;
558                          break;                          break;
559    
560                  default:                  default:
# Line 391  clean_up_and_return: Line 572  clean_up_and_return:
572   *                                      CCID_Transmit   *                                      CCID_Transmit
573   *   *
574   ****************************************************************************/   ****************************************************************************/
575  RESPONSECODE CCID_Transmit(int lun, unsigned int tx_length,  RESPONSECODE CCID_Transmit(unsigned int reader_index, unsigned int tx_length,
576          const unsigned char tx_buffer[])          const unsigned char tx_buffer[], unsigned short rx_length, unsigned char bBWI)
577  {  {
578          unsigned char cmd[10+CMD_BUF_SIZE];     /* CCID + APDU buffer */          unsigned char cmd[10+CMD_BUF_SIZE];     /* CCID + APDU buffer */
579          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(lun);          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
580    
581          cmd[0] = 0x6F; /* XfrBlock */          cmd[0] = 0x6F; /* XfrBlock */
582          i2dw(tx_length, cmd+1); /* APDU length */          i2dw(tx_length, cmd+1); /* APDU length */
583          cmd[5] = 0;     /* slot number */          cmd[5] = ccid_descriptor->bCurrentSlotIndex;    /* slot number */
584          cmd[6] = ccid_descriptor->bSeq++;          cmd[6] = (*ccid_descriptor->pbSeq)++;
585          cmd[7] = cmd[8] = cmd[9] = 0; /* RFU */          cmd[7] = bBWI;  /* extend block waiting timeout */
586            cmd[8] = rx_length & 0xFF;      /* Expected length */
587            cmd[9] = (rx_length >> 8) & 0xFF;
588    
589            /* check that the command is not too large */
590            if (tx_length > CMD_BUF_SIZE)
591                    return IFD_NOT_SUPPORTED;
592    
593          memcpy(cmd+10, tx_buffer, tx_length);          memcpy(cmd+10, tx_buffer, tx_length);
594    
595          if (WritePort(lun, 10+tx_length, cmd) != STATUS_SUCCESS)          if (WritePort(reader_index, 10+tx_length, cmd) != STATUS_SUCCESS)
596                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
597    
598          return IFD_SUCCESS;          return IFD_SUCCESS;
# Line 416  RESPONSECODE CCID_Transmit(int lun, unsi Line 604  RESPONSECODE CCID_Transmit(int lun, unsi
604   *                                      CCID_Receive   *                                      CCID_Receive
605   *   *
606   ****************************************************************************/   ****************************************************************************/
607  RESPONSECODE CCID_Receive(int lun, unsigned int *rx_length,  RESPONSECODE CCID_Receive(unsigned int reader_index, unsigned int *rx_length,
608          unsigned char rx_buffer[])          unsigned char rx_buffer[])
609  {  {
610          unsigned char cmd[10+CMD_BUF_SIZE];     /* CCID + APDU buffer */          unsigned char cmd[10+CMD_BUF_SIZE];     /* CCID + APDU buffer */
# Line 424  RESPONSECODE CCID_Receive(int lun, unsig Line 612  RESPONSECODE CCID_Receive(int lun, unsig
612    
613  time_request:  time_request:
614          length = sizeof(cmd);          length = sizeof(cmd);
615          if (ReadPort(lun, &length, cmd) != STATUS_SUCCESS)          if (ReadPort(reader_index, &length, cmd) != STATUS_SUCCESS)
616            {
617                    *rx_length = 0;
618                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
619            }
620    
621          if (cmd[STATUS_OFFSET] & CCID_COMMAND_FAILED)          if (cmd[STATUS_OFFSET] & CCID_COMMAND_FAILED)
622          {          {
623                  ccid_error(cmd[ERROR_OFFSET], __FILE__, __LINE__);    /* bError */                  ccid_error(cmd[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__);    /* bError */
624                  *rx_length = 0; /* nothing received */                  switch (cmd[ERROR_OFFSET])
625                  return IFD_COMMUNICATION_ERROR;                  {
626                            case 0xEF:      /* cancel */
627                                    if (*rx_length < 2)
628                                            return IFD_COMMUNICATION_ERROR;
629                                    rx_buffer[0]= 0x64;
630                                    rx_buffer[1]= 0x01;
631                                    *rx_length = 2;
632                                    return IFD_SUCCESS;
633    
634                            case 0xF0:      /* timeout */
635                                    if (*rx_length < 2)
636                                            return IFD_COMMUNICATION_ERROR;
637                                    rx_buffer[0]= 0x64;
638                                    rx_buffer[1]= 0x00;
639                                    *rx_length = 2;
640                                    return IFD_SUCCESS;
641    
642                            case 0xFD:      /* Parity error during exchange */
643                                    *rx_length = 0; /* nothing received */
644                                    return IFD_PARITY_ERROR;
645    
646                            default:
647                                    *rx_length = 0; /* nothing received */
648                                    return IFD_COMMUNICATION_ERROR;
649                    }
650          }          }
651    
652          if (cmd[STATUS_OFFSET] & CCID_TIME_EXTENSION)          if (cmd[STATUS_OFFSET] & CCID_TIME_EXTENSION)
653          {          {
654                  DEBUG_CRITICAL2("Time extension requested: 0x%02X", cmd[ERROR_OFFSET]);                  DEBUG_COMM2("Time extension requested: 0x%02X", cmd[ERROR_OFFSET]);
655                  goto time_request;                  goto time_request;
656          }          }
657    
# Line 456  time_request: Line 671  time_request:
671   *                                      CmdXfrBlockTPDU_T0   *                                      CmdXfrBlockTPDU_T0
672   *   *
673   ****************************************************************************/   ****************************************************************************/
674  RESPONSECODE CmdXfrBlockTPDU_T0(int lun, unsigned int tx_length,  static RESPONSECODE CmdXfrBlockTPDU_T0(unsigned int reader_index,
675          unsigned char tx_buffer[], unsigned int *rx_length,          unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
676          unsigned char rx_buffer[])          unsigned char rx_buffer[])
677  {  {
678          RESPONSECODE return_value = IFD_SUCCESS;          RESPONSECODE return_value = IFD_SUCCESS;
679    
680          DEBUG_COMM2("T=0: %d bytes", tx_length);          DEBUG_COMM2("T=0: %d bytes", tx_length);
681    
682          return_value = CCID_Transmit(lun, tx_length, tx_buffer);          return_value = CCID_Transmit(reader_index, tx_length, tx_buffer, 0, 0);
683          if (return_value != IFD_SUCCESS)          if (return_value != IFD_SUCCESS)
684                  return return_value;                  return return_value;
685    
686          return CCID_Receive(lun, rx_length, rx_buffer);          return CCID_Receive(reader_index, rx_length, rx_buffer);
687  } /* CmdXfrBlockTPDU_T0 */  } /* CmdXfrBlockTPDU_T0 */
688    
689    
690  /*****************************************************************************  /*****************************************************************************
691   *   *
692   *                                      CmdXfrBlockTPDU_T1   *                                      T0CmdParsing
693   *   *
694   ****************************************************************************/   ****************************************************************************/
695  RESPONSECODE CmdXfrBlockTPDU_T1(int lun, unsigned int tx_length,  static RESPONSECODE T0CmdParsing(unsigned char *cmd, unsigned int cmd_len,
696          unsigned char tx_buffer[], unsigned int *rx_length,          unsigned int *exp_len)
697          unsigned char rx_buffer[])  {
698            *exp_len = 0;
699    
700            /* Ref: 7816-4 Annex A */
701            switch (cmd_len)
702            {
703                    case 4: /* Case 1 */
704                            *exp_len = 2; /* SW1 and SW2 only */
705                            break;
706    
707                    case 5: /* Case 2 */
708                            if (cmd[4] != 0)
709                                    *exp_len = cmd[4] + 2;
710                            else
711                                    *exp_len = 256 + 2;
712                            break;
713    
714                    default: /* Case 3 */
715                            if (cmd_len > 5 && cmd_len == (unsigned int)(cmd[4] + 5))
716                                    *exp_len = 2; /* SW1 and SW2 only */
717                            else
718                                    return IFD_COMMUNICATION_ERROR; /* situation not supported */
719                            break;
720            }
721    
722            return IFD_SUCCESS;
723    } /* T0CmdParsing */
724    
725    
726    /*****************************************************************************
727     *
728     *                                      T0ProcACK
729     *
730     ****************************************************************************/
731    static RESPONSECODE T0ProcACK(unsigned int reader_index,
732            unsigned char **snd_buf, unsigned int *snd_len,
733            unsigned char **rcv_buf, unsigned int *rcv_len,
734            unsigned char **in_buf, unsigned int *in_len,
735            unsigned int proc_len, int is_rcv)
736  {  {
737          RESPONSECODE return_value;          RESPONSECODE return_value;
738          APDU_Cmd cmd;          unsigned int remain_len;
739          APDU_Rsp rsp;          unsigned char tmp_buf[512];
740            unsigned int ret_len;
741    
742            DEBUG_COMM2("Enter, is_rcv = %d", is_rcv);
743    
744            if (is_rcv == 1)
745            {       /* Receiving mode */
746                    if (*in_len > 0)
747                    {       /* There are still available data in our buffer */
748                            if (*in_len >= proc_len)
749                            {
750                                    /* We only need to get the data from our buffer */
751                                    memcpy(*rcv_buf, *in_buf, proc_len);
752                                    *rcv_buf += proc_len;
753                                    *in_buf += proc_len;
754                                    *rcv_len += proc_len;
755                                    *in_len -= proc_len;
756    
757          DEBUG_COMM2("T=1: %d bytes", tx_length);                                  return IFD_SUCCESS;
758                            }
759                            else
760                            {
761                                    /* Move all data in the input buffer to the reply buffer */
762                                    remain_len = proc_len - *in_len;
763                                    memcpy(*rcv_buf, *in_buf, *in_len);
764                                    *rcv_buf += *in_len;
765                                    *in_buf += *in_len;
766                                    *rcv_len += *in_len;
767                                    *in_len = 0;
768                            }
769                    }
770                    else
771                            /* There is no data in our tmp_buf,
772                             * we have to read all data we needed */
773                            remain_len = proc_len;
774    
775                    /* Read the expected data from the smartcard */
776                    if (*in_len != 0)
777                    {
778                            DEBUG_CRITICAL("*in_len != 0");
779                            return IFD_COMMUNICATION_ERROR;
780                    }
781    
782                    memset(tmp_buf, 0, sizeof(tmp_buf));
783    
784                    ret_len = remain_len;
785                    return_value = CCID_Transmit(reader_index, 0, *snd_buf, ret_len, 0);
786                    if (return_value != IFD_SUCCESS)
787                            return return_value;
788    
789                    return_value = CCID_Receive(reader_index, &ret_len, tmp_buf);
790                    if (return_value != IFD_SUCCESS)
791                            return return_value;
792    
793                    memcpy(*rcv_buf, tmp_buf, remain_len);
794                    *rcv_buf += remain_len, *rcv_len += remain_len;
795    
796                    /* If ret_len != remain_len, our logic is erroneous */
797                    if (ret_len != remain_len)
798                    {
799                            DEBUG_CRITICAL("ret_len != remain_len");
800                            return IFD_COMMUNICATION_ERROR;
801                    }
802            }
803            else
804            {       /* Sending mode */
805    
806                    return_value = CCID_Transmit(reader_index, proc_len, *snd_buf, 1, 0);
807                    if (return_value != IFD_SUCCESS)
808                            return return_value;
809    
810                    *snd_len -= proc_len;
811                    *snd_buf += proc_len;
812            }
813    
814            DEBUG_COMM("Exit");
815    
816            return IFD_SUCCESS;
817    } /* T0ProcACK */
818    
819    
820    /*****************************************************************************
821     *
822     *                                      T0ProcSW1
823     *
824     ****************************************************************************/
825    static RESPONSECODE T0ProcSW1(unsigned int reader_index,
826            unsigned char *rcv_buf, unsigned int *rcv_len,
827            unsigned char *in_buf, unsigned int in_len)
828    {
829            RESPONSECODE return_value = IFD_SUCCESS;
830            UCHAR tmp_buf[512];
831            unsigned char *rcv_buf_tmp = rcv_buf;
832            const unsigned int rcv_len_tmp = *rcv_len;
833            unsigned char sw1, sw2;
834    
835            /* store the SW1 */
836            sw1 = *rcv_buf = *in_buf;
837            rcv_buf++;
838            in_buf++;
839            in_len--;
840            (*rcv_len)++;
841    
842            /* store the SW2 */
843            if (0 == in_len)
844            {
845                    return_value = CCID_Transmit(reader_index, 0, rcv_buf, 1, 0);
846                    if (return_value != IFD_SUCCESS)
847                            return return_value;
848    
849                    in_len = 1;
850    
851          /* set up command APDU */                  return_value = CCID_Receive(reader_index, &in_len, tmp_buf);
852          cmd.command = tx_buffer;                  if (return_value != IFD_SUCCESS)
853          cmd.length = tx_length;                          return return_value;
854    
855          return_value = Protocol_T1_Command(&((get_ccid_slot(lun)) -> t1), &cmd,                  in_buf = tmp_buf;
856                  &rsp);          }
857            sw2 = *rcv_buf = *in_buf;
858            rcv_buf++;
859            in_buf++;
860            in_len--;
861            (*rcv_len)++;
862    
863          if (return_value == PROTOCOL_T1_OK)          if (return_value != IFD_SUCCESS)
864          {          {
865                  return_value = IFD_SUCCESS;                  rcv_buf_tmp[0] = rcv_buf_tmp[1] = 0;
866                    *rcv_len = rcv_len_tmp;
867            }
868    
869            DEBUG_COMM3("Exit: SW=%02X %02X", sw1, sw2);
870    
871                  /* copy the response */          return return_value;
872                  memcpy(rx_buffer, rsp.response, rsp.length);  } /* T0ProcSW1 */
873    
                 /* free the allocated response buffer */  
                 free(rsp.response);  
874    
875                  *rx_length = rsp.length;  /*****************************************************************************
876     *
877     *                                      CmdXfrBlockCHAR_T0
878     *
879     ****************************************************************************/
880    static RESPONSECODE CmdXfrBlockCHAR_T0(unsigned int reader_index,
881            unsigned int snd_len, unsigned char snd_buf[], unsigned int *rcv_len,
882            unsigned char rcv_buf[])
883    {
884            int is_rcv;
885            unsigned char cmd[5];
886            unsigned char tmp_buf[512];
887            unsigned int exp_len, in_len;
888            unsigned char ins, *in_buf;
889            RESPONSECODE return_value = IFD_SUCCESS;
890    
891            DEBUG_COMM2("T=0: %d bytes", snd_len);
892    
893            in_buf = tmp_buf;
894            in_len = 0;
895            *rcv_len = 0;
896    
897            return_value = T0CmdParsing(snd_buf, snd_len, &exp_len);
898            if (return_value != IFD_SUCCESS)
899            {
900                    DEBUG_CRITICAL("T0CmdParsing failed");
901                    return IFD_COMMUNICATION_ERROR;
902            }
903    
904            if (snd_len == 5 || snd_len == 4)
905                    is_rcv = 1;
906            else
907                    is_rcv = 0;
908    
909            /* Command to send to the smart card (must be 5 bytes, from 7816 p.15) */
910            memset(cmd, 0, sizeof(cmd));
911            if (snd_len == 4)
912            {
913                    memcpy(cmd, snd_buf, 4);
914                    snd_buf += 4;
915                    snd_len -= 4;
916          }          }
917          else          else
918          {          {
919                    memcpy(cmd, snd_buf, 5);
920                    snd_buf += 5;
921                    snd_len -= 5;
922            }
923    
924            /* Make sure this is a valid command by checking the INS field */
925            ins = cmd[1];
926            if ((ins & 0xF0) == 0x60 ||     /* 7816-3 8.3.2 */
927                    (ins & 0xF0) == 0x90)
928            {
929                    DEBUG_CRITICAL2("fatal: INS (0x%02X) = 0x6X or 0x9X", ins);
930                    return IFD_COMMUNICATION_ERROR;
931            }
932    
933            return_value = CCID_Transmit(reader_index, 5, cmd, 1, 0);
934            if (return_value != IFD_SUCCESS)
935                    return return_value;
936    
937            while (1)
938            {
939                    if (in_len == 0)
940                    {
941                            in_len = 1;
942                            return_value = CCID_Receive(reader_index, &in_len, tmp_buf);
943                            if (return_value != IFD_SUCCESS)
944                            {
945                                    DEBUG_CRITICAL("CCID_Receive failed");
946                                    return return_value;
947                            }
948                            in_buf = tmp_buf;
949                    }
950                    if (in_len == 0)
951                    {
952                            /* Suppose we should be able to get data.
953                             * If not, error. Set the time-out error */
954                            DEBUG_CRITICAL("error: in_len = 0");
955                            return IFD_RESPONSE_TIMEOUT;
956                    }
957    
958                    /* Start to process the procedure bytes */
959                    if (*in_buf == 0x60)
960                    {
961                            in_len = 0;
962                            return_value = CCID_Transmit(reader_index, 0, cmd, 1, 0);
963    
964                            if (return_value != IFD_SUCCESS)
965                                    return return_value;
966    
967                            continue;
968                    }
969                    else if (*in_buf == ins || *in_buf == (ins ^ 0x01))
970                    {
971                            /* ACK => To transfer all remaining data bytes */
972                            in_buf++, in_len--;
973                            if (is_rcv)
974                                    return_value = T0ProcACK(reader_index, &snd_buf, &snd_len,
975                                            &rcv_buf, rcv_len, &in_buf, &in_len, exp_len - *rcv_len, 1);
976                            else
977                                    return_value = T0ProcACK(reader_index, &snd_buf, &snd_len,
978                                            &rcv_buf, rcv_len, &in_buf, &in_len, snd_len, 0);
979    
980                            if (*rcv_len == exp_len)
981                                    return return_value;
982    
983                            continue;
984                    }
985                    else if (*in_buf == (ins ^ 0xFF) || *in_buf == (ins ^ 0xFE))
986                    {
987                            /* ACK => To transfer 1 remaining bytes */
988                            in_buf++, in_len--;
989                            return_value = T0ProcACK(reader_index, &snd_buf, &snd_len,
990                                    &rcv_buf, rcv_len, &in_buf, &in_len, 1, is_rcv);
991    
992                            if (return_value != IFD_SUCCESS)
993                                    return return_value;
994    
995                            continue;
996                    }
997                    else if ((*in_buf & 0xF0) == 0x60 || (*in_buf & 0xF0) == 0x90)
998                            /* SW1 */
999                            return T0ProcSW1(reader_index, rcv_buf, rcv_len, in_buf, in_len);
1000    
1001                    /* Error, unrecognized situation found */
1002                    DEBUG_CRITICAL2("Unrecognized Procedure byte (0x%02X) found!", *in_buf);
1003                    return return_value;
1004            }
1005    
1006            return return_value;
1007    } /* CmdXfrBlockCHAR_T0 */
1008    
1009    
1010    /*****************************************************************************
1011     *
1012     *                                      CmdXfrBlockTPDU_T1
1013     *
1014     ****************************************************************************/
1015    static RESPONSECODE CmdXfrBlockTPDU_T1(unsigned int reader_index,
1016            unsigned int tx_length, unsigned char tx_buffer[], unsigned int *rx_length,
1017            unsigned char rx_buffer[])
1018    {
1019            RESPONSECODE return_value = IFD_SUCCESS;
1020            int ret;
1021    
1022            DEBUG_COMM2("T=1: %d bytes", tx_length);
1023    
1024            ret = t1_transceive(&((get_ccid_slot(reader_index)) -> t1), 0,
1025                    tx_buffer, tx_length, rx_buffer, *rx_length);
1026    
1027            if (ret < 0)
1028            {
1029                  *rx_length = 0;                  *rx_length = 0;
1030                  return_value = IFD_COMMUNICATION_ERROR;                  return_value = IFD_COMMUNICATION_ERROR;
1031          }          }
1032            else
1033                    *rx_length = ret;
1034    
1035          return return_value;          return return_value;
1036  } /* CmdXfrBlockTPDU_T1 */  } /* CmdXfrBlockTPDU_T1 */
# Line 521  RESPONSECODE CmdXfrBlockTPDU_T1(int lun, Line 1041  RESPONSECODE CmdXfrBlockTPDU_T1(int lun,
1041   *                                      SetParameters   *                                      SetParameters
1042   *   *
1043   ****************************************************************************/   ****************************************************************************/
1044  RESPONSECODE SetParameters(int lun, char protocol, unsigned int length,  RESPONSECODE SetParameters(unsigned int reader_index, char protocol,
1045          unsigned char buffer[])          unsigned int length, unsigned char buffer[])
1046  {  {
1047          unsigned char cmd[10+CMD_BUF_SIZE];     /* CCID + APDU buffer */          unsigned char cmd[10+CMD_BUF_SIZE];     /* CCID + APDU buffer */
1048          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(lun);          _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
1049    
1050          DEBUG_COMM2("length: %d bytes", length);          DEBUG_COMM2("length: %d bytes", length);
1051    
1052          cmd[0] = 0x61; /* SetParameters */          cmd[0] = 0x61; /* SetParameters */
1053          i2dw(length, cmd+1);    /* APDU length */          i2dw(length, cmd+1);    /* APDU length */
1054          cmd[5] = 0;     /* slot number */          cmd[5] = ccid_descriptor->bCurrentSlotIndex;    /* slot number */
1055          cmd[6] = ccid_descriptor->bSeq++;          cmd[6] = (*ccid_descriptor->pbSeq)++;
1056          cmd[7] = protocol;      /* bProtocolNum */          cmd[7] = protocol;      /* bProtocolNum */
1057          cmd[8] = cmd[9] = 0; /* RFU */          cmd[8] = cmd[9] = 0; /* RFU */
1058    
1059            /* check that the command is not too large */
1060            if (length > CMD_BUF_SIZE)
1061                    return IFD_NOT_SUPPORTED;
1062    
1063          memcpy(cmd+10, buffer, length);          memcpy(cmd+10, buffer, length);
1064    
1065          if (WritePort(lun, 10+length, cmd) != STATUS_SUCCESS)          if (WritePort(reader_index, 10+length, cmd) != STATUS_SUCCESS)
1066                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
1067    
1068          length = sizeof(cmd);          length = sizeof(cmd);
1069          if (ReadPort(lun, &length, cmd) != STATUS_SUCCESS)          if (ReadPort(reader_index, &length, cmd) != STATUS_SUCCESS)
1070                  return IFD_COMMUNICATION_ERROR;                  return IFD_COMMUNICATION_ERROR;
1071    
1072          if (cmd[STATUS_OFFSET] & CCID_COMMAND_FAILED)          if (cmd[STATUS_OFFSET] & CCID_COMMAND_FAILED)
1073          {          {
1074                  ccid_error(cmd[ERROR_OFFSET], __FILE__, __LINE__);    /* bError */                  ccid_error(cmd[ERROR_OFFSET], __FILE__, __LINE__, __FUNCTION__);    /* bError */
1075                  return IFD_COMMUNICATION_ERROR;                  if (0x00 == cmd[ERROR_OFFSET])  /* command not supported */
1076                            return IFD_NOT_SUPPORTED;
1077                    else
1078                            return IFD_COMMUNICATION_ERROR;
1079          }          }
1080    
1081          return IFD_SUCCESS;          return IFD_SUCCESS;
# Line 556  RESPONSECODE SetParameters(int lun, char Line 1084  RESPONSECODE SetParameters(int lun, char
1084    
1085  /*****************************************************************************  /*****************************************************************************
1086   *   *
1087     *                                      isCharLevel
1088     *
1089     ****************************************************************************/
1090    int isCharLevel(int reader_index)
1091    {
1092            return CCID_CLASS_CHARACTER == (get_ccid_descriptor(reader_index)->dwFeatures & CCID_CLASS_EXCHANGE_MASK);
1093    } /* isCharLevel */
1094    
1095    
1096    /*****************************************************************************
1097     *
1098   *                                      i2dw   *                                      i2dw
1099   *   *
1100   ****************************************************************************/   ****************************************************************************/
1101  void i2dw(int value, unsigned char buffer[])  static void i2dw(int value, unsigned char buffer[])
1102  {  {
1103          buffer[0] = value & 0xFF;          buffer[0] = value & 0xFF;
1104          buffer[1] = (value >> 8) & 0xFF;          buffer[1] = (value >> 8) & 0xFF;

Legend:
Removed from v.904  
changed lines
  Added in v.1675

  ViewVC Help
Powered by ViewVC 1.1.5