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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.5