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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.5