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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.5