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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.5