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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2489 - (show annotations) (download)
Wed Mar 21 12:44:38 2007 UTC (6 years, 2 months ago) by rousseau
File MIME type: text/plain
File size: 10069 byte(s)
ccid_open_hack(): add Dutch(nl) and Tukish(tr) messages for the GemPC
pinpad
1 /*
2 ccid.c: CCID common code
3 Copyright (C) 2003-2005 Ludovic Rousseau
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library 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 GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 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
18 */
19
20 /*
21 * $Id$
22 */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <pcsclite.h>
28 #include <ifdhandler.h>
29
30 #include "config.h"
31 #include "debug.h"
32 #include "ccid.h"
33 #include "defs.h"
34 #include "ccid_ifdhandler.h"
35 #include "commands.h"
36
37 /*****************************************************************************
38 *
39 * ccid_open_hack
40 *
41 ****************************************************************************/
42 int ccid_open_hack(unsigned int reader_index)
43 {
44 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
45
46 switch (ccid_descriptor->readerID)
47 {
48 case CARDMAN3121+1:
49 /* Reader announces APDU but is in fact TPDU */
50 ccid_descriptor->dwFeatures &= ~CCID_CLASS_EXCHANGE_MASK;
51 ccid_descriptor->dwFeatures |= CCID_CLASS_TPDU;
52 break;
53
54 case GEMPCKEY:
55 case GEMPCTWIN:
56 /* Reader announces TPDU but can do APDU */
57 if (DriverOptions & DRIVER_OPTION_GEMPC_TWIN_KEY_APDU)
58 {
59 unsigned char cmd[] = { 0xA0, 0x02 };
60 unsigned char res[10];
61 unsigned int length_res = sizeof(res);
62
63 if (CmdEscape(reader_index, cmd, sizeof(cmd), res, &length_res) == IFD_SUCCESS)
64 {
65 ccid_descriptor->dwFeatures &= ~CCID_CLASS_EXCHANGE_MASK;
66 ccid_descriptor->dwFeatures |= CCID_CLASS_SHORT_APDU;
67 }
68 }
69 break;
70
71 case GEMPCPINPAD:
72 /* load the l10n strings in the pinpad memory */
73 {
74 #define L10N_HEADER_SIZE 5
75 #define L10N_STRING_MAX_SIZE 16
76 #define L10N_NB_STRING 10
77
78 unsigned char cmd[L10N_HEADER_SIZE + L10N_NB_STRING * L10N_STRING_MAX_SIZE];
79 unsigned char res[20];
80 unsigned int length_res = sizeof(res);
81 int offset, i, j;
82
83 const char *fr[] = {
84 "Entrer PIN",
85 "Nouveau PIN",
86 "Confirmer PIN",
87 "PIN correct",
88 "PIN Incorrect !",
89 "Delai depasse",
90 "* essai restant",
91 "Inserer carte",
92 "Erreur carte",
93 "PIN bloque" };
94
95 const char *de[] = {
96 "PIN eingeben",
97 "Neue PIN",
98 "PIN bestatigen",
99 "PIN korrect",
100 "Falsche PIN !",
101 "Zeit abgelaufen",
102 "* Versuche ubrig",
103 "Karte einstecken",
104 "Fehler Karte",
105 "PIN blockiert" };
106
107 const char *es[] = {
108 "Introducir PIN",
109 "Nuevo PIN",
110 "Confirmar PIN",
111 "PIN OK",
112 "PIN Incorrecto !",
113 "Tiempo Agotado",
114 "* ensayos quedan",
115 "Introducir Tarj.",
116 "Error en Tarjeta",
117 "PIN bloqueado" };
118
119 const char *it[] = {
120 "Inserire PIN",
121 "Nuovo PIN",
122 "Confermare PIN",
123 "PIN Corretto",
124 "PIN Errato !",
125 "Tempo scaduto",
126 "* prove rimaste",
127 "Inserire Carta",
128 "Errore Carta",
129 "PIN ostruito"};
130
131 const char *pt[] = {
132 "Insira PIN",
133 "Novo PIN",
134 "Conf. novo PIN",
135 "PIN OK",
136 "PIN falhou!",
137 "Tempo expirou",
138 "* tentiv. restam",
139 "Introduza cartao",
140 "Erro cartao",
141 "PIN bloqueado" };
142
143 const char *nl[] = {
144 "Inbrengen code",
145 "Nieuwe code",
146 "Bevestig code",
147 "Code aanvaard",
148 "Foute code",
149 "Time out",
150 "* Nog Pogingen",
151 "Kaart inbrengen",
152 "Kaart fout",
153 "Kaart blok" };
154
155 const char *tr[] = {
156 "PIN Giriniz",
157 "Yeni PIN",
158 "PIN Onayala",
159 "PIN OK",
160 "Yanlis PIN",
161 "Zaman Asimi",
162 "* deneme kaldi",
163 "Karti Takiniz",
164 "Kart Hatasi",
165 "Kart Kilitli" };
166
167 const char *en[] = {
168 "Enter PIN",
169 "New PIN",
170 "Confirm PIN",
171 "PIN OK",
172 "Incorrect PIN!",
173 "Time Out",
174 "* retries left",
175 "Insert Card",
176 "Card Error",
177 "PIN blocked" };
178
179 char *lang;
180 const char **l10n;
181
182 lang = getenv("LANG");
183 if (NULL == lang)
184 l10n = en;
185 else
186 {
187 if (0 == strncmp(lang, "fr", 2))
188 l10n = fr;
189 else if (0 == strncmp(lang, "de", 2))
190 l10n = de;
191 else if (0 == strncmp(lang, "es", 2))
192 l10n = es;
193 else if (0 == strncmp(lang, "it", 2))
194 l10n = it;
195 else if (0 == strncmp(lang, "pt", 2))
196 l10n = pt;
197 else if (0 == strncmp(lang, "nl", 2))
198 l10n = nl;
199 else if (0 == strncmp(lang, "tr", 2))
200 l10n = tr;
201 else
202 l10n = en;
203 }
204
205 offset = 0;
206 cmd[offset++] = 0xB2; /* load strings */
207 cmd[offset++] = 0xA0; /* address of the memory */
208 cmd[offset++] = 0x00; /* address of the first byte */
209 cmd[offset++] = 0x4D; /* magic value */
210 cmd[offset++] = 0x4C; /* magic value */
211
212 /* for each string */
213 for (i=0; i<L10N_NB_STRING; i++)
214 {
215 /* copy the string */
216 for (j=0; l10n[i][j]; j++)
217 cmd[offset++] = l10n[i][j];
218
219 /* pad with " " */
220 for (; j<L10N_STRING_MAX_SIZE; j++)
221 cmd[offset++] = ' ';
222 }
223
224 if (IFD_SUCCESS == CmdEscape(reader_index, cmd, sizeof(cmd), res, &length_res))
225 {
226 DEBUG_COMM("l10n string loaded successfully");
227 }
228 else
229 {
230 DEBUG_COMM("Failed to load l10n strings");
231 }
232 }
233 break;
234
235 /* SCM SCR331-DI contactless */
236 case SCR331DI:
237 /* SCM SCR331-DI-NTTCOM contactless */
238 case SCR331DINTTCOM:
239 /* SCM SDI010 contactless */
240 case SDI010:
241 /* the contactless reader is in the second slot */
242 if (ccid_descriptor->bCurrentSlotIndex > 0)
243 {
244 unsigned char cmd1[] = { 0x00 };
245 /* command: 00 ??
246 * response: 06 10 03 03 00 00 00 01 FE FF FF FE 01 ?? */
247 unsigned char cmd2[] = { 0x02 };
248 /* command: 02 ??
249 * response: 00 ?? */
250
251 unsigned char res[20];
252 unsigned int length_res = sizeof(res);
253
254 if ((IFD_SUCCESS == CmdEscape(reader_index, cmd1, sizeof(cmd1), res, &length_res))
255 && (IFD_SUCCESS == CmdEscape(reader_index, cmd2, sizeof(cmd2), res, &length_res)))
256 {
257 DEBUG_COMM("SCM SCR331-DI contactless detected");
258 }
259 else
260 {
261 DEBUG_COMM("SCM SCR331-DI contactless init failed");
262 }
263
264 /* hack since the contactless reader do not share dwFeatures */
265 ccid_descriptor->dwFeatures &= ~CCID_CLASS_EXCHANGE_MASK;
266 ccid_descriptor->dwFeatures |= CCID_CLASS_SHORT_APDU;
267
268 ccid_descriptor->dwFeatures |= CCID_CLASS_AUTO_IFSD;
269 }
270 break;
271
272 case MYSMARTPAD:
273 ccid_descriptor->dwMaxIFSD = 254;
274 break;
275
276 case CL1356D:
277 /* the firmware needs some time to initialize */
278 sleep(1);
279 ccid_descriptor->readTimeout = 60; /* 60 seconds */
280 break;
281 }
282
283 /* ICCD type A */
284 if (ICCD_A == ccid_descriptor->bInterfaceProtocol)
285 {
286 unsigned char tmp[MAX_ATR_SIZE];
287 unsigned int n = sizeof(tmp);
288
289 DEBUG_COMM("ICCD type A");
290 CmdPowerOff(reader_index);
291 CmdPowerOn(reader_index, &n, tmp, CCID_CLASS_AUTO_VOLTAGE);
292 CmdPowerOff(reader_index);
293 }
294
295 /* ICCD type B */
296 if (ICCD_B == ccid_descriptor->bInterfaceProtocol)
297 {
298 unsigned char tmp[MAX_ATR_SIZE];
299 unsigned int n = sizeof(tmp);
300
301 DEBUG_COMM("ICCD type B");
302 if (CCID_CLASS_SHORT_APDU ==
303 (ccid_descriptor->dwFeatures & CCID_CLASS_EXCHANGE_MASK))
304 {
305 /* use the extended APDU comm alogorithm */
306 ccid_descriptor->dwFeatures &= ~CCID_CLASS_EXCHANGE_MASK;
307 ccid_descriptor->dwFeatures |= CCID_CLASS_EXTENDED_APDU;
308 }
309
310 CmdPowerOff(reader_index);
311 CmdPowerOn(reader_index, &n, tmp, CCID_CLASS_AUTO_VOLTAGE);
312 CmdPowerOff(reader_index);
313 }
314
315 return 0;
316 } /* ccid_open_hack */
317
318 /*****************************************************************************
319 *
320 * ccid_error
321 *
322 ****************************************************************************/
323 void ccid_error(int error, const char *file, int line, const char *function)
324 {
325 const char *text;
326 char var_text[20];
327
328 switch (error)
329 {
330 case 0x00:
331 text = "Command not supported or not allowed";
332 break;
333
334 case 0x01:
335 text = "Wrong command length";
336 break;
337
338 case 0x05:
339 text = "Invalid slot number";
340 break;
341
342 case 0xA2:
343 text = "Card short-circuiting. Card powered off";
344 break;
345
346 case 0xA3:
347 text = "ATR too long (> 33)";
348 break;
349
350 case 0xAB:
351 text = "No data exchanged";
352 break;
353
354 case 0xB0:
355 text = "Reader in EMV mode and T=1 message too long";
356 break;
357
358 case 0xBB:
359 text = "Protocol error in EMV mode";
360 break;
361
362 case 0xBD:
363 text = "Card error during T=1 exchange";
364 break;
365
366 case 0xBE:
367 text = "Wrong APDU command length";
368 break;
369
370 case 0xE0:
371 text = "Slot busy";
372 break;
373
374 case 0xEF:
375 text = "PIN cancelled";
376 break;
377
378 case 0xF0:
379 text = "PIN timeout";
380 break;
381
382 case 0xF2:
383 text = "Busy with autosequence";
384 break;
385
386 case 0xF3:
387 text = "Deactivated protocol";
388 break;
389
390 case 0xF4:
391 text = "Procedure byte conflict";
392 break;
393
394 case 0xF5:
395 text = "Class not supported";
396 break;
397
398 case 0xF6:
399 text = "Protocol not supported";
400 break;
401
402 case 0xF7:
403 text = "Invalid ATR checksum byte (TCK)";
404 break;
405
406 case 0xF8:
407 text = "Invalid ATR first byte";
408 break;
409
410 case 0xFB:
411 text = "Hardware error";
412 break;
413
414 case 0xFC:
415 text = "Overrun error";
416 break;
417
418 case 0xFD:
419 text = "Parity error during exchange";
420 break;
421
422 case 0xFE:
423 text = "Card absent or mute";
424 break;
425
426 case 0xFF:
427 text = "Activity aborted by Host";
428 break;
429
430 default:
431 if ((error >= 1) && (error <= 127))
432 {
433 sprintf(var_text, "error on byte %d", error);
434 text = var_text;
435 }
436 else
437 sprintf(var_text, "Unknown CCID error: 0x%02X", error);
438 text = var_text;
439 break;
440 }
441 log_msg(PCSC_LOG_ERROR, "%s:%d:%s %s", file, line, function, text);
442
443 } /* ccid_error */
444

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.5