/[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 1156 - (show annotations) (download)
Fri Aug 6 11:32:01 2004 UTC (8 years, 9 months ago) by rousseau
File MIME type: text/plain
File size: 26675 byte(s)
IFDHICCPresence(): periodic debug message indicating the card presence/absence
1 /*
2 ifdhandler.c: IFDH API
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 /* $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
28 #include "ccid.h"
29 #include "defs.h"
30 #include "ccid_ifdhandler.h"
31 #include "config.h"
32 #include "debug.h"
33 #include "utils.h"
34 #include "commands.h"
35 #include "towitoko/atr.h"
36 #include "towitoko/pps.h"
37 #include "parser.h"
38
39 #ifdef HAVE_PTHREAD
40 #include <pthread.h>
41 #endif
42
43 /* Array of structures to hold the ATR and other state value of each slot */
44 static CcidDesc CcidSlots[CCID_DRIVER_MAX_READERS];
45
46 /* global mutex */
47 #ifdef HAVE_PTHREAD
48 static pthread_mutex_t ifdh_context_mutex = PTHREAD_MUTEX_INITIALIZER;
49 #endif
50
51 int LogLevel = DEBUG_LEVEL_CRITICAL | DEBUG_LEVEL_INFO;
52 int DriverOptions = 0;
53 static int DebugInitialized = FALSE;
54
55 /* local functions */
56 static void init_driver(void);
57
58
59 RESPONSECODE IFDHCreateChannelByName(DWORD Lun, LPTSTR lpcDevice)
60 {
61 RESPONSECODE return_value = IFD_SUCCESS;
62 int reader_index;
63
64 if (! DebugInitialized)
65 init_driver();
66
67 DEBUG_INFO3("lun: %X, device: %s", Lun, lpcDevice);
68
69 if (-1 == (reader_index = GetNewReaderIndex(Lun)))
70 return IFD_COMMUNICATION_ERROR;
71
72 /* Reset ATR buffer */
73 CcidSlots[reader_index].nATRLength = 0;
74 *CcidSlots[reader_index].pcATRBuffer = '\0';
75
76 /* Reset PowerFlags */
77 CcidSlots[reader_index].bPowerFlags = POWERFLAGS_RAZ;
78
79 #ifdef HAVE_PTHREAD
80 pthread_mutex_lock(&ifdh_context_mutex);
81 #endif
82
83 if (OpenPortByName(reader_index, lpcDevice) != STATUS_SUCCESS)
84 {
85 DEBUG_CRITICAL("failed");
86 return_value = IFD_COMMUNICATION_ERROR;
87
88 /* release the allocated reader_index */
89 ReleaseReaderIndex(reader_index);
90 }
91 else
92 /* Maybe we have a special treatment for this reader */
93 ccid_open_hack(reader_index);
94
95 #ifdef HAVE_PTHREAD
96 pthread_mutex_unlock(&ifdh_context_mutex);
97 #endif
98
99 return return_value;
100 } /* IFDHCreateChannelByName */
101
102
103 RESPONSECODE IFDHCreateChannel(DWORD Lun, DWORD Channel)
104 {
105 /*
106 * Lun - Logical Unit Number, use this for multiple card slots or
107 * multiple readers. 0xXXXXYYYY - XXXX multiple readers, YYYY multiple
108 * slots. The resource manager will set these automatically. By
109 * default the resource manager loads a new instance of the driver so
110 * if your reader does not have more than one smartcard slot then
111 * ignore the Lun in all the functions. Future versions of PC/SC might
112 * support loading multiple readers through one instance of the driver
113 * in which XXXX would be important to implement if you want this.
114 */
115
116 /*
117 * Channel - Channel ID. This is denoted by the following: 0x000001 -
118 * /dev/pcsc/1 0x000002 - /dev/pcsc/2 0x000003 - /dev/pcsc/3
119 *
120 * USB readers may choose to ignore this parameter and query the bus
121 * for the particular reader.
122 */
123
124 /*
125 * This function is required to open a communications channel to the
126 * port listed by Channel. For example, the first serial reader on
127 * COM1 would link to /dev/pcsc/1 which would be a sym link to
128 * /dev/ttyS0 on some machines This is used to help with intermachine
129 * independance.
130 *
131 * Once the channel is opened the reader must be in a state in which
132 * it is possible to query IFDHICCPresence() for card status.
133 *
134 * returns:
135 *
136 * IFD_SUCCESS IFD_COMMUNICATION_ERROR
137 */
138 RESPONSECODE return_value = IFD_SUCCESS;
139 int reader_index;
140
141 if (! DebugInitialized)
142 init_driver();
143
144 DEBUG_INFO2("lun: %X", Lun);
145
146 if (-1 == (reader_index = GetNewReaderIndex(Lun)))
147 return IFD_COMMUNICATION_ERROR;
148
149 /* Reset ATR buffer */
150 CcidSlots[reader_index].nATRLength = 0;
151 *CcidSlots[reader_index].pcATRBuffer = '\0';
152
153 /* Reset PowerFlags */
154 CcidSlots[reader_index].bPowerFlags = POWERFLAGS_RAZ;
155
156 #ifdef HAVE_PTHREAD
157 pthread_mutex_lock(&ifdh_context_mutex);
158 #endif
159
160 if (OpenPort(reader_index, Channel) != STATUS_SUCCESS)
161 {
162 DEBUG_CRITICAL("failed");
163 return_value = IFD_COMMUNICATION_ERROR;
164
165 /* release the allocated reader_index */
166 ReleaseReaderIndex(reader_index);
167 }
168 else
169 /* Maybe we have a special treatment for this reader */
170 ccid_open_hack(reader_index);
171
172 #ifdef HAVE_PTHREAD
173 pthread_mutex_unlock(&ifdh_context_mutex);
174 #endif
175
176 return return_value;
177 } /* IFDHCreateChannel */
178
179
180 RESPONSECODE IFDHCloseChannel(DWORD Lun)
181 {
182 /*
183 * This function should close the reader communication channel for the
184 * particular reader. Prior to closing the communication channel the
185 * reader should make sure the card is powered down and the terminal
186 * is also powered down.
187 *
188 * returns:
189 *
190 * IFD_SUCCESS IFD_COMMUNICATION_ERROR
191 */
192 int reader_index;
193
194 DEBUG_INFO2("lun: %X", Lun);
195
196 if (-1 == (reader_index = LunToReaderIndex(Lun)))
197 return IFD_COMMUNICATION_ERROR;
198
199 (void)CmdPowerOff(reader_index);
200 /* No reader status check, if it failed, what can you do ? :) */
201
202 #ifdef HAVE_PTHREAD
203 pthread_mutex_lock(&ifdh_context_mutex);
204 #endif
205
206 (void)ClosePort(reader_index);
207 ReleaseReaderIndex(reader_index);
208
209 #ifdef HAVE_PTHREAD
210 pthread_mutex_unlock(&ifdh_context_mutex);
211 #endif
212
213 return IFD_SUCCESS;
214 } /* IFDHCloseChannel */
215
216
217 RESPONSECODE IFDHGetCapabilities(DWORD Lun, DWORD Tag,
218 PDWORD Length, PUCHAR Value)
219 {
220 /*
221 * This function should get the slot/card capabilities for a
222 * particular slot/card specified by Lun. Again, if you have only 1
223 * card slot and don't mind loading a new driver for each reader then
224 * ignore Lun.
225 *
226 * Tag - the tag for the information requested example: TAG_IFD_ATR -
227 * return the Atr and it's size (required). these tags are defined in
228 * ifdhandler.h
229 *
230 * Length - the length of the returned data Value - the value of the
231 * data
232 *
233 * returns:
234 *
235 * IFD_SUCCESS IFD_ERROR_TAG
236 */
237 int reader_index;
238
239 DEBUG_INFO3("lun: %X, tag: 0x%X", Lun, Tag);
240
241 if (-1 == (reader_index = LunToReaderIndex(Lun)))
242 return IFD_COMMUNICATION_ERROR;
243
244 switch (Tag)
245 {
246 case TAG_IFD_ATR:
247 case SCARD_ATTR_ATR_STRING:
248 /* If Length is not zero, powerICC has been performed.
249 * Otherwise, return NULL pointer
250 * Buffer size is stored in *Length */
251 *Length = (*Length < CcidSlots[reader_index].nATRLength) ?
252 *Length : CcidSlots[reader_index].nATRLength;
253
254 if (*Length)
255 memcpy(Value, CcidSlots[reader_index]
256 .pcATRBuffer, *Length);
257 break;
258
259 #ifdef HAVE_PTHREAD
260 case TAG_IFD_SIMULTANEOUS_ACCESS:
261 if (*Length >= 1)
262 {
263 *Length = 1;
264 *Value = CCID_DRIVER_MAX_READERS;
265 }
266 break;
267
268 case TAG_IFD_THREAD_SAFE:
269 if (*Length >= 1)
270 {
271 *Length = 1;
272 *Value = 1; /* Can talk to multiple readers at the same time */
273 }
274 break;
275 #endif
276
277 case TAG_IFD_SLOTS_NUMBER:
278 if (*Length >= 1)
279 {
280 *Length = 1;
281 *Value = 1 + get_ccid_descriptor(reader_index) -> bMaxSlotIndex;
282 DEBUG_COMM2("Reader supports %d slots", *Value);
283 }
284 break;
285
286 case TAG_IFD_SLOT_THREAD_SAFE:
287 if (*Length >= 1)
288 {
289 *Length = 1;
290 *Value = 0; /* Can NOT talk to multiple slots at the same time */
291 }
292 break;
293
294 case IOCTL_SMARTCARD_VENDOR_VERIFY_PIN:
295 if (*Length >= 1)
296 {
297 *Length = 1;
298 *Value = get_ccid_descriptor(reader_index) -> bPINSupport & CCID_CLASS_PIN_VERIFY;
299 }
300 break;
301
302 default:
303 return IFD_ERROR_TAG;
304 }
305
306 return IFD_SUCCESS;
307 } /* IFDHGetCapabilities */
308
309
310 RESPONSECODE IFDHSetCapabilities(DWORD Lun, DWORD Tag,
311 /*@unused@*/ DWORD Length, /*@unused@*/ PUCHAR Value)
312 {
313 /*
314 * This function should set the slot/card capabilities for a
315 * particular slot/card specified by Lun. Again, if you have only 1
316 * card slot and don't mind loading a new driver for each reader then
317 * ignore Lun.
318 *
319 * Tag - the tag for the information needing set
320 *
321 * Length - the length of the returned data Value - the value of the
322 * data
323 *
324 * returns:
325 *
326 * IFD_SUCCESS IFD_ERROR_TAG IFD_ERROR_SET_FAILURE
327 * IFD_ERROR_VALUE_READ_ONLY
328 */
329
330 /* By default, say it worked */
331
332 DEBUG_INFO3("lun: %X, tag: 0x%X", Lun, Tag);
333
334 /* if (CheckLun(Lun))
335 return IFD_COMMUNICATION_ERROR; */
336
337 return IFD_NOT_SUPPORTED;
338 } /* IFDHSetCapabilities */
339
340
341 RESPONSECODE IFDHSetProtocolParameters(DWORD Lun, DWORD Protocol,
342 UCHAR Flags, UCHAR PTS1, UCHAR PTS2, UCHAR PTS3)
343 {
344 /*
345 * This function should set the PTS of a particular card/slot using
346 * the three PTS parameters sent
347 *
348 * Protocol - 0 .... 14 T=0 .... T=14
349 * Flags - Logical OR of possible values:
350 * IFD_NEGOTIATE_PTS1
351 * IFD_NEGOTIATE_PTS2
352 * IFD_NEGOTIATE_PTS3
353 * to determine which PTS values to negotiate.
354 * PTS1,PTS2,PTS3 - PTS Values.
355 *
356 * returns:
357 * IFD_SUCCESS
358 * IFD_ERROR_PTS_FAILURE
359 * IFD_COMMUNICATION_ERROR
360 * IFD_PROTOCOL_NOT_SUPPORTED
361 */
362
363 BYTE pps[PPS_MAX_LENGTH];
364 ATR atr;
365 unsigned int len;
366 int convention;
367 int reader_index;
368
369 /* Set ccid desc params */
370 CcidDesc *ccid_slot;
371 _ccid_descriptor *ccid_desc;
372
373 DEBUG_INFO3("lun: %X, protocol T=%d", Lun, Protocol-1);
374
375 if (-1 == (reader_index = LunToReaderIndex(Lun)))
376 return IFD_COMMUNICATION_ERROR;
377
378 /* Set to zero buffer */
379 memset(pps, 0, sizeof(pps));
380 memset(&atr, 0, sizeof(atr));
381
382 /* Get ccid params */
383 ccid_slot = get_ccid_slot(reader_index);
384 ccid_desc = get_ccid_descriptor(reader_index);
385
386 /* Get ATR of the card */
387 ATR_InitFromArray(&atr, ccid_slot->pcATRBuffer, ccid_slot->nATRLength);
388
389 if (SCARD_PROTOCOL_T0 == Protocol)
390 pps[1] |= ATR_PROTOCOL_TYPE_T0;
391 else
392 if (SCARD_PROTOCOL_T1 == Protocol)
393 pps[1] |= ATR_PROTOCOL_TYPE_T1;
394 else
395 return IFD_PROTOCOL_NOT_SUPPORTED;
396
397 /* TA2 present -> specific mode */
398 if (atr.ib[1][ATR_INTERFACE_BYTE_TA].present)
399 {
400 if (pps[1] != (atr.ib[1][ATR_INTERFACE_BYTE_TA].value & 0x0F))
401 {
402 /* wrong protocol */
403 DEBUG_COMM3("Specific mode in T=%d and T=%d requested",
404 atr.ib[1][ATR_INTERFACE_BYTE_TA].value & 0x0F, pps[1]);
405
406 return IFD_PROTOCOL_NOT_SUPPORTED;
407 }
408 }
409
410 /* TCi (i>2) indicates CRC instead of LRC */
411 if (SCARD_PROTOCOL_T1 == Protocol)
412 {
413 t1_state_t *t1 = &(ccid_slot -> t1);
414 int i;
415
416 /* TCi (i>2) present? */
417 for (i=2; i<ATR_MAX_PROTOCOLS; i++)
418 if (atr.ib[i][ATR_INTERFACE_BYTE_TC].present)
419 {
420 if (0 == atr.ib[i][ATR_INTERFACE_BYTE_TC].value)
421 {
422 DEBUG_COMM("Use LRC");
423 t1_set_param(t1, IFD_PROTOCOL_T1_CHECKSUM_LRC, 0);
424 }
425 else
426 if (1 == atr.ib[i][ATR_INTERFACE_BYTE_TC].value)
427 {
428 DEBUG_COMM("Use CRC");
429 t1_set_param(t1, IFD_PROTOCOL_T1_CHECKSUM_CRC, 0);
430 }
431 else
432 DEBUG_COMM2("Wrong value for TCi: %d",
433 atr.ib[i][ATR_INTERFACE_BYTE_TC].value);
434
435 /* only the first TCi (i>2) must be used */
436 break;
437 }
438 }
439
440 /* PTS1? */
441 if (Flags & IFD_NEGOTIATE_PTS1)
442 {
443 /* just use the value passed in argument */
444 pps[1] |= 0x10; /* PTS1 presence */
445 pps[2] = PTS1;
446 }
447 else
448 {
449 /* PPS not negociated by reader, and TA1 present */
450 if (atr.ib[0][ATR_INTERFACE_BYTE_TA].present &&
451 ! (ccid_desc->dwFeatures & CCID_CLASS_AUTO_PPS_CUR))
452 {
453 unsigned int card_baudrate;
454 unsigned int default_baudrate;
455 double f, d;
456
457 ATR_GetParameter(&atr, ATR_PARAMETER_D, &d);
458 ATR_GetParameter(&atr, ATR_PARAMETER_F, &f);
459
460 /* Baudrate = f x D/F */
461 card_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock
462 * d / f);
463
464 default_baudrate = (unsigned int) (1000 * ccid_desc->dwDefaultClock
465 * ATR_DEFAULT_D / ATR_DEFAULT_F);
466
467 /* if the reader is fast enough */
468 if ((card_baudrate < ccid_desc->dwMaxDataRate)
469 /* and the card does not try to lower the default speed */
470 && (card_baudrate > default_baudrate ))
471 {
472 pps[1] |= 0x10; /* PTS1 presence */
473 pps[2] = atr.ib[0][ATR_INTERFACE_BYTE_TA].value;
474
475 DEBUG_COMM2("Set speed to %d bauds", card_baudrate);
476 }
477 }
478 }
479
480 /* PTS2? */
481 if (Flags & IFD_NEGOTIATE_PTS2)
482 {
483 pps[1] |= 0x20; /* PTS2 presence */
484 pps[3] = PTS2;
485 }
486
487 /* PTS3? */
488 if (Flags & IFD_NEGOTIATE_PTS3)
489 {
490 pps[1] |= 0x40; /* PTS3 presence */
491 pps[4] = PTS3;
492 }
493
494 /* Generate PPS */
495 pps[0] = 0xFF;
496
497 /* Automatic PPS made by the ICC? */
498 if ((! (ccid_desc->dwFeatures & CCID_CLASS_AUTO_PPS_CUR))
499 /* TA2 absent: negociable mode */
500 && (! atr.ib[1][ATR_INTERFACE_BYTE_TA].present))
501 {
502 int default_protocol;
503
504 if (ATR_MALFORMED == ATR_GetDefaultProtocol(&atr, &default_protocol))
505 return IFD_PROTOCOL_NOT_SUPPORTED;
506
507 /* if the requested protocol is not the default one
508 * or a TA1/PPS1 is present */
509 if (((pps[1] & 0x0F) != default_protocol) || (PPS_HAS_PPS1(pps)))
510 if (PPS_Exchange(reader_index, pps, &len, &pps[2]) != PPS_OK)
511 {
512 DEBUG_INFO("PPS_Exchange Failed");
513
514 return IFD_ERROR_PTS_FAILURE;
515 }
516 }
517
518 /* Now we must set the reader parameters */
519 ATR_GetConvention(&atr, &convention);
520
521 /* specific mode and implicit parameters? (b5 of TA2) */
522 if (atr.ib[1][ATR_INTERFACE_BYTE_TA].present
523 && (atr.ib[1][ATR_INTERFACE_BYTE_TA].value & 0x10))
524 return IFD_COMMUNICATION_ERROR;
525
526 /* T=1 */
527 if (SCARD_PROTOCOL_T1 == Protocol)
528 {
529 BYTE param[] = {
530 0x11, /* Fi/Di */
531 0x10, /* TCCKS */
532 0x00, /* GuardTime */
533 0x4D, /* BWI/BCI */
534 0x00, /* ClockStop */
535 0x20, /* IFSC */
536 0x00 /* NADValue */
537 };
538 int i;
539
540 /* TA1 is not default */
541 if (PPS_HAS_PPS1(pps))
542 param[0] = pps[2];
543
544 if (ATR_CONVENTION_INVERSE == convention)
545 param[1] &= 0x02;
546
547 /* get TC1 Extra guard time */
548 if (atr.ib[0][ATR_INTERFACE_BYTE_TC].present)
549 param[2] = atr.ib[0][ATR_INTERFACE_BYTE_TC].value;
550
551 /* TBi (i>2) present? BWI/BCI */
552 for (i=2; i<ATR_MAX_PROTOCOLS; i++)
553 if (atr.ib[i][ATR_INTERFACE_BYTE_TB].present)
554 {
555 DEBUG_COMM3("BWI/BCI (TB%d) present: %d", i+1,
556 atr.ib[i][ATR_INTERFACE_BYTE_TB].value);
557 param[3] = atr.ib[i][ATR_INTERFACE_BYTE_TB].value;
558
559 /* only the first TBi (i>2) must be used */
560 break;
561 }
562
563 if (IFD_SUCCESS != SetParameters(reader_index, 1, sizeof(param), param))
564 return IFD_COMMUNICATION_ERROR;
565 }
566 else
567 /* T=0 */
568 {
569 BYTE param[] = {
570 0x11, /* Fi/Di */
571 0x00, /* TCCKS */
572 0x00, /* GuardTime */
573 0x0A, /* WaitingInteger */
574 0x00 /* ClockStop */
575 };
576
577 /* TA1 is not default */
578 if (PPS_HAS_PPS1(pps))
579 param[0] = pps[2];
580
581 if (ATR_CONVENTION_INVERSE == convention)
582 param[1] &= 0x02;
583
584 /* get TC1 Extra guard time */
585 if (atr.ib[0][ATR_INTERFACE_BYTE_TC].present)
586 param[2] = atr.ib[0][ATR_INTERFACE_BYTE_TC].value;
587
588 /* TC2 WWT */
589 if (atr.ib[1][ATR_INTERFACE_BYTE_TC].present)
590 param[3] = atr.ib[1][ATR_INTERFACE_BYTE_TC].value;
591
592 if (IFD_SUCCESS != SetParameters(reader_index, 0, sizeof(param), param))
593 return IFD_COMMUNICATION_ERROR;
594 }
595
596 /* set IFSC & IFSD in T=1 */
597 if (SCARD_PROTOCOL_T1 == Protocol)
598 {
599 t1_state_t *t1 = &(ccid_slot -> t1);
600 int i;
601
602 /* TAi (i>2) present? */
603 for (i=2; i<ATR_MAX_PROTOCOLS; i++)
604 if (atr.ib[i][ATR_INTERFACE_BYTE_TA].present)
605 {
606 DEBUG_COMM3("IFSC (TA%d) present: %d", i+1,
607 atr.ib[i][ATR_INTERFACE_BYTE_TA].value);
608 t1_set_param(t1, IFD_PROTOCOL_T1_IFSC,
609 atr.ib[i][ATR_INTERFACE_BYTE_TA].value);
610
611 /* only the first TAi (i>2) must be used */
612 break;
613 }
614
615 /* IFSD not negociated by the reader? */
616 if (! (ccid_desc->dwFeatures & CCID_CLASS_AUTO_IFSD))
617 {
618 DEBUG_COMM2("Negociate IFSD at %d", ccid_desc -> dwMaxIFSD);
619 if (t1_negociate_ifsd(t1, 0, ccid_desc -> dwMaxIFSD) < 0)
620 return IFD_COMMUNICATION_ERROR;
621 }
622 t1_set_param(t1, IFD_PROTOCOL_T1_IFSD, ccid_desc -> dwMaxIFSD);
623
624 DEBUG_COMM3("T=1: IFSC=%d, IFSD=%d", t1->ifsc, t1->ifsd);
625 }
626
627 return IFD_SUCCESS;
628 } /* IFDHSetProtocolParameters */
629
630
631 RESPONSECODE IFDHPowerICC(DWORD Lun, DWORD Action,
632 PUCHAR Atr, PDWORD AtrLength)
633 {
634 /*
635 * This function controls the power and reset signals of the smartcard
636 * reader at the particular reader/slot specified by Lun.
637 *
638 * Action - Action to be taken on the card.
639 *
640 * IFD_POWER_UP - Power and reset the card if not done so (store the
641 * ATR and return it and it's length).
642 *
643 * IFD_POWER_DOWN - Power down the card if not done already
644 * (Atr/AtrLength should be zero'd)
645 *
646 * IFD_RESET - Perform a quick reset on the card. If the card is not
647 * powered power up the card. (Store and return the Atr/Length)
648 *
649 * Atr - Answer to Reset of the card. The driver is responsible for
650 * caching this value in case IFDHGetCapabilities is called requesting
651 * the ATR and it's length. This should not exceed MAX_ATR_SIZE.
652 *
653 * AtrLength - Length of the Atr. This should not exceed
654 * MAX_ATR_SIZE.
655 *
656 * Notes:
657 *
658 * Memory cards without an ATR should return IFD_SUCCESS on reset but
659 * the Atr should be zero'd and the length should be zero
660 *
661 * Reset errors should return zero for the AtrLength and return
662 * IFD_ERROR_POWER_ACTION.
663 *
664 * returns:
665 *
666 * IFD_SUCCESS IFD_ERROR_POWER_ACTION IFD_COMMUNICATION_ERROR
667 * IFD_NOT_SUPPORTED
668 */
669
670 unsigned int nlength;
671 RESPONSECODE return_value = IFD_SUCCESS;
672 unsigned char pcbuffer[RESP_BUF_SIZE];
673 int reader_index;
674
675 DEBUG_INFO2("lun: %X", Lun);
676
677 /* By default, assume it won't work :) */
678 *AtrLength = 0;
679
680 if (-1 == (reader_index = LunToReaderIndex(Lun)))
681 return IFD_COMMUNICATION_ERROR;
682
683 switch (Action)
684 {
685 case IFD_POWER_DOWN:
686 /* Clear ATR buffer */
687 CcidSlots[reader_index].nATRLength = 0;
688 *CcidSlots[reader_index].pcATRBuffer = '\0';
689
690 /* Memorise the request */
691 CcidSlots[reader_index].bPowerFlags |=
692 MASK_POWERFLAGS_PDWN;
693
694 /* send the command */
695 if (IFD_SUCCESS != CmdPowerOff(reader_index))
696 {
697 DEBUG_CRITICAL("PowerDown failed");
698 return_value = IFD_ERROR_POWER_ACTION;
699 goto end;
700 }
701
702 /* clear T=1 context */
703 t1_release(&(get_ccid_slot(reader_index) -> t1));
704 break;
705
706 case IFD_POWER_UP:
707 case IFD_RESET:
708 nlength = sizeof(pcbuffer);
709 if (CmdPowerOn(reader_index, &nlength, pcbuffer) != IFD_SUCCESS)
710 {
711 DEBUG_CRITICAL("PowerUp failed");
712 return_value = IFD_ERROR_POWER_ACTION;
713 goto end;
714 }
715
716 /* Power up successful, set state variable to memorise it */
717 CcidSlots[reader_index].bPowerFlags |=
718 MASK_POWERFLAGS_PUP;
719 CcidSlots[reader_index].bPowerFlags &=
720 ~MASK_POWERFLAGS_PDWN;
721
722 /* Reset is returned, even if TCK is wrong */
723 CcidSlots[reader_index].nATRLength = *AtrLength =
724 (nlength < MAX_ATR_SIZE) ? nlength : MAX_ATR_SIZE;
725 memcpy(Atr, pcbuffer, *AtrLength);
726 memcpy(CcidSlots[reader_index].pcATRBuffer,
727 pcbuffer, *AtrLength);
728
729 /* initialise T=1 context */
730 t1_init(&(get_ccid_slot(reader_index) -> t1), reader_index);
731 break;
732
733 default:
734 DEBUG_CRITICAL("Action not supported");
735 return_value = IFD_NOT_SUPPORTED;
736 }
737 end:
738
739 return return_value;
740 } /* IFDHPowerICC */
741
742
743 RESPONSECODE IFDHTransmitToICC(DWORD Lun, SCARD_IO_HEADER SendPci,
744 PUCHAR TxBuffer, DWORD TxLength,
745 PUCHAR RxBuffer, PDWORD RxLength, /*@unused@*/ PSCARD_IO_HEADER RecvPci)
746 {
747 /*
748 * This function performs an APDU exchange with the card/slot
749 * specified by Lun. The driver is responsible for performing any
750 * protocol specific exchanges such as T=0/1 ... differences. Calling
751 * this function will abstract all protocol differences.
752 *
753 * SendPci Protocol - 0, 1, .... 14 Length - Not used.
754 *
755 * TxBuffer - Transmit APDU example (0x00 0xA4 0x00 0x00 0x02 0x3F
756 * 0x00) TxLength - Length of this buffer. RxBuffer - Receive APDU
757 * example (0x61 0x14) RxLength - Length of the received APDU. This
758 * function will be passed the size of the buffer of RxBuffer and this
759 * function is responsible for setting this to the length of the
760 * received APDU. This should be ZERO on all errors. The resource
761 * manager will take responsibility of zeroing out any temporary APDU
762 * buffers for security reasons.
763 *
764 * RecvPci Protocol - 0, 1, .... 14 Length - Not used.
765 *
766 * Notes: The driver is responsible for knowing what type of card it
767 * has. If the current slot/card contains a memory card then this
768 * command should ignore the Protocol and use the MCT style commands
769 * for support for these style cards and transmit them appropriately.
770 * If your reader does not support memory cards or you don't want to
771 * then ignore this.
772 *
773 * RxLength should be set to zero on error.
774 *
775 * returns:
776 *
777 * IFD_SUCCESS IFD_COMMUNICATION_ERROR IFD_RESPONSE_TIMEOUT
778 * IFD_ICC_NOT_PRESENT IFD_PROTOCOL_NOT_SUPPORTED
779 */
780
781 RESPONSECODE return_value;
782 unsigned int rx_length;
783 int reader_index;
784
785 DEBUG_INFO2("lun: %X", Lun);
786
787 if (-1 == (reader_index = LunToReaderIndex(Lun)))
788 return IFD_COMMUNICATION_ERROR;
789
790 rx_length = *RxLength;
791 return_value = CmdXfrBlock(reader_index, TxLength, TxBuffer, &rx_length,
792 RxBuffer, SendPci.Protocol);
793 *RxLength = rx_length;
794
795 return return_value;
796 } /* IFDHTransmitToICC */
797
798
799 RESPONSECODE IFDHControl(DWORD Lun, DWORD dwControlCode, PUCHAR TxBuffer,
800 DWORD TxLength, PUCHAR RxBuffer, DWORD RxLength, PDWORD pdwBytesReturned)
801 {
802 /*
803 * This function performs a data exchange with the reader (not the
804 * card) specified by Lun. Here XXXX will only be used. It is
805 * responsible for abstracting functionality such as PIN pads,
806 * biometrics, LCD panels, etc. You should follow the MCT, CTBCS
807 * specifications for a list of accepted commands to implement.
808 *
809 * TxBuffer - Transmit data TxLength - Length of this buffer. RxBuffer
810 * - Receive data RxLength - Length of the received data. This
811 * function will be passed the length of the buffer RxBuffer and it
812 * must set this to the length of the received data.
813 *
814 * Notes: RxLength should be zero on error.
815 */
816 RESPONSECODE return_value = IFD_COMMUNICATION_ERROR;
817 int reader_index;
818
819 DEBUG_INFO3("lun: %X, ControlCode: 0x%X", Lun, dwControlCode);
820
821 reader_index = LunToReaderIndex(Lun);
822 if ((-1 == reader_index) || (NULL == pdwBytesReturned)
823 || (NULL == RxBuffer))
824 return return_value;
825
826 /* Set the return length to 0 to avoid problems */
827 *pdwBytesReturned = 0;
828
829 if (IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE == dwControlCode)
830 {
831 if (FALSE == (DriverOptions & DRIVER_OPTION_CCID_EXCHANGE_AUTHORIZED))
832 {
833 DEBUG_INFO("ifd exchange (Escape command) not allowed");
834 return_value = IFD_COMMUNICATION_ERROR;
835 }
836 else
837 {
838 unsigned int iBytesReturned;
839
840 iBytesReturned = RxLength;
841 return_value = CmdEscape(reader_index, TxBuffer, TxLength, RxBuffer,
842 &iBytesReturned);
843 *pdwBytesReturned = iBytesReturned;
844 }
845 }
846
847 if (IOCTL_SMARTCARD_VENDOR_VERIFY_PIN == dwControlCode)
848 {
849 unsigned int iBytesReturned;
850
851 iBytesReturned = RxLength;
852 return_value = SecurePIN(reader_index, TxBuffer, TxLength, RxBuffer,
853 &iBytesReturned);
854 *pdwBytesReturned = iBytesReturned;
855 }
856
857 return return_value;
858 } /* IFDHControl */
859
860
861 RESPONSECODE IFDHICCPresence(DWORD Lun)
862 {
863 /*
864 * This function returns the status of the card inserted in the
865 * reader/slot specified by Lun. It will return either:
866 *
867 * returns: IFD_ICC_PRESENT IFD_ICC_NOT_PRESENT
868 * IFD_COMMUNICATION_ERROR
869 */
870
871 unsigned char pcbuffer[SIZE_GET_SLOT_STATUS];
872 RESPONSECODE return_value = IFD_COMMUNICATION_ERROR;
873 int oldLogLevel;
874 int reader_index;
875 _ccid_descriptor *ccid_descriptor;
876
877 DEBUG_PERIODIC2("lun: %X", Lun);
878
879 if (-1 == (reader_index = LunToReaderIndex(Lun)))
880 return IFD_COMMUNICATION_ERROR;
881
882 ccid_descriptor = get_ccid_descriptor(reader_index);
883
884 /* if DEBUG_LEVEL_PERIODIC is not set we remove DEBUG_LEVEL_COMM */
885 oldLogLevel = LogLevel;
886 if (! (LogLevel & DEBUG_LEVEL_PERIODIC))
887 LogLevel &= ~DEBUG_LEVEL_COMM;
888
889 return_value = CmdGetSlotStatus(reader_index, pcbuffer);
890
891 /* set back the old LogLevel */
892 LogLevel = oldLogLevel;
893
894 if (return_value != IFD_SUCCESS)
895 return IFD_COMMUNICATION_ERROR;
896
897 return_value = IFD_COMMUNICATION_ERROR;
898 switch (pcbuffer[7]) /* bStatus */
899 {
900 case 0x00:
901 case 0x01:
902 return_value = IFD_ICC_PRESENT;
903 /* use default slot */
904 break;
905
906 case 0x02:
907 /* Reset ATR buffer */
908 CcidSlots[reader_index].nATRLength = 0;
909 *CcidSlots[reader_index].pcATRBuffer = '\0';
910
911 /* Reset PowerFlags */
912 CcidSlots[reader_index].bPowerFlags = POWERFLAGS_RAZ;
913
914 return_value = IFD_ICC_NOT_PRESENT;
915 break;
916 }
917
918 /* SCR331-DI contactless reader */
919 if ((SCR331DI == ccid_descriptor->readerID)
920 && (ccid_descriptor->bCurrentSlotIndex > 0))
921 {
922 unsigned char cmd[] = { 0x11 };
923 /* command: 11 ??
924 * response: 00 11 01 ?? no card
925 * 01 04 00 ?? card present */
926
927 unsigned char res[10];
928 unsigned int length_res = sizeof(res);
929
930 /* if DEBUG_LEVEL_PERIODIC is not set we remove DEBUG_LEVEL_COMM */
931 oldLogLevel = LogLevel;
932 if (! (LogLevel & DEBUG_LEVEL_PERIODIC))
933 LogLevel &= ~DEBUG_LEVEL_COMM;
934
935 CmdEscape(reader_index, cmd, sizeof(cmd), res, &length_res);
936
937 /* set back the old LogLevel */
938 LogLevel = oldLogLevel;
939
940 if (0x01 == res[0])
941 return_value = IFD_ICC_PRESENT;
942 else
943 {
944 /* Reset ATR buffer */
945 CcidSlots[reader_index].nATRLength = 0;
946 *CcidSlots[reader_index].pcATRBuffer = '\0';
947
948 /* Reset PowerFlags */
949 CcidSlots[reader_index].bPowerFlags = POWERFLAGS_RAZ;
950
951 return_value = IFD_ICC_NOT_PRESENT;
952 }
953 }
954
955 DEBUG_PERIODIC2("Card %s",
956 IFD_ICC_PRESENT == return_value ? "present" : "absent");
957
958 return return_value;
959 } /* IFDHICCPresence */
960
961
962 CcidDesc *get_ccid_slot(unsigned int reader_index)
963 {
964 return &CcidSlots[reader_index];
965 } /* get_ccid_slot */
966
967
968 void init_driver(void)
969 {
970 char keyValue[TOKEN_MAX_VALUE_SIZE];
971 char infofile[FILENAME_MAX];
972
973 /* Info.plist full patch filename */
974 snprintf(infofile, sizeof(infofile), "%s/%s/Contents/Info.plist",
975 PCSCLITE_HP_DROPDIR, BUNDLE);
976
977 /* Log level */
978 if (0 == LTPBundleFindValueWithKey(infofile, "ifdLogLevel", keyValue, 0))
979 {
980 /* convert from hex or dec or octal */
981 LogLevel = strtoul(keyValue, NULL, 0);
982
983 /* print the log level used */
984 debug_msg("%s:%d:%s LogLevel: 0x%.4X", __FILE__, __LINE__, __FUNCTION__,
985 LogLevel);
986 }
987
988 /* Driver options */
989 if (0 == LTPBundleFindValueWithKey(infofile, "ifdDriverOptions", keyValue, 0))
990 {
991 /* convert from hex or dec or octal */
992 DriverOptions = strtoul(keyValue, NULL, 0);
993
994 /* print the log level used */
995 debug_msg("%s:%d:%s DriverOptions: 0x%.4X", __FILE__, __LINE__,
996 __FUNCTION__, DriverOptions);
997 }
998
999 /* initialise the Lun to reader_index mapping */
1000 InitReaderIndex();
1001
1002 DebugInitialized = TRUE;
1003 } /* init_driver */
1004

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.5