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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 269 - (hide annotations) (download)
Tue Aug 12 12:40:23 2003 UTC (9 years, 9 months ago) by rousseau
File MIME type: text/plain
File size: 6367 byte(s)
Initial revision
1 rousseau 269 /*
2     commands.c: Commands sent to the card
3     Copyright (C) 2003 Ludovic Rousseau
4    
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9    
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13     GNU General Public License for more details.
14    
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18     */
19    
20     /*
21     * $Id$
22     */
23    
24     #include <string.h>
25    
26     #include "pcscdefines.h"
27     #include "ifdhandler.h"
28     #include "commands.h"
29     #include "ccid_usb.h"
30     #include "defs.h"
31     #include "config.h"
32     #include "debug.h"
33    
34     #define SET_ISO_MODE 1
35    
36     RESPONSECODE CmdPowerOn(int lun, int * nlength, unsigned char buffer[])
37     {
38     unsigned char cmd[10];
39     status_t res;
40     int atr_len, length, count = 1;
41     RESPONSECODE return_value = IFD_SUCCESS;
42    
43     /* store length of buffer[] */
44     length = *nlength;
45     again:
46     cmd[0] = 0x62; /* IccPowerOn */
47     cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0; /* dwLength */
48     cmd[5] = 0; /* slot number */
49     cmd[6] = ccid_get_seq(lun);
50     cmd[7] = 0x01; /* 5.0V */
51     cmd[8] = cmd[9] = 0; /* RFU */
52    
53     res = WriteUSB(lun, sizeof(cmd), cmd);
54     if (res != STATUS_SUCCESS)
55     return IFD_COMMUNICATION_ERROR;
56    
57     /* reset available buffer size */
58     /* needed if we go back after a switch to ISO mode */
59     *nlength = length;
60    
61     res = ReadUSB(lun, nlength, buffer);
62     if (res != STATUS_SUCCESS)
63     return IFD_COMMUNICATION_ERROR;
64    
65     if (buffer[STATUS_OFFSET] & 0x40)
66     {
67     ccid_error(buffer[ERROR_OFFSET], __FILE__, __LINE__); /* bError */
68    
69     /* Protocol error in EMV mode */
70     if (buffer[ERROR_OFFSET] == 0xBB)
71     {
72     DEBUG_INFO("Switch reader in ISO mode");
73     if ((return_value = Escape(lun, SET_ISO_MODE)) != IFD_SUCCESS)
74     return return_value;
75    
76     /* avoid looping if we can't switch mode */
77     if (count--)
78     goto again;
79     else
80     DEBUG_CRITICAL("Can't set reader in ISO mode");
81     }
82    
83     return IFD_COMMUNICATION_ERROR;
84     }
85    
86     /* extract the ATR */
87     atr_len = dw2i(buffer, 1); /* ATR length */
88     if (atr_len > *nlength)
89     atr_len = *nlength;
90     else
91     *nlength = atr_len;
92    
93     memcpy(buffer, buffer+10, atr_len);
94    
95     return return_value;
96     } /* CmdPowerOn */
97    
98     RESPONSECODE Escape(int lun, int command)
99     {
100     unsigned char cmd[12];
101     status_t res;
102     int length;
103     RESPONSECODE return_value = IFD_SUCCESS;
104    
105     cmd[0] = 0x6B; /* PC_to_RDR_Escape */
106     cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0; /* dwLength */
107     cmd[5] = 0; /* slot number */
108     cmd[6] = ccid_get_seq(lun);
109     cmd[7] = cmd[8] = cmd[9] = 0; /* RFU */
110    
111     switch (command)
112     {
113     /* Gemplus proprietary */
114     case SET_ISO_MODE:
115     cmd[10] = 0x1F; /* switch mode */
116     cmd[11] = 0x01; /* set ISO mode */
117     cmd[1] = 2; /* length of data */
118     length = 12;
119     break;
120    
121     default:
122     DEBUG_CRITICAL2("Unkown Escape command: %d", command);
123     return return_value;
124     }
125    
126     res = WriteUSB(lun, length, cmd);
127     if (res != STATUS_SUCCESS)
128     return IFD_COMMUNICATION_ERROR;
129    
130     length = sizeof(cmd);
131     res = ReadUSB(lun, &length, cmd);
132     if (res != STATUS_SUCCESS)
133     return IFD_COMMUNICATION_ERROR;
134    
135     if (cmd[STATUS_OFFSET] & 0x40)
136     {
137     ccid_error(cmd[ERROR_OFFSET], __FILE__, __LINE__); /* bError */
138     return_value = IFD_COMMUNICATION_ERROR;
139     }
140    
141     return return_value;
142     } /* Escape */
143    
144     RESPONSECODE CmdPowerOff(int lun)
145     {
146     unsigned char cmd[10];
147     status_t res;
148     int length;
149     RESPONSECODE return_value = IFD_SUCCESS;
150    
151     cmd[0] = 0x63; /* IccPowerOff */
152     cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0; /* dwLength */
153     cmd[5] = 0; /* slot number */
154     cmd[6] = ccid_get_seq(lun);
155     cmd[7] = cmd[8] = cmd[9] = 0; /* RFU */
156    
157     res = WriteUSB(lun, sizeof(cmd), cmd);
158     if (res != STATUS_SUCCESS)
159     return IFD_COMMUNICATION_ERROR;
160    
161     length = sizeof(cmd);
162     res = ReadUSB(lun, &length, cmd);
163     if (res != STATUS_SUCCESS)
164     return IFD_COMMUNICATION_ERROR;
165    
166     if (cmd[STATUS_OFFSET] & 0x40)
167     {
168     ccid_error(cmd[ERROR_OFFSET], __FILE__, __LINE__); /* bError */
169     return_value = IFD_COMMUNICATION_ERROR;
170     }
171    
172     return return_value;
173     } /* CmdPowerOff */
174    
175     RESPONSECODE CmdGetSlotStatus(int lun, unsigned char buffer[])
176     {
177     unsigned char cmd[10];
178     status_t res;
179     int length;
180     RESPONSECODE return_value = IFD_SUCCESS;
181    
182     cmd[0] = 0x65; /* GetSlotStatus */
183     cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0; /* dwLength */
184     cmd[5] = 0; /* slot number */
185     cmd[6] = ccid_get_seq(lun);
186     cmd[7] = cmd[8] = cmd[9] = 0; /* RFU */
187    
188     res = WriteUSB(lun, sizeof(cmd), cmd);
189     if (res != STATUS_SUCCESS)
190     return IFD_COMMUNICATION_ERROR;
191    
192     length = SIZE_GET_SLOT_STATUS;
193     res = ReadUSB(lun, &length, buffer);
194     if (res != STATUS_SUCCESS)
195     return IFD_COMMUNICATION_ERROR;
196    
197     if (buffer[STATUS_OFFSET] & 0x40)
198     {
199     ccid_error(buffer[ERROR_OFFSET], __FILE__, __LINE__); /* bError */
200     return_value = IFD_COMMUNICATION_ERROR;
201     }
202    
203     return return_value;
204     } /* CmdGetSlotStatus */
205    
206     RESPONSECODE CmdXfrBlock(int lun, int tx_length, unsigned char tx_buffer[],
207     PDWORD rx_length, unsigned char rx_buffer[])
208     {
209     unsigned char cmd[10+CMD_BUF_SIZE]; /* CCID + APDU buffer */
210     status_t res;
211     int length;
212     RESPONSECODE return_value = IFD_SUCCESS;
213    
214     cmd[0] = 0x6F; /* IccPowerOff */
215     i2dw(tx_length, cmd+1); /* APDU length */
216     cmd[5] = 0; /* slot number */
217     cmd[6] = ccid_get_seq(lun);
218     cmd[7] = cmd[8] = cmd[9] = 0; /* RFU */
219     memcpy(cmd+10, tx_buffer, tx_length);
220    
221     res = WriteUSB(lun, 10+tx_length, cmd);
222     if (res != STATUS_SUCCESS)
223     return IFD_COMMUNICATION_ERROR;
224    
225     length = sizeof(cmd);
226     res = ReadUSB(lun, &length, cmd);
227     if (res != STATUS_SUCCESS)
228     return IFD_COMMUNICATION_ERROR;
229    
230     if (cmd[STATUS_OFFSET] & 0x40)
231     {
232     ccid_error(cmd[ERROR_OFFSET], __FILE__, __LINE__); /* bError */
233     *rx_length = 0; /* nothing received */
234     return_value = IFD_COMMUNICATION_ERROR;
235     }
236    
237     length = dw2i(cmd, 1);
238     if (length < *rx_length)
239     *rx_length = length;
240     else
241     length = *rx_length;
242     memcpy(rx_buffer, cmd+10, length);
243    
244     return return_value;
245     } /* CmdXfrBlock */
246    
247     void i2dw(int value, unsigned char buffer[])
248     {
249     buffer[0] = value & 0xFF;
250     buffer[1] = (value >> 8) & 0xFF;
251     buffer[2] = (value >> 16) & 0xFF;
252     buffer[3] = (value >> 24) & 0xFF;
253     } /* i2dw */
254    

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.5