/[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 - (show 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 /*
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