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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1752 - (show annotations) (download)
Thu Nov 24 16:16:33 2005 UTC (7 years, 5 months ago) by rousseau
File MIME type: text/plain
File size: 35710 byte(s)
IFDHGetCapabilities(): use info instead of comm debug level to print the
number of slots supported by the reader
1 /*
2 ifdhandler.c: IFDH API
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 /* $Id$ */
21
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <PCSC/pcsclite.h>
26 #include <PCSC/ifdhandler.h>
27 #include <PCSC/reader.h>
28
29 #include "ccid.h"
30 #include "defs.h"
31 #include "ccid_ifdhandler.h"
32 #include "config.h"
33 #include "debug.h"
34 #include "utils.h"
35 #include "commands.h"
36 #include "towitoko/atr.h"
37 #include "towitoko/pps.h"
38 #include "parser.h"
39
40 #ifdef HAVE_PTHREAD
41 #include <pthread.h>
42 #endif
43
44 /* Array of structures to hold the ATR and other state value of each slot */
45 static CcidDesc CcidSlots[CCID_DRIVER_MAX_READERS];
46
47 /* global mutex */
48 #ifdef HAVE_PTHREAD
49 static pthread_mutex_t ifdh_context_mutex = PTHREAD_MUTEX_INITIALIZER;
50 #endif
51
52 int LogLevel = DEBUG_LEVEL_CRITICAL | DEBUG_LEVEL_INFO;
53 int DriverOptions = 0;
54 static int DebugInitialized = FALSE;
55
56 /* local functions */
57 static void init_driver(void);
58 static void extra_egt(ATR_t *atr, _ccid_descriptor *ccid_desc, DWORD Protocol);
59 static char find_baud_rate(unsigned int baudrate, unsigned int *list);
60 static unsigned int T0_card_timeout(double f, double d, int TC1, int TC2,
61 int clock_frequency);
62 static unsigned int T1_card_timeout(double f, double d, int TC1, int BWI,
63 int CWI, int clock_frequency);
64
65
66 RESPONSECODE IFDHCreateChannelByName(DWORD Lun, LPTSTR lpcDevice)
67 {
68 RESPONSECODE return_value = IFD_SUCCESS;
69 int reader_index;
70
71 if (! DebugInitialized)
72 init_driver();
73
74 DEBUG_INFO3("lun: %X, device: %s", Lun, lpcDevice);
75
76 if (-1 == (reader_index = GetNewReaderIndex(Lun)))
77 return IFD_COMMUNICATION_ERROR;
78
79 /* Reset ATR buffer */
80 CcidSlots[reader_index].nATRLength = 0;
81 *CcidSlots[reader_index].pcATRBuffer = '\0';
82
83 /* Reset PowerFlags */
84 CcidSlots[reader_index].bPowerFlags = POWERFLAGS_RAZ;
85
86 #ifdef HAVE_PTHREAD
87 pthread_mutex_lock(&ifdh_context_mutex);
88 #endif
89
90 if (OpenPortByName(reader_index, lpcDevice) != STATUS_SUCCESS)
91 {
92 DEBUG_CRITICAL("failed");
93 return_value = IFD_COMMUNICATION_ERROR;
94
95 /* release the allocated reader_index */
96 ReleaseReaderIndex(reader_index);
97 }
98 else
99 /* Maybe we have a special treatment for this reader */
100 ccid_open_hack(reader_index);
101
102 #ifdef HAVE_PTHREAD
103 pthread_mutex_unlock(&ifdh_context_mutex);
104 #endif
105
106 return return_value;
107 } /* IFDHCreateChannelByName */
108
109
110 RESPONSECODE IFDHCreateChannel(DWORD Lun, DWORD Channel)
111 {
112 /*
113 * Lun - Logical Unit Number, use this for multiple card slots or
114 * multiple readers. 0xXXXXYYYY - XXXX multiple readers, YYYY multiple
115 * slots. The resource manager will set these automatically. By
116 * default the resource manager loads a new instance of the driver so
117 * if your reader does not have more than one smartcard slot then
118 * ignore the Lun in all the functions. Future versions of PC/SC might
119 * support loading multiple readers through one instance of the driver
120 * in which XXXX would be important to implement if you want this.
121 */
122
123 /*
124 * Channel - Channel ID. This is denoted by the following: 0x000001 -
125 * /dev/pcsc/1 0x000002 - /dev/pcsc/2 0x000003 - /dev/pcsc/3
126 *
127 * USB readers may choose to ignore this parameter and query the bus
128 * for the particular reader.
129 */
130
131 /*
132 * This function is required to open a communications channel to the
133 * port listed by Channel. For example, the first serial reader on
134 * COM1 would link to /dev/pcsc/1 which would be a sym link to
135 * /dev/ttyS0 on some machines This is used to help with intermachine
136 * independance.
137 *
138 * Once the channel is opened the reader must be in a state in which
139 * it is possible to query IFDHICCPresence() for card status.
140 *
141 * returns:
142 *
143 * IFD_SUCCESS IFD_COMMUNICATION_ERROR
144 */
145 RESPONSECODE return_value = IFD_SUCCESS;
146 int reader_index;
147
148 if (! DebugInitialized)
149 init_driver();
150
151 DEBUG_INFO2("lun: %X", Lun);
152
153 if (-1 == (reader_index = GetNewReaderIndex(Lun)))
154 return IFD_COMMUNICATION_ERROR;
155
156 /* Reset ATR buffer */
157 CcidSlots[reader_index].nATRLength = 0;
158 *CcidSlots[reader_index].pcATRBuffer = '\0';
159
160 /* Reset PowerFlags */
161 CcidSlots[reader_index].bPowerFlags = POWERFLAGS_RAZ;
162
163 #ifdef HAVE_PTHREAD
164 pthread_mutex_lock(&ifdh_context_mutex);
165 #endif
166
167 if (OpenPort(reader_index, Channel) != STATUS_SUCCESS)
168 {
169 DEBUG_CRITICAL("failed");
170 return_value = IFD_COMMUNICATION_ERROR;
171
172 /* release the allocated reader_index */
173 ReleaseReaderIndex(reader_index);
174 }
175 else
176 /* Maybe we have a special treatment for this reader */
177 ccid_open_hack(reader_index);
178
179 #ifdef HAVE_PTHREAD
180 pthread_mutex_unlock(&ifdh_context_mutex);
181 #endif
182
183 return return_value;
184 } /* IFDHCreateChannel */
185
186
187 RESPONSECODE IFDHCloseChannel(DWORD Lun)
188 {
189 /*
190 * This function should close the reader communication channel for the
191 * particular reader. Prior to closing the communication channel the
192 * reader should make sure the card is powered down and the terminal
193 * is also powered down.
194 *
195 * returns:
196 *
197 * IFD_SUCCESS IFD_COMMUNICATION_ERROR
198 */
199 int reader_index;
200
201 DEBUG_INFO2("lun: %X", Lun);
202
203 if (-1 == (reader_index = LunToReaderIndex(Lun)))
204 return IFD_COMMUNICATION_ERROR;
205
206 /* Restore the default timeout
207 * No need to wait too long if the reader disapeared */
208 get_ccid_descriptor(reader_index)->readTimeout = DEFAULT_COM_READ_TIMEOUT;
209
210 (void)CmdPowerOff(reader_index);
211 /* No reader status check, if it failed, what can you do ? :) */
212
213 #ifdef HAVE_PTHREAD
214 pthread_mutex_lock(&ifdh_context_mutex);
215 #endif
216
217 (void)ClosePort(reader_index);
218 ReleaseReaderIndex(reader_index);
219
220 #ifdef HAVE_PTHREAD
221 pthread_mutex_unlock(&ifdh_context_mutex);
222 #endif
223
224 return IFD_SUCCESS;
225 } /* IFDHCloseChannel */
226
227
228 RESPONSECODE IFDHGetCapabilities(DWORD Lun, DWORD Tag,
229 PDWORD Length, PUCHAR Value)
230 {
231 /*
232 * This function should get the slot/card capabilities for a
233 * particular slot/card specified by Lun. Again, if you have only 1
234 * card slot and don't mind loading a new driver for each reader then
235 * ignore Lun.
236 *
237 * Tag - the tag for the information requested example: TAG_IFD_ATR -
238 * return the Atr and it's size (required). these tags are defined in
239 * ifdhandler.h
240 *
241 * Length - the length of the returned data Value - the value of the
242 * data
243 *
244 * returns:
245 *
246 * IFD_SUCCESS IFD_ERROR_TAG
247 */
248 int reader_index;
249
250 DEBUG_INFO3("lun: %X, tag: 0x%X", Lun, Tag);
251
252 if (-1 == (reader_index = LunToReaderIndex(Lun)))
253 return IFD_COMMUNICATION_ERROR;
254
255 switch (Tag)
256 {
257 case TAG_IFD_ATR:
258 case SCARD_ATTR_ATR_STRING:
259 /* If Length is not zero, powerICC has been performed.
260 * Otherwise, return NULL pointer
261 * Buffer size is stored in *Length */
262 *Length = (*Length < CcidSlots[reader_index].nATRLength) ?
263 *Length : CcidSlots[reader_index].nATRLength;
264
265 if (*Length)
266 memcpy(Value, CcidSlots[reader_index].pcATRBuffer, *Length);
267 break;
268
269 #ifdef HAVE_PTHREAD
270 case TAG_IFD_SIMULTANEOUS_ACCESS:
271 if (*Length >= 1)
272 {
273 *Length = 1;
274 *Value = CCID_DRIVER_MAX_READERS;
275 }
276 break;
277
278 case TAG_IFD_THREAD_SAFE:
279 if (*Length >= 1)
280 {
281 *Length = 1;
282 *Value = 1; /* Can talk to multiple readers at the same time */
283 }
284 break;
285 #endif
286
287 case TAG_IFD_SLOTS_NUMBER:
288 if (*Length >= 1)
289 {
290 *Length = 1;
291 *Value = 1 + get_ccid_descriptor(reader_index) -> bMaxSlotIndex;
292 DEBUG_INFO2("Reader supports %d slots", *Value);
293 }
294 break;
295
296 case TAG_IFD_SLOT_THREAD_SAFE:
297 if (*Length >= 1)
298 {
299 *Length = 1;
300 *Value = 0; /* Can NOT talk to multiple slots at the same time */
301 }
302 break;
303
304 default:
305 return IFD_ERROR_TAG;
306 }
307
308 return IFD_SUCCESS;
309 } /* IFDHGetCapabilities */
310
311
312 RESPONSECODE IFDHSetCapabilities(DWORD Lun, DWORD Tag,
313 /*@unused@*/ DWORD Length, /*@unused@*/ PUCHAR Value)
314 {
315 /*
316 * This function should set the slot/card capabilities for a
317 * particular slot/card specified by Lun. Again, if you have only 1
318 * card slot and don't mind loading a new driver for each reader then
319 * ignore Lun.
320 *
321 * Tag - the tag for the information needing set
322 *
323 * Length - the length of the returned data Value - the value of the
324 * data
325 *
326 * returns:
327 *
328 * IFD_SUCCESS IFD_ERROR_TAG IFD_ERROR_SET_FAILURE
329 * IFD_ERROR_VALUE_READ_ONLY
330 */
331
332 /* By default, say it worked */
333
334 DEBUG_INFO3("lun: %X, tag: 0x%X", Lun, Tag);
335
336 /* if (CheckLun(Lun))
337 return IFD_COMMUNICATION_ERROR; */
338
339 return IFD_NOT_SUPPORTED;
340 } /* IFDHSetCapabilities */
341
342
343 RESPONSECODE IFDHSetProtocolParameters(DWORD Lun, DWORD Protocol,
344 UCHAR Flags, UCHAR PTS1, UCHAR PTS2, UCHAR PTS3)
345 {
346 /*
347 * This function should set the PTS of a particular card/slot using
348 * the three PTS parameters sent
349 *
350 * Protocol - 0 .... 14 T=0 .... T=14
351 * Flags - Logical OR of possible values:
352 * IFD_NEGOTIATE_PTS1
353 * IFD_NEGOTIATE_PTS2
354 * IFD_NEGOTIATE_PTS3
355 * to determine which PTS values to negotiate.
356 * PTS1,PTS2,PTS3 - PTS Values.
357 *
358 * returns:
359 * IFD_SUCCESS
360 * IFD_ERROR_PTS_FAILURE
361 * IFD_COMMUNICATION_ERROR
362 * IFD_PROTOCOL_NOT_SUPPORTED
363 */
364
365 BYTE pps[PPS_MAX_LENGTH];
366 ATR_t atr;
367 unsigned int len;
368 int convention;
369 int reader_index;
370
371 /* Set ccid desc params */
372 CcidDesc *ccid_slot;
373 _ccid_descriptor *ccid_desc;
374
375 DEBUG_INFO3("lun: %X, protocol T=%d", Lun, Protocol-1);
376
377 if (-1 == (reader_index = LunToReaderIndex(Lun)))
378 return IFD_COMMUNICATION_ERROR;
379
380 /* Set to zero buffer */
381 memset(pps, 0, sizeof(pps));
382 memset(&atr, 0, sizeof(atr));
383
384 /* Get ccid params */
385 ccid_slot = get_ccid_slot(reader_index);
386 ccid_desc = get_ccid_descriptor(reader_index);
387
388 /* Do not send CCID command SetParameters or PPS to the CCID
389 * The CCID will do this himself */
390 if (ccid_desc->dwFeatures & CCID_CLASS_AUTO_PPS_PROP)
391 return IFD_SUCCESS;
392
393 /* Get ATR of the card */
394 ATR_InitFromArray(&atr, ccid_slot->pcATRBuffer, ccid_slot->nATRLength);
395
396 /* Apply Extra EGT patch for bogus cards */
397 extra_egt(&atr, ccid_desc, Protocol);
398
399 if (SCARD_PROTOCOL_T0 == Protocol)
400 pps[1] |= ATR_PROTOCOL_TYPE_T0;
401 else
402 if (SCARD_PROTOCOL_T1 == Protocol)
403 pps[1] |= ATR_PROTOCOL_TYPE_T1;
404 else
405 return IFD_PROTOCOL_NOT_SUPPORTED;
406
407 /* TA2 present -> specific mode */
408 if (atr.ib[1][ATR_INTERFACE_BYTE_TA].present)
409 {
410 if (pps[1] != (atr.ib[1][ATR_INTERFACE_BYTE_TA].value & 0x0F))
411 {
412 /* wrong protocol */
413 DEBUG_COMM3("Specific mode in T=%d and T=%d requested",
414 atr.ib[1][ATR_INTERFACE_BYTE_TA].value & 0x0F, pps[1]);
415
416 return IFD_PROTOCOL_NOT_SUPPORTED;
417 }
418 }
419
420 /* TCi (i>2) indicates CRC instead of LRC */
421 if (SCARD_PROTOCOL_T1 == Protocol)
422 {
423 t1_state_t *t1 = &(ccid_slot -> t1);
424 int i;
425
426 /* TCi (i>2) present? */
427 for (i=2; i<ATR_MAX_PROTOCOLS; i++)
428 if (atr.ib[i][ATR_INTERFACE_BYTE_TC].present)
429 {
430 if (0 == atr.ib[i][ATR_INTERFACE_BYTE_TC].value)
431 {
432 DEBUG_COMM("Use LRC");
433 t1_set_param(t1, IFD_PROTOCOL_T1_CHECKSUM_LRC, 0);
434 }
435 else
436 if (1 == atr.ib[i][ATR_INTERFACE_BYTE_TC].value)
437 {
438 DEBUG_COMM("Use CRC");
439 t1_set_param(t1, IFD_PROTOCOL_T1_CHECKSUM_CRC, 0);
440 }
441 else
442 DEBUG_COMM2("Wrong value for TCi: %d",
443 atr.ib[i][ATR_INTERFACE_BYTE_TC].value);
444
445 /* only the first TCi (i>2) must be used */
446 break;
447 }
448 }
449
450 /* PTS1? */
451 if (Flags & IFD_NEGOTIATE_PTS1)
452 {
453 /* just use the value passed in argument */
454 pps[1] |= 0x10; /* PTS1 presence */
455 pps[2] = PTS1;
456 }
457 else
458 {
459 /* TA1 present */
460 if (atr.ib[0][ATR_INTERFACE_BYTE_TA].present)
461 {
462 unsigned int card_baudrate;
463 unsigned int default_baudrate;
464 double f, d;
465
466 ATR_GetParameter(&atr, ATR_PARAMETER_D, &d);
467 ATR_GetParameter(&atr, ATR_PARAMETER_F, &f);
468
469 /* Baudrate = f x D/F */
470 card_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock
471 * d / f);
472
473 default_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock
474 * ATR_DEFAULT_D / ATR_DEFAULT_F);
475
476 /* if the card does not try to lower the default speed */
477 if ((card_baudrate > default_baudrate)
478 /* and the reader is fast enough */
479 && (card_baudrate <= ccid_desc->dwMaxDataRate))
480 {
481 /* the reader has no baud rates table */
482 if ((NULL == ccid_desc->arrayOfSupportedDataRates)
483 /* or explicitely support it */
484 || find_baud_rate(card_baudrate,
485 ccid_desc->arrayOfSupportedDataRates))
486 {
487 pps[1] |= 0x10; /* PTS1 presence */
488 pps[2] = atr.ib[0][ATR_INTERFACE_BYTE_TA].value;
489
490 DEBUG_COMM2("Set speed to %d bauds", card_baudrate);
491 }
492 else
493 DEBUG_COMM2("Reader does not support %d bauds",
494 card_baudrate);
495 }
496 }
497 }
498
499 /* PTS2? */
500 if (Flags & IFD_NEGOTIATE_PTS2)
501 {
502 pps[1] |= 0x20; /* PTS2 presence */
503 pps[3] = PTS2;
504 }
505
506 /* PTS3? */
507 if (Flags & IFD_NEGOTIATE_PTS3)
508 {
509 pps[1] |= 0x40; /* PTS3 presence */
510 pps[4] = PTS3;
511 }
512
513 /* Generate PPS */
514 pps[0] = 0xFF;
515
516 /* Automatic PPS made by the ICC? */
517 if ((! (ccid_desc->dwFeatures & CCID_CLASS_AUTO_PPS_CUR))
518 /* TA2 absent: negociable mode */
519 && (! atr.ib[1][ATR_INTERFACE_BYTE_TA].present))
520 {
521 int default_protocol;
522
523 if (ATR_MALFORMED == ATR_GetDefaultProtocol(&atr, &default_protocol))
524 return IFD_PROTOCOL_NOT_SUPPORTED;
525
526 /* if the requested protocol is not the default one
527 * or a TA1/PPS1 is present */
528 if (((pps[1] & 0x0F) != default_protocol) || (PPS_HAS_PPS1(pps)))
529 if (PPS_Exchange(reader_index, pps, &len, &pps[2]) != PPS_OK)
530 {
531 DEBUG_INFO("PPS_Exchange Failed");
532
533 return IFD_ERROR_PTS_FAILURE;
534 }
535 }
536
537 /* Now we must set the reader parameters */
538 ATR_GetConvention(&atr, &convention);
539
540 /* specific mode and implicit parameters? (b5 of TA2) */
541 if (atr.ib[1][ATR_INTERFACE_BYTE_TA].present
542 && (atr.ib[1][ATR_INTERFACE_BYTE_TA].value & 0x10))
543 return IFD_COMMUNICATION_ERROR;
544
545 /* T=1 */
546 if (SCARD_PROTOCOL_T1 == Protocol)
547 {
548 BYTE param[] = {
549 0x11, /* Fi/Di */
550 0x10, /* TCCKS */
551 0x00, /* GuardTime */
552 0x4D, /* BWI/CWI */
553 0x00, /* ClockStop */
554 0x20, /* IFSC */
555 0x00 /* NADValue */
556 };
557 int i;
558 t1_state_t *t1 = &(ccid_slot -> t1);
559 RESPONSECODE ret;
560 double f, d;
561
562 /* TA1 is not default */
563 if (PPS_HAS_PPS1(pps))
564 param[0] = pps[2];
565
566 /* CRC checksum? */
567 if (2 == t1->rc_bytes)
568 param[1] |= 0x01;
569
570 /* the CCID should ignore this bit */
571 if (ATR_CONVENTION_INVERSE == convention)
572 param[1] |= 0x02;
573
574 /* get TC1 Extra guard time */
575 if (atr.ib[0][ATR_INTERFACE_BYTE_TC].present)
576 param[2] = atr.ib[0][ATR_INTERFACE_BYTE_TC].value;
577
578 /* TBi (i>2) present? BWI/CWI */
579 for (i=2; i<ATR_MAX_PROTOCOLS; i++)
580 if (atr.ib[i][ATR_INTERFACE_BYTE_TB].present)
581 {
582 DEBUG_COMM3("BWI/CWI (TB%d) present: 0x%02X", i+1,
583 atr.ib[i][ATR_INTERFACE_BYTE_TB].value);
584 param[3] = atr.ib[i][ATR_INTERFACE_BYTE_TB].value;
585
586 /* only the first TBi (i>2) must be used */
587 break;
588 }
589
590 /* compute communication timeout */
591 ATR_GetParameter(&atr, ATR_PARAMETER_F, &f);
592 ATR_GetParameter(&atr, ATR_PARAMETER_D, &d);
593 ccid_desc->readTimeout = T1_card_timeout(f, d, param[2],
594 (param[3] & 0xF0) >> 4 /* BWI */, param[3] & 0x0F /* CWI */,
595 ccid_desc->dwDefaultClock);
596
597 DEBUG_COMM2("Timeout: %d seconds", ccid_desc->readTimeout);
598
599 ret = SetParameters(reader_index, 1, sizeof(param), param);
600 if (IFD_SUCCESS != ret)
601 return ret;
602 }
603 else
604 /* T=0 */
605 {
606 BYTE param[] = {
607 0x11, /* Fi/Di */
608 0x00, /* TCCKS */
609 0x00, /* GuardTime */
610 0x0A, /* WaitingInteger */
611 0x00 /* ClockStop */
612 };
613 RESPONSECODE ret;
614 double f, d;
615
616 /* TA1 is not default */
617 if (PPS_HAS_PPS1(pps))
618 param[0] = pps[2];
619
620 if (ATR_CONVENTION_INVERSE == convention)
621 param[1] |= 0x02;
622
623 /* get TC1 Extra guard time */
624 if (atr.ib[0][ATR_INTERFACE_BYTE_TC].present)
625 param[2] = atr.ib[0][ATR_INTERFACE_BYTE_TC].value;
626
627 /* TC2 WWT */
628 if (atr.ib[1][ATR_INTERFACE_BYTE_TC].present)
629 param[3] = atr.ib[1][ATR_INTERFACE_BYTE_TC].value;
630
631 /* compute communication timeout */
632 ATR_GetParameter(&atr, ATR_PARAMETER_F, &f);
633 ATR_GetParameter(&atr, ATR_PARAMETER_D, &d);
634
635 ccid_desc->readTimeout = T0_card_timeout(f, d, param[2] /* TC1 */,
636 param[3] /* TC2 */, ccid_desc->dwDefaultClock);
637
638 DEBUG_COMM2("Communication timeout: %d seconds",
639 ccid_desc->readTimeout);
640
641 ret = SetParameters(reader_index, 0, sizeof(param), param);
642 if (IFD_SUCCESS != ret)
643 return ret;
644 }
645
646 /* set IFSC & IFSD in T=1 */
647 if (SCARD_PROTOCOL_T1 == Protocol)
648 {
649 t1_state_t *t1 = &(ccid_slot -> t1);
650 int i;
651
652 /* TAi (i>2) present? */
653 for (i=2; i<ATR_MAX_PROTOCOLS; i++)
654 if (atr.ib[i][ATR_INTERFACE_BYTE_TA].present)
655 {
656 DEBUG_COMM3("IFSC (TA%d) present: %d", i+1,
657 atr.ib[i][ATR_INTERFACE_BYTE_TA].value);
658 t1_set_param(t1, IFD_PROTOCOL_T1_IFSC,
659 atr.ib[i][ATR_INTERFACE_BYTE_TA].value);
660
661 /* only the first TAi (i>2) must be used */
662 break;
663 }
664
665 /* IFSD not negociated by the reader? */
666 if (! (ccid_desc->dwFeatures & CCID_CLASS_AUTO_IFSD))
667 {
668 DEBUG_COMM2("Negociate IFSD at %d", ccid_desc -> dwMaxIFSD);
669 if (t1_negociate_ifsd(t1, 0, ccid_desc -> dwMaxIFSD) < 0)
670 return IFD_COMMUNICATION_ERROR;
671 }
672 t1_set_param(t1, IFD_PROTOCOL_T1_IFSD, ccid_desc -> dwMaxIFSD);
673
674 DEBUG_COMM3("T=1: IFSC=%d, IFSD=%d", t1->ifsc, t1->ifsd);
675 }
676
677 return IFD_SUCCESS;
678 } /* IFDHSetProtocolParameters */
679
680
681 RESPONSECODE IFDHPowerICC(DWORD Lun, DWORD Action,
682 PUCHAR Atr, PDWORD AtrLength)
683 {
684 /*
685 * This function controls the power and reset signals of the smartcard
686 * reader at the particular reader/slot specified by Lun.
687 *
688 * Action - Action to be taken on the card.
689 *
690 * IFD_POWER_UP - Power and reset the card if not done so (store the
691 * ATR and return it and it's length).
692 *
693 * IFD_POWER_DOWN - Power down the card if not done already
694 * (Atr/AtrLength should be zero'd)
695 *
696 * IFD_RESET - Perform a quick reset on the card. If the card is not
697 * powered power up the card. (Store and return the Atr/Length)
698 *
699 * Atr - Answer to Reset of the card. The driver is responsible for
700 * caching this value in case IFDHGetCapabilities is called requesting
701 * the ATR and it's length. This should not exceed MAX_ATR_SIZE.
702 *
703 * AtrLength - Length of the Atr. This should not exceed
704 * MAX_ATR_SIZE.
705 *
706 * Notes:
707 *
708 * Memory cards without an ATR should return IFD_SUCCESS on reset but
709 * the Atr should be zero'd and the length should be zero
710 *
711 * Reset errors should return zero for the AtrLength and return
712 * IFD_ERROR_POWER_ACTION.
713 *
714 * returns:
715 *
716 * IFD_SUCCESS IFD_ERROR_POWER_ACTION IFD_COMMUNICATION_ERROR
717 * IFD_NOT_SUPPORTED
718 */
719
720 unsigned int nlength;
721 RESPONSECODE return_value = IFD_SUCCESS;
722 unsigned char pcbuffer[RESP_BUF_SIZE];
723 int reader_index;
724
725 DEBUG_INFO2("lun: %X", Lun);
726
727 /* By default, assume it won't work :) */
728 *AtrLength = 0;
729
730 if (-1 == (reader_index = LunToReaderIndex(Lun)))
731 return IFD_COMMUNICATION_ERROR;
732
733 switch (Action)
734 {
735 case IFD_POWER_DOWN:
736 /* Clear ATR buffer */
737 CcidSlots[reader_index].nATRLength = 0;
738 *CcidSlots[reader_index].pcATRBuffer = '\0';
739
740 /* Memorise the request */
741 CcidSlots[reader_index].bPowerFlags |= MASK_POWERFLAGS_PDWN;
742
743 /* send the command */
744 if (IFD_SUCCESS != CmdPowerOff(reader_index))
745 {
746 DEBUG_CRITICAL("PowerDown failed");
747 return_value = IFD_ERROR_POWER_ACTION;
748 goto end;
749 }
750
751 /* clear T=1 context */
752 t1_release(&(get_ccid_slot(reader_index) -> t1));
753 break;
754
755 case IFD_POWER_UP:
756 case IFD_RESET:
757 nlength = sizeof(pcbuffer);
758 if (CmdPowerOn(reader_index, &nlength, pcbuffer) != IFD_SUCCESS)
759 {
760 DEBUG_CRITICAL("PowerUp failed");
761 return_value = IFD_ERROR_POWER_ACTION;
762 goto end;
763 }
764
765 /* Power up successful, set state variable to memorise it */
766 CcidSlots[reader_index].bPowerFlags |= MASK_POWERFLAGS_PUP;
767 CcidSlots[reader_index].bPowerFlags &= ~MASK_POWERFLAGS_PDWN;
768
769 /* Reset is returned, even if TCK is wrong */
770 CcidSlots[reader_index].nATRLength = *AtrLength =
771 (nlength < MAX_ATR_SIZE) ? nlength : MAX_ATR_SIZE;
772 memcpy(Atr, pcbuffer, *AtrLength);
773 memcpy(CcidSlots[reader_index].pcATRBuffer, pcbuffer, *AtrLength);
774
775 /* initialise T=1 context */
776 t1_init(&(get_ccid_slot(reader_index) -> t1), reader_index);
777 break;
778
779 default:
780 DEBUG_CRITICAL("Action not supported");
781 return_value = IFD_NOT_SUPPORTED;
782 }
783 end:
784
785 return return_value;
786 } /* IFDHPowerICC */
787
788
789 RESPONSECODE IFDHTransmitToICC(DWORD Lun, SCARD_IO_HEADER SendPci,
790 PUCHAR TxBuffer, DWORD TxLength,
791 PUCHAR RxBuffer, PDWORD RxLength, /*@unused@*/ PSCARD_IO_HEADER RecvPci)
792 {
793 /*
794 * This function performs an APDU exchange with the card/slot
795 * specified by Lun. The driver is responsible for performing any
796 * protocol specific exchanges such as T=0/1 ... differences. Calling
797 * this function will abstract all protocol differences.
798 *
799 * SendPci Protocol - 0, 1, .... 14 Length - Not used.
800 *
801 * TxBuffer - Transmit APDU example (0x00 0xA4 0x00 0x00 0x02 0x3F
802 * 0x00) TxLength - Length of this buffer. RxBuffer - Receive APDU
803 * example (0x61 0x14) RxLength - Length of the received APDU. This
804 * function will be passed the size of the buffer of RxBuffer and this
805 * function is responsible for setting this to the length of the
806 * received APDU. This should be ZERO on all errors. The resource
807 * manager will take responsibility of zeroing out any temporary APDU
808 * buffers for security reasons.
809 *
810 * RecvPci Protocol - 0, 1, .... 14 Length - Not used.
811 *
812 * Notes: The driver is responsible for knowing what type of card it
813 * has. If the current slot/card contains a memory card then this
814 * command should ignore the Protocol and use the MCT style commands
815 * for support for these style cards and transmit them appropriately.
816 * If your reader does not support memory cards or you don't want to
817 * then ignore this.
818 *
819 * RxLength should be set to zero on error.
820 *
821 * returns:
822 *
823 * IFD_SUCCESS IFD_COMMUNICATION_ERROR IFD_RESPONSE_TIMEOUT
824 * IFD_ICC_NOT_PRESENT IFD_PROTOCOL_NOT_SUPPORTED
825 */
826
827 RESPONSECODE return_value;
828 unsigned int rx_length;
829 int reader_index;
830
831 DEBUG_INFO2("lun: %X", Lun);
832
833 if (-1 == (reader_index = LunToReaderIndex(Lun)))
834 return IFD_COMMUNICATION_ERROR;
835
836 rx_length = *RxLength;
837 return_value = CmdXfrBlock(reader_index, TxLength, TxBuffer, &rx_length,
838 RxBuffer, SendPci.Protocol);
839 *RxLength = rx_length;
840
841 return return_value;
842 } /* IFDHTransmitToICC */
843
844
845 RESPONSECODE IFDHControl(DWORD Lun, DWORD dwControlCode, PUCHAR TxBuffer,
846 DWORD TxLength, PUCHAR RxBuffer, DWORD RxLength, PDWORD pdwBytesReturned)
847 {
848 /*
849 * This function performs a data exchange with the reader (not the
850 * card) specified by Lun. Here XXXX will only be used. It is
851 * responsible for abstracting functionality such as PIN pads,
852 * biometrics, LCD panels, etc. You should follow the MCT, CTBCS
853 * specifications for a list of accepted commands to implement.
854 *
855 * TxBuffer - Transmit data TxLength - Length of this buffer. RxBuffer
856 * - Receive data RxLength - Length of the received data. This
857 * function will be passed the length of the buffer RxBuffer and it
858 * must set this to the length of the received data.
859 *
860 * Notes: RxLength should be zero on error.
861 */
862 RESPONSECODE return_value = IFD_COMMUNICATION_ERROR;
863 int reader_index;
864
865 DEBUG_INFO3("lun: %X, ControlCode: 0x%X", Lun, dwControlCode);
866
867 reader_index = LunToReaderIndex(Lun);
868 if ((-1 == reader_index) || (NULL == pdwBytesReturned))
869 return return_value;
870
871 /* Set the return length to 0 to avoid problems */
872 *pdwBytesReturned = 0;
873
874 if (IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE == dwControlCode)
875 {
876 if (FALSE == (DriverOptions & DRIVER_OPTION_CCID_EXCHANGE_AUTHORIZED))
877 {
878 DEBUG_INFO("ifd exchange (Escape command) not allowed");
879 return_value = IFD_COMMUNICATION_ERROR;
880 }
881 else
882 {
883 unsigned int iBytesReturned;
884
885 iBytesReturned = RxLength;
886 return_value = CmdEscape(reader_index, TxBuffer, TxLength, RxBuffer,
887 &iBytesReturned);
888 *pdwBytesReturned = iBytesReturned;
889 }
890 }
891
892 /* Implement the PC/SC v2.1.2 Part 10 IOCTL mechanism */
893
894 /* Query for features */
895 if (CM_IOCTL_GET_FEATURE_REQUEST == dwControlCode)
896 {
897 unsigned int iBytesReturned = 0;
898 PCSC_TLV_STRUCTURE *pcsc_tlv = (PCSC_TLV_STRUCTURE *)RxBuffer;
899
900 /* we need room for two records */
901 if (RxLength < 2 * sizeof(PCSC_TLV_STRUCTURE))
902 return IFD_COMMUNICATION_ERROR;
903
904 /* We can only support direct verify and/or modify currently */
905 if (get_ccid_descriptor(reader_index) -> bPINSupport
906 & CCID_CLASS_PIN_VERIFY)
907 {
908 pcsc_tlv -> tag = FEATURE_VERIFY_PIN_DIRECT;
909 pcsc_tlv -> length = 0x04; /* always 0x04 */
910 pcsc_tlv -> value = IOCTL_FEATURE_VERIFY_PIN_DIRECT;
911
912 pcsc_tlv++;
913 iBytesReturned += sizeof(PCSC_TLV_STRUCTURE);
914 }
915
916 if (get_ccid_descriptor(reader_index) -> bPINSupport
917 & CCID_CLASS_PIN_MODIFY)
918 {
919 pcsc_tlv -> tag = FEATURE_MODIFY_PIN_DIRECT;
920 pcsc_tlv -> length = 0x04; /* always 0x04 */
921 pcsc_tlv -> value = IOCTL_FEATURE_MODIFY_PIN_DIRECT;
922
923 pcsc_tlv++;
924 iBytesReturned += sizeof(PCSC_TLV_STRUCTURE);
925 }
926 *pdwBytesReturned = iBytesReturned;
927 return_value = IFD_SUCCESS;
928 }
929
930 /* Verify a PIN, plain CCID */
931 if (IOCTL_FEATURE_VERIFY_PIN_DIRECT == dwControlCode)
932 {
933 unsigned int iBytesReturned;
934
935 iBytesReturned = RxLength;
936 return_value = SecurePINVerify(reader_index, TxBuffer, TxLength,
937 RxBuffer, &iBytesReturned);
938 *pdwBytesReturned = iBytesReturned;
939 }
940
941 /* Modify a PIN, plain CCID */
942 if (IOCTL_FEATURE_MODIFY_PIN_DIRECT == dwControlCode)
943 {
944 unsigned int iBytesReturned;
945
946 iBytesReturned = RxLength;
947 return_value = SecurePINModify(reader_index, TxBuffer, TxLength,
948 RxBuffer, &iBytesReturned);
949 *pdwBytesReturned = iBytesReturned;
950 }
951
952 return return_value;
953 } /* IFDHControl */
954
955
956 RESPONSECODE IFDHICCPresence(DWORD Lun)
957 {
958 /*
959 * This function returns the status of the card inserted in the
960 * reader/slot specified by Lun. It will return either:
961 *
962 * returns: IFD_ICC_PRESENT IFD_ICC_NOT_PRESENT
963 * IFD_COMMUNICATION_ERROR
964 */
965
966 unsigned char pcbuffer[SIZE_GET_SLOT_STATUS];
967 RESPONSECODE return_value = IFD_COMMUNICATION_ERROR;
968 int oldLogLevel;
969 int reader_index;
970 _ccid_descriptor *ccid_descriptor;
971 unsigned int oldReadTimeout;
972
973 DEBUG_PERIODIC2("lun: %X", Lun);
974
975 if (-1 == (reader_index = LunToReaderIndex(Lun)))
976 return IFD_COMMUNICATION_ERROR;
977
978 ccid_descriptor = get_ccid_descriptor(reader_index);
979
980 /* save the current read timeout computed from card capabilities */
981 oldReadTimeout = ccid_descriptor->readTimeout;
982
983 /* use default timeout since the reader may not be present anymore */
984 ccid_descriptor->readTimeout = DEFAULT_COM_READ_TIMEOUT;
985
986 /* if DEBUG_LEVEL_PERIODIC is not set we remove DEBUG_LEVEL_COMM */
987 oldLogLevel = LogLevel;
988 if (! (LogLevel & DEBUG_LEVEL_PERIODIC))
989 LogLevel &= ~DEBUG_LEVEL_COMM;
990
991 return_value = CmdGetSlotStatus(reader_index, pcbuffer);
992
993 /* set back the old timeout */
994 ccid_descriptor->readTimeout = oldReadTimeout;
995
996 /* set back the old LogLevel */
997 LogLevel = oldLogLevel;
998
999 if (return_value != IFD_SUCCESS)
1000 return IFD_COMMUNICATION_ERROR;
1001
1002 return_value = IFD_COMMUNICATION_ERROR;
1003 switch (pcbuffer[7] & CCID_ICC_STATUS_MASK) /* bStatus */
1004 {
1005 case CCID_ICC_PRESENT_ACTIVE:
1006 case CCID_ICC_PRESENT_INACTIVE:
1007 return_value = IFD_ICC_PRESENT;
1008 /* use default slot */
1009 break;
1010
1011 case CCID_ICC_ABSENT:
1012 /* Reset ATR buffer */
1013 CcidSlots[reader_index].nATRLength = 0;
1014 *CcidSlots[reader_index].pcATRBuffer = '\0';
1015
1016 /* Reset PowerFlags */
1017 CcidSlots[reader_index].bPowerFlags = POWERFLAGS_RAZ;
1018
1019 return_value = IFD_ICC_NOT_PRESENT;
1020 break;
1021 }
1022
1023 /* SCR331-DI contactless reader */
1024 if (((SCR331DI == ccid_descriptor->readerID)
1025 || (SCR331DINTTCOM == ccid_descriptor->readerID))
1026 && (ccid_descriptor->bCurrentSlotIndex > 0))
1027 {
1028 unsigned char cmd[] = { 0x11 };
1029 /* command: 11 ??
1030 * response: 00 11 01 ?? no card
1031 * 01 04 00 ?? card present */
1032
1033 unsigned char res[10];
1034 unsigned int length_res = sizeof(res);
1035
1036 /* if DEBUG_LEVEL_PERIODIC is not set we remove DEBUG_LEVEL_COMM */
1037 oldLogLevel = LogLevel;
1038 if (! (LogLevel & DEBUG_LEVEL_PERIODIC))
1039 LogLevel &= ~DEBUG_LEVEL_COMM;
1040
1041 CmdEscape(reader_index, cmd, sizeof(cmd), res, &length_res);
1042
1043 /* set back the old LogLevel */
1044 LogLevel = oldLogLevel;
1045
1046 if (0x01 == res[0])
1047 return_value = IFD_ICC_PRESENT;
1048 else
1049 {
1050 /* Reset ATR buffer */
1051 CcidSlots[reader_index].nATRLength = 0;
1052 *CcidSlots[reader_index].pcATRBuffer = '\0';
1053
1054 /* Reset PowerFlags */
1055 CcidSlots[reader_index].bPowerFlags = POWERFLAGS_RAZ;
1056
1057 return_value = IFD_ICC_NOT_PRESENT;
1058 }
1059 }
1060
1061 DEBUG_PERIODIC2("Card %s",
1062 IFD_ICC_PRESENT == return_value ? "present" : "absent");
1063
1064 return return_value;
1065 } /* IFDHICCPresence */
1066
1067
1068 CcidDesc *get_ccid_slot(unsigned int reader_index)
1069 {
1070 return &CcidSlots[reader_index];
1071 } /* get_ccid_slot */
1072
1073
1074 void init_driver(void)
1075 {
1076 char keyValue[TOKEN_MAX_VALUE_SIZE];
1077 char infofile[FILENAME_MAX];
1078
1079 /* Info.plist full patch filename */
1080 snprintf(infofile, sizeof(infofile), "%s/%s/Contents/Info.plist",
1081 PCSCLITE_HP_DROPDIR, BUNDLE);
1082
1083 /* Log level */
1084 if (0 == LTPBundleFindValueWithKey(infofile, "ifdLogLevel", keyValue, 0))
1085 {
1086 /* convert from hex or dec or octal */
1087 LogLevel = strtoul(keyValue, NULL, 0);
1088
1089 /* print the log level used */
1090 DEBUG_INFO2("LogLevel: 0x%.4X", LogLevel);
1091 }
1092
1093 /* Driver options */
1094 if (0 == LTPBundleFindValueWithKey(infofile, "ifdDriverOptions", keyValue, 0))
1095 {
1096 /* convert from hex or dec or octal */
1097 DriverOptions = strtoul(keyValue, NULL, 0);
1098
1099 /* print the log level used */
1100 DEBUG_INFO2("DriverOptions: 0x%.4X", DriverOptions);
1101 }
1102
1103 /* initialise the Lun to reader_index mapping */
1104 InitReaderIndex();
1105
1106 DebugInitialized = TRUE;
1107 } /* init_driver */
1108
1109
1110 void extra_egt(ATR_t *atr, _ccid_descriptor *ccid_desc, DWORD Protocol)
1111 {
1112 /* This function use an EGT value for cards who comply with followings
1113 * criterias:
1114 * - TA1 > 11
1115 * - current EGT = 0x00 or 0xFF
1116 * - T=0 or (T=1 and CWI >= 2)
1117 *
1118 * Without this larger EGT some non ISO 7816-3 smart cards may not
1119 * communicate with the reader.
1120 *
1121 * This modification is harmless, the reader will just be less restrictive
1122 */
1123
1124 unsigned int card_baudrate;
1125 unsigned int default_baudrate;
1126 double f, d;
1127 int i;
1128
1129 /* if TA1 not present */
1130 if (! atr->ib[0][ATR_INTERFACE_BYTE_TA].present)
1131 return;
1132
1133 ATR_GetParameter(atr, ATR_PARAMETER_D, &d);
1134 ATR_GetParameter(atr, ATR_PARAMETER_F, &f);
1135
1136 /* Baudrate = f x D/F */
1137 card_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock * d / f);
1138
1139 default_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock
1140 * ATR_DEFAULT_D / ATR_DEFAULT_F);
1141
1142 /* TA1 > 11? */
1143 if (card_baudrate <= default_baudrate)
1144 return;
1145
1146 /* Current EGT = 0 or FF? */
1147 if (atr->ib[0][ATR_INTERFACE_BYTE_TC].present &&
1148 ((0x00 == atr->ib[0][ATR_INTERFACE_BYTE_TC].value) ||
1149 (0xFF == atr->ib[0][ATR_INTERFACE_BYTE_TC].value)))
1150 {
1151 if (SCARD_PROTOCOL_T0 == Protocol)
1152 {
1153 /* Init TC1 */
1154 atr->ib[0][ATR_INTERFACE_BYTE_TC].present = TRUE;
1155 atr->ib[0][ATR_INTERFACE_BYTE_TC].value = 2;
1156 DEBUG_INFO("Extra EGT patch applied");
1157 }
1158
1159 if (SCARD_PROTOCOL_T1 == Protocol)
1160 {
1161 /* TBi (i>2) present? BWI/CWI */
1162 for (i=2; i<ATR_MAX_PROTOCOLS; i++)
1163 {
1164 /* CWI >= 2 ? */
1165 if (atr->ib[i][ATR_INTERFACE_BYTE_TB].present &&
1166 ((atr->ib[i][ATR_INTERFACE_BYTE_TB].value & 0x0F) >= 2))
1167 {
1168 /* Init TC1 */
1169 atr->ib[0][ATR_INTERFACE_BYTE_TC].present = TRUE;
1170 atr->ib[0][ATR_INTERFACE_BYTE_TC].value = 2;
1171 DEBUG_INFO("Extra EGT patch applied");
1172
1173 /* only the first TBi (i>2) must be used */
1174 break;
1175 }
1176 }
1177 }
1178 }
1179 } /* extra_egt */
1180
1181
1182 static char find_baud_rate(unsigned int baudrate, unsigned int *list)
1183 {
1184 int i;
1185
1186 DEBUG_COMM2("Card baud rate: %d", baudrate);
1187
1188 /* Does the reader support the annonced smart card data speed? */
1189 for (i=0;; i++)
1190 {
1191 /* end of array marker */
1192 if (0 == list[i])
1193 break;
1194
1195 DEBUG_COMM2("Reader can do: %d", list[i]);
1196
1197 /* We must take into account that the card_baudrate integral value
1198 * is an approximative result, computed from the d/f float result.
1199 */
1200 if ((baudrate < list[i] + 2) && (baudrate > list[i] - 2))
1201 return TRUE;
1202 }
1203
1204 return FALSE;
1205 } /* find_baud_rate */
1206
1207
1208 static unsigned int T0_card_timeout(double f, double d, int TC1, int TC2,
1209 int clock_frequency)
1210 {
1211 unsigned int timeout = DEFAULT_COM_READ_TIMEOUT;
1212 double EGT, WWT;
1213 unsigned int t;
1214
1215 /* Timeout applied on ISO_IN or ISO_OUT card exchange
1216 * we choose the maximum computed value.
1217 *
1218 * ISO_IN timeout is the sum of:
1219 * Terminal: Smart card:
1220 * 5 bytes header cmd ->
1221 * <- Procedure byte
1222 * 256 data bytes ->
1223 * <- SW1-SW2
1224 * = 261 EGT + 3 WWT + 3 WWT
1225 *
1226 * ISO_OUT Timeout is the sum of:
1227 * Terminal: Smart card:
1228 * 5 bytes header cmd ->
1229 * <- Procedure byte + 256 data bytes + SW1-SW2
1230 * = 5 EGT + 1 WWT + 259 WWT
1231 */
1232
1233 /* clock_frequency is in kHz so the times are in milliseconds and not
1234 * in seconds */
1235
1236 /* EGT */
1237 /* see ch. 6.5.3 Extra Guard Time, page 12 of ISO 7816-3 */
1238 EGT = 12 * f / d / clock_frequency + (f / d) * TC1 / clock_frequency;
1239
1240 /* card WWT */
1241 /* see ch. 8.2 Character level, page 15 of ISO 7816-3 */
1242 WWT = 960 * TC2 * f / clock_frequency;
1243
1244 /* ISO in */
1245 t = 261 * EGT + (3 + 3) * WWT;
1246 /* Convert from milliseonds to seconds rouned to the upper value
1247 * use +1 instead of ceil() to round up to the nearest interger
1248 * so we can avoid a dependency on the math library */
1249 t = t/1000 +1;
1250 if (timeout < t)
1251 timeout = t;
1252
1253 /* ISO out */
1254 t = 5 * EGT + (1 + 259) * WWT;
1255 t = t/1000 +1;
1256 if (timeout < t)
1257 timeout = t;
1258
1259 return timeout;
1260 } /* T0_card_timeout */
1261
1262
1263 static unsigned int T1_card_timeout(double f, double d, int TC1,
1264 int BWI, int CWI, int clock_frequency)
1265 {
1266 double EGT, BWT, CWT, etu;
1267 unsigned int timeout;
1268
1269 /* Timeout applied on ISO in + ISO out card exchange
1270 *
1271 * Timeout is the sum of:
1272 * - ISO in delay between leading edge of the first character sent by the
1273 * interface device and the last one (NAD PCB LN APDU CKS) = 260 EGT,
1274 * - delay between ISO in and ISO out = BWT,
1275 * - ISO out delay between leading edge of the first character sent by the
1276 * card and the last one (NAD PCB LN DATAS CKS) = 260 CWT.
1277 */
1278
1279 /* clock_frequency is in kHz so the times are in milliseconds and not
1280 * in seconds */
1281
1282 /* see ch. 6.5.2 Transmission factors F and D, page 12 of ISO 7816-3 */
1283 etu = f / d / clock_frequency;
1284
1285 /* EGT */
1286 /* see ch. 6.5.3 Extra Guard Time, page 12 of ISO 7816-3 */
1287 EGT = 12 * etu + (f / d) * TC1 / clock_frequency;
1288
1289 /* card BWT */
1290 /* see ch. 9.5.3.2 Block Waiting Time, page 20 of ISO 7816-3 */
1291 BWT = 11 * etu + (1<<BWI) * 960 * 372 / clock_frequency;
1292
1293 /* card CWT */
1294 /* see ch. 9.5.3.1 Caracter Waiting Time, page 20 of ISO 7816-3 */
1295 CWT = (11 + (1<<CWI)) * etu;
1296
1297 timeout = 260*EGT + BWT + 260*CWT;
1298
1299 /* Convert from milliseonds to seconds rounded to the upper value
1300 * we use +1 instead of ceil() to round up to the nearest greater interger
1301 * so we can avoid a dependency on the math library */
1302 timeout = timeout/1000 +1;
1303
1304 return timeout;
1305 } /* T1_card_timeout */
1306

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.5