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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.5