/[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 3403 - (show annotations) (download)
Mon Mar 30 08:55:59 2009 UTC (4 years, 1 month ago) by rousseau
File MIME type: text/plain
File size: 11297 byte(s)
split ccid_open_hack() in ccid_open_hack_pre() and ccid_open_hack_post()
before and after the empirical "warm up" sequence

The problem is the USB toggle bit. I could not find a simple way to
reset it. So when the driver is started again the reader and the host
may not be in sync. The few first CCID commands may fail.
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 License
16 along with this library; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 #include "ccid_usb.h"
37
38 /*****************************************************************************
39 *
40 * ccid_open_hack_pre
41 *
42 ****************************************************************************/
43 int ccid_open_hack_pre(unsigned int reader_index)
44 {
45 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
46
47 switch (ccid_descriptor->readerID)
48 {
49 case CARDMAN3121+1:
50 /* Reader announces APDU but is in fact TPDU */
51 ccid_descriptor->dwFeatures &= ~CCID_CLASS_EXCHANGE_MASK;
52 ccid_descriptor->dwFeatures |= CCID_CLASS_TPDU;
53 break;
54
55 case GEMPCKEY:
56 case GEMPCTWIN:
57 /* Reader announces TPDU but can do APDU */
58 if (DriverOptions & DRIVER_OPTION_GEMPC_TWIN_KEY_APDU)
59 {
60 unsigned char cmd[] = { 0xA0, 0x02 };
61 unsigned char res[10];
62 unsigned int length_res = sizeof(res);
63
64 if (CmdEscape(reader_index, cmd, sizeof(cmd), res, &length_res) == IFD_SUCCESS)
65 {
66 ccid_descriptor->dwFeatures &= ~CCID_CLASS_EXCHANGE_MASK;
67 ccid_descriptor->dwFeatures |= CCID_CLASS_SHORT_APDU;
68 }
69 }
70 break;
71
72 case GEMPCPINPAD:
73 /* load the l10n strings in the pinpad memory */
74 {
75 #define L10N_HEADER_SIZE 5
76 #define L10N_STRING_MAX_SIZE 16
77 #define L10N_NB_STRING 10
78
79 unsigned char cmd[L10N_HEADER_SIZE + L10N_NB_STRING * L10N_STRING_MAX_SIZE];
80 unsigned char res[20];
81 unsigned int length_res = sizeof(res);
82 int offset, i, j;
83
84 const char *fr[] = {
85 "Entrer PIN",
86 "Nouveau PIN",
87 "Confirmer PIN",
88 "PIN correct",
89 "PIN Incorrect !",
90 "Delai depasse",
91 "* essai restant",
92 "Inserer carte",
93 "Erreur carte",
94 "PIN bloque" };
95
96 const char *de[] = {
97 "PIN eingeben",
98 "Neue PIN",
99 "PIN bestatigen",
100 "PIN korrect",
101 "Falsche PIN !",
102 "Zeit abgelaufen",
103 "* Versuche ubrig",
104 "Karte einstecken",
105 "Fehler Karte",
106 "PIN blockiert" };
107
108 const char *es[] = {
109 "Introducir PIN",
110 "Nuevo PIN",
111 "Confirmar PIN",
112 "PIN OK",
113 "PIN Incorrecto !",
114 "Tiempo Agotado",
115 "* ensayos quedan",
116 "Introducir Tarj.",
117 "Error en Tarjeta",
118 "PIN bloqueado" };
119
120 const char *it[] = {
121 "Inserire PIN",
122 "Nuovo PIN",
123 "Confermare PIN",
124 "PIN Corretto",
125 "PIN Errato !",
126 "Tempo scaduto",
127 "* prove rimaste",
128 "Inserire Carta",
129 "Errore Carta",
130 "PIN ostruito"};
131
132 const char *pt[] = {
133 "Insira PIN",
134 "Novo PIN",
135 "Conf. novo PIN",
136 "PIN OK",
137 "PIN falhou!",
138 "Tempo expirou",
139 "* tentiv. restam",
140 "Introduza cartao",
141 "Erro cartao",
142 "PIN bloqueado" };
143
144 const char *nl[] = {
145 "Inbrengen code",
146 "Nieuwe code",
147 "Bevestig code",
148 "Code aanvaard",
149 "Foute code",
150 "Time out",
151 "* Nog Pogingen",
152 "Kaart inbrengen",
153 "Kaart fout",
154 "Kaart blok" };
155
156 const char *tr[] = {
157 "PIN Giriniz",
158 "Yeni PIN",
159 "PIN Onayala",
160 "PIN OK",
161 "Yanlis PIN",
162 "Zaman Asimi",
163 "* deneme kaldi",
164 "Karti Takiniz",
165 "Kart Hatasi",
166 "Kart Kilitli" };
167
168 const char *en[] = {
169 "Enter PIN",
170 "New PIN",
171 "Confirm PIN",
172 "PIN OK",
173 "Incorrect PIN!",
174 "Time Out",
175 "* retries left",
176 "Insert Card",
177 "Card Error",
178 "PIN blocked" };
179
180 char *lang;
181 const char **l10n;
182
183 lang = getenv("LANG");
184 if (NULL == lang)
185 l10n = en;
186 else
187 {
188 if (0 == strncmp(lang, "fr", 2))
189 l10n = fr;
190 else if (0 == strncmp(lang, "de", 2))
191 l10n = de;
192 else if (0 == strncmp(lang, "es", 2))
193 l10n = es;
194 else if (0 == strncmp(lang, "it", 2))
195 l10n = it;
196 else if (0 == strncmp(lang, "pt", 2))
197 l10n = pt;
198 else if (0 == strncmp(lang, "nl", 2))
199 l10n = nl;
200 else if (0 == strncmp(lang, "tr", 2))
201 l10n = tr;
202 else
203 l10n = en;
204 }
205
206 offset = 0;
207 cmd[offset++] = 0xB2; /* load strings */
208 cmd[offset++] = 0xA0; /* address of the memory */
209 cmd[offset++] = 0x00; /* address of the first byte */
210 cmd[offset++] = 0x4D; /* magic value */
211 cmd[offset++] = 0x4C; /* magic value */
212
213 /* for each string */
214 for (i=0; i<L10N_NB_STRING; i++)
215 {
216 /* copy the string */
217 for (j=0; l10n[i][j]; j++)
218 cmd[offset++] = l10n[i][j];
219
220 /* pad with " " */
221 for (; j<L10N_STRING_MAX_SIZE; j++)
222 cmd[offset++] = ' ';
223 }
224
225 (void)sleep(1);
226 if (IFD_SUCCESS == CmdEscape(reader_index, cmd, sizeof(cmd), res, &length_res))
227 {
228 DEBUG_COMM("l10n string loaded successfully");
229 }
230 else
231 {
232 DEBUG_COMM("Failed to load l10n strings");
233 }
234 }
235 break;
236
237 #if 0
238 /* SCM SCR331-DI contactless */
239 case SCR331DI:
240 /* SCM SCR331-DI-NTTCOM contactless */
241 case SCR331DINTTCOM:
242 /* SCM SDI010 contactless */
243 case SDI010:
244 /* the contactless reader is in the second slot */
245 if (ccid_descriptor->bCurrentSlotIndex > 0)
246 {
247 unsigned char cmd1[] = { 0x00 };
248 /* command: 00 ??
249 * response: 06 10 03 03 00 00 00 01 FE FF FF FE 01 ?? */
250 unsigned char cmd2[] = { 0x02 };
251 /* command: 02 ??
252 * response: 00 ?? */
253
254 unsigned char res[20];
255 unsigned int length_res = sizeof(res);
256
257 if ((IFD_SUCCESS == CmdEscape(reader_index, cmd1, sizeof(cmd1), res, &length_res))
258 && (IFD_SUCCESS == CmdEscape(reader_index, cmd2, sizeof(cmd2), res, &length_res)))
259 {
260 DEBUG_COMM("SCM SCR331-DI contactless detected");
261 }
262 else
263 {
264 DEBUG_COMM("SCM SCR331-DI contactless init failed");
265 }
266
267 /* hack since the contactless reader do not share dwFeatures */
268 ccid_descriptor->dwFeatures &= ~CCID_CLASS_EXCHANGE_MASK;
269 ccid_descriptor->dwFeatures |= CCID_CLASS_SHORT_APDU;
270
271 ccid_descriptor->dwFeatures |= CCID_CLASS_AUTO_IFSD;
272 }
273 break;
274 #endif
275
276 case MYSMARTPAD:
277 ccid_descriptor->dwMaxIFSD = 254;
278 break;
279
280 case CL1356D:
281 /* the firmware needs some time to initialize */
282 (void)sleep(1);
283 ccid_descriptor->readTimeout = 60; /* 60 seconds */
284 break;
285
286 case SEG:
287 #ifndef TWIN_SERIAL
288 (void)InterruptRead(reader_index);
289 #endif
290 break;
291
292 #ifndef USE_USB_INTERRUPT
293 /* only if we do not use USB interrupts */
294 case GEMALTOPROXDU:
295 case GEMALTOPROXSU:
296 {
297 /* disable card movements notification
298 * with RDR_to_PC_NotifySlotChange */
299 unsigned char cmd[] = { 0x42, 0x00 /* disable */};
300 unsigned char res[10];
301 unsigned int length_res = sizeof(res);
302
303 if (CmdEscape(reader_index, cmd, sizeof(cmd), res, &length_res) == IFD_SUCCESS)
304 {
305 DEBUG_COMM("NotifySlotChange disabled");
306 }
307 else
308 {
309 DEBUG_CRITICAL("NotifySlotChange disabling failed");
310 }
311 }
312 break;
313 #endif
314 }
315
316 /* ICCD type A */
317 if (ICCD_A == ccid_descriptor->bInterfaceProtocol)
318 {
319 unsigned char tmp[MAX_ATR_SIZE];
320 unsigned int n = sizeof(tmp);
321
322 DEBUG_COMM("ICCD type A");
323 (void)CmdPowerOff(reader_index);
324 (void)CmdPowerOn(reader_index, &n, tmp, CCID_CLASS_AUTO_VOLTAGE);
325 (void)CmdPowerOff(reader_index);
326 }
327
328 /* ICCD type B */
329 if (ICCD_B == ccid_descriptor->bInterfaceProtocol)
330 {
331 unsigned char tmp[MAX_ATR_SIZE];
332 unsigned int n = sizeof(tmp);
333
334 DEBUG_COMM("ICCD type B");
335 if (CCID_CLASS_SHORT_APDU ==
336 (ccid_descriptor->dwFeatures & CCID_CLASS_EXCHANGE_MASK))
337 {
338 /* use the extended APDU comm alogorithm */
339 ccid_descriptor->dwFeatures &= ~CCID_CLASS_EXCHANGE_MASK;
340 ccid_descriptor->dwFeatures |= CCID_CLASS_EXTENDED_APDU;
341 }
342
343 (void)CmdPowerOff(reader_index);
344 (void)CmdPowerOn(reader_index, &n, tmp, CCID_CLASS_AUTO_VOLTAGE);
345 (void)CmdPowerOff(reader_index);
346 }
347
348 return 0;
349 } /* ccid_open_hack_pre */
350
351 /*****************************************************************************
352 *
353 * ccid_open_hack_post
354 *
355 ****************************************************************************/
356 int ccid_open_hack_post(unsigned int reader_index)
357 {
358 _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
359
360 switch (ccid_descriptor->readerID)
361 {
362 }
363
364 return 0;
365 } /* ccid_open_hack_post */
366
367 /*****************************************************************************
368 *
369 * ccid_error
370 *
371 ****************************************************************************/
372 void ccid_error(int error, const char *file, int line, const char *function)
373 {
374 const char *text;
375 char var_text[30];
376
377 switch (error)
378 {
379 case 0x00:
380 text = "Command not supported or not allowed";
381 break;
382
383 case 0x01:
384 text = "Wrong command length";
385 break;
386
387 case 0x05:
388 text = "Invalid slot number";
389 break;
390
391 case 0xA2:
392 text = "Card short-circuiting. Card powered off";
393 break;
394
395 case 0xA3:
396 text = "ATR too long (> 33)";
397 break;
398
399 case 0xAB:
400 text = "No data exchanged";
401 break;
402
403 case 0xB0:
404 text = "Reader in EMV mode and T=1 message too long";
405 break;
406
407 case 0xBB:
408 text = "Protocol error in EMV mode";
409 break;
410
411 case 0xBD:
412 text = "Card error during T=1 exchange";
413 break;
414
415 case 0xBE:
416 text = "Wrong APDU command length";
417 break;
418
419 case 0xE0:
420 text = "Slot busy";
421 break;
422
423 case 0xEF:
424 text = "PIN cancelled";
425 break;
426
427 case 0xF0:
428 text = "PIN timeout";
429 break;
430
431 case 0xF2:
432 text = "Busy with autosequence";
433 break;
434
435 case 0xF3:
436 text = "Deactivated protocol";
437 break;
438
439 case 0xF4:
440 text = "Procedure byte conflict";
441 break;
442
443 case 0xF5:
444 text = "Class not supported";
445 break;
446
447 case 0xF6:
448 text = "Protocol not supported";
449 break;
450
451 case 0xF7:
452 text = "Invalid ATR checksum byte (TCK)";
453 break;
454
455 case 0xF8:
456 text = "Invalid ATR first byte";
457 break;
458
459 case 0xFB:
460 text = "Hardware error";
461 break;
462
463 case 0xFC:
464 text = "Overrun error";
465 break;
466
467 case 0xFD:
468 text = "Parity error during exchange";
469 break;
470
471 case 0xFE:
472 text = "Card absent or mute";
473 break;
474
475 case 0xFF:
476 text = "Activity aborted by Host";
477 break;
478
479 default:
480 if ((error >= 1) && (error <= 127))
481 {
482 (void)snprintf(var_text, sizeof(var_text), "error on byte %d",
483 error);
484 text = var_text;
485 }
486 else
487 (void)snprintf(var_text, sizeof(var_text),
488 "Unknown CCID error: 0x%02X", error);
489 text = var_text;
490 break;
491 }
492 log_msg(PCSC_LOG_ERROR, "%s:%d:%s %s", file, line, function, text);
493
494 } /* ccid_error */
495

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.5