/[pcsclite]/trunk/Drivers/ccid/examples/scardcontrol.c
ViewVC logotype

Contents of /trunk/Drivers/ccid/examples/scardcontrol.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1742 - (hide annotations) (download)
Thu Nov 24 15:26:41 2005 UTC (7 years, 6 months ago) by rousseau
File MIME type: text/plain
File size: 15915 byte(s)
exit if the test applet is not found
1 rousseau 889 /*
2     scardcontrol.c: sample code to use/test SCardControl() API
3     Copyright (C) 2004 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     /*
21     * $Id$
22     */
23    
24     #include <stdio.h>
25     #include <stdlib.h>
26 rousseau 1346 #include <sys/time.h>
27 rousseau 889 #include <unistd.h>
28     #include <string.h>
29 rousseau 972 #include <PCSC/winscard.h>
30 rousseau 1558 #include <PCSC/reader.h>
31 rousseau 889
32 rousseau 1676 #define VERIFY_PIN
33     #undef MODIFY_PIN
34    
35 rousseau 889 #ifndef TRUE
36     #define TRUE 1
37     #define FALSE 0
38     #endif
39    
40     #define IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE SCARD_CTL_CODE(1)
41    
42     /* PCSC error message pretty print */
43     #define PCSC_ERROR_EXIT(rv, text) \
44     if (rv != SCARD_S_SUCCESS) \
45     { \
46     printf(text ": %s (0x%lX)\n", pcsc_stringify_error(rv), rv); \
47     goto end; \
48     } \
49     else \
50     printf(text ": OK\n\n");
51    
52     #define PCSC_ERROR_CONT(rv, text) \
53     if (rv != SCARD_S_SUCCESS) \
54     printf(text ": %s (0x%lX)\n", pcsc_stringify_error(rv), rv); \
55     else \
56     printf(text ": OK\n\n");
57    
58     int main(int argc, char *argv[])
59     {
60     LONG rv;
61     SCARDCONTEXT hContext;
62     DWORD dwReaders;
63 rousseau 972 LPTSTR mszReaders;
64 rousseau 889 char *ptr, **readers = NULL;
65     int nbReaders;
66     SCARDHANDLE hCard;
67     DWORD dwActiveProtocol, dwReaderLen, dwState, dwProt, dwAtrLen;
68     BYTE pbAtr[MAX_ATR_SIZE] = "";
69 rousseau 892 char pbReader[MAX_READERNAME] = "";
70 rousseau 889 int reader_nb;
71 rousseau 1691 int i;
72 rousseau 889 unsigned char bSendBuffer[MAX_BUFFER_SIZE];
73     unsigned char bRecvBuffer[MAX_BUFFER_SIZE];
74 rousseau 1676 DWORD send_length, length;
75 rousseau 1631 DWORD verify_ioctl = 0;
76     DWORD modify_ioctl = 0;
77 rousseau 972 SCARD_IO_REQUEST pioRecvPci;
78 rousseau 1635 SCARD_IO_REQUEST pioSendPci;
79 rousseau 1631 PCSC_TLV_STRUCTURE *pcsc_tlv;
80 rousseau 1691 #if defined(VERIFY_PIN) | defined(MODIFY_PIN)
81     int offset;
82     #endif
83     #ifdef VERIFY_PIN
84 rousseau 1631 PIN_VERIFY_STRUCTURE *pin_verify;
85 rousseau 1691 #endif
86     #ifdef MODIFY_PIN
87 rousseau 1631 PIN_MODIFY_STRUCTURE *pin_modify;
88 rousseau 1691 #endif
89 rousseau 889
90     printf("SCardControl sample code\n");
91 rousseau 1676 printf("V 1.1 2004-2005, Ludovic Rousseau <ludovic.rousseau@free.fr>\n");
92 rousseau 889
93 rousseau 1263 printf("\nTHIS PROGRAM IS NOT DESIGNED AS A TESTING TOOL!\n");
94     printf("Do NOT use it unless you really know what you do.\n\n");
95    
96 rousseau 889 rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
97     if (rv != SCARD_S_SUCCESS)
98     {
99     printf("SCardEstablishContext: Cannot Connect to Resource Manager %lX\n", rv);
100     return 1;
101     }
102    
103     /* Retrieve the available readers list */
104     rv = SCardListReaders(hContext, NULL, NULL, &dwReaders);
105     if (rv != SCARD_S_SUCCESS)
106     {
107     printf("SCardListReader: %lX\n", rv);
108     }
109    
110     mszReaders = malloc(sizeof(char)*dwReaders);
111     if (mszReaders == NULL)
112     {
113     printf("malloc: not enough memory\n");
114     goto end;
115     }
116    
117     rv = SCardListReaders(hContext, NULL, mszReaders, &dwReaders);
118     if (rv != SCARD_S_SUCCESS)
119     printf("SCardListReader: %lX\n", rv);
120    
121     /* Extract readers from the null separated string and get the total
122     * number of readers */
123     nbReaders = 0;
124     ptr = mszReaders;
125     while (*ptr != '\0')
126     {
127     ptr += strlen(ptr)+1;
128     nbReaders++;
129     }
130    
131     if (nbReaders == 0)
132     {
133     printf("No reader found\n");
134     goto end;
135     }
136    
137     /* allocate the readers table */
138     readers = calloc(nbReaders, sizeof(char *));
139     if (NULL == readers)
140     {
141     printf("Not enough memory for readers[]\n");
142     goto end;
143     }
144    
145     /* fill the readers table */
146     nbReaders = 0;
147     ptr = mszReaders;
148     while (*ptr != '\0')
149     {
150     printf("%d: %s\n", nbReaders, ptr);
151     readers[nbReaders] = ptr;
152     ptr += strlen(ptr)+1;
153     nbReaders++;
154     }
155    
156     if (argc > 1)
157     {
158     reader_nb = atoi(argv[1]);
159     if (reader_nb < 0 || reader_nb >= nbReaders)
160     {
161     printf("Wrong reader index: %d\n", reader_nb);
162     goto end;
163     }
164     }
165     else
166     reader_nb = 0;
167    
168 rousseau 900 /* connect to a reader (even without a card) */
169 rousseau 889 dwActiveProtocol = -1;
170     rv = SCardConnect(hContext, readers[reader_nb], SCARD_SHARE_DIRECT,
171 rousseau 940 SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol);
172 rousseau 889 printf(" Protocol: %ld\n", dwActiveProtocol);
173     PCSC_ERROR_EXIT(rv, "SCardConnect")
174    
175 rousseau 972 /* get GemPC firmware */
176     printf(" Get GemPC Firmware\n");
177 rousseau 889
178     /* this is specific to Gemplus readers */
179     bSendBuffer[0] = 0x02;
180     rv = SCardControl(hCard, IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE, bSendBuffer,
181     1, bRecvBuffer, sizeof(bRecvBuffer), &length);
182    
183     printf(" Firmware: ");
184     for (i=0; i<length; i++)
185     printf("%02X ", bRecvBuffer[i]);
186     printf("\n");
187    
188     bRecvBuffer[length] = '\0';
189     printf(" Firmware: %s (length %ld bytes)\n", bRecvBuffer, length);
190    
191     PCSC_ERROR_CONT(rv, "SCardControl")
192    
193     /* get card status */
194     dwAtrLen = sizeof(pbAtr);
195     dwReaderLen = sizeof(pbReader);
196     rv = SCardStatus(hCard, pbReader, &dwReaderLen, &dwState, &dwProt,
197     pbAtr, &dwAtrLen);
198     printf(" Reader: %s (length %ld bytes)\n", pbReader, dwReaderLen);
199     printf(" State: 0x%lX\n", dwState);
200     printf(" Prot: %ld\n", dwProt);
201     printf(" ATR (length %ld bytes):", dwAtrLen);
202     for (i=0; i<dwAtrLen; i++)
203     printf(" %02X", pbAtr[i]);
204     printf("\n");
205     PCSC_ERROR_CONT(rv, "SCardStatus")
206    
207 rousseau 900 /* does the reader support PIN verification? */
208 rousseau 1631 rv = SCardControl(hCard, CM_IOCTL_GET_FEATURE_REQUEST, NULL, 0,
209     bRecvBuffer, sizeof(bRecvBuffer), &length);
210    
211     printf(" TLV (%ld): ", length);
212     for (i=0; i<length; i++)
213     printf("%02X ", bRecvBuffer[i]);
214     printf("\n");
215    
216     PCSC_ERROR_CONT(rv, "SCardControl(CM_IOCTL_GET_FEATURE_REQUEST)")
217    
218     if (length % sizeof(PCSC_TLV_STRUCTURE))
219 rousseau 900 {
220 rousseau 1631 printf("Inconsistent result! Bad TLV values!\n");
221     goto end;
222     }
223    
224     /* get the number of elements instead of the complete size */
225     length /= sizeof(PCSC_TLV_STRUCTURE);
226    
227     pcsc_tlv = (PCSC_TLV_STRUCTURE *)bRecvBuffer;
228     for (i = 0; i < length; i++)
229     {
230     if (pcsc_tlv[i].tag == FEATURE_VERIFY_PIN_DIRECT)
231     verify_ioctl = pcsc_tlv[i].value;
232     if (pcsc_tlv[i].tag == FEATURE_MODIFY_PIN_DIRECT)
233     modify_ioctl = pcsc_tlv[i].value;
234     }
235    
236     if (0 == verify_ioctl)
237     {
238 rousseau 900 printf("Reader %s does not support PIN verification\n",
239     readers[reader_nb]);
240     goto end;
241     }
242    
243 rousseau 972 /* connect to a reader (even without a card) */
244     dwActiveProtocol = -1;
245     rv = SCardReconnect(hCard, SCARD_SHARE_SHARED,
246 rousseau 1635 SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1, SCARD_UNPOWER_CARD,
247     &dwActiveProtocol);
248 rousseau 972 printf(" Protocol: %ld\n", dwActiveProtocol);
249     PCSC_ERROR_EXIT(rv, "SCardReconnect")
250    
251 rousseau 1635 switch(dwActiveProtocol)
252     {
253     case SCARD_PROTOCOL_T0:
254     pioSendPci = *SCARD_PCI_T0;
255     break;
256     case SCARD_PROTOCOL_T1:
257     pioSendPci = *SCARD_PCI_T1;
258     break;
259     default:
260     printf("Unknown protocol\n");
261     return -1;
262     }
263    
264 rousseau 1676 /* APDU select applet */
265     printf("Select applet: ");
266     send_length = 11;
267     memcpy(bSendBuffer, "\x00\xA4\x04\x00\x06\xA0\x00\x00\x00\x18\xFF",
268     send_length);
269     for (i=0; i<send_length; i++)
270     printf(" %02X", bSendBuffer[i]);
271 rousseau 972 printf("\n");
272     length = sizeof(bRecvBuffer);
273 rousseau 1676 rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length,
274 rousseau 972 &pioRecvPci, bRecvBuffer, &length);
275     printf(" card response:");
276     for (i=0; i<length; i++)
277     printf(" %02X", bRecvBuffer[i]);
278     printf("\n");
279     PCSC_ERROR_EXIT(rv, "SCardTransmit")
280 rousseau 1742 if ((bRecvBuffer[0] != 0x90) || (bRecvBuffer[0] != 0x00))
281     {
282     printf("Error: test applet not found!\n");
283     goto end;
284     }
285 rousseau 972
286 rousseau 1676 #ifdef VERIFY_PIN
287 rousseau 889 /* verify PIN */
288     printf(" Secure verify PIN\n");
289 rousseau 1631 pin_verify = (PIN_VERIFY_STRUCTURE *)bSendBuffer;
290    
291     /* PC/SC v2.0.2 Part 10 PIN verification data structure */
292     pin_verify -> bTimerOut = 0x00;
293     pin_verify -> bTimerOut2 = 0x00;
294     pin_verify -> bmFormatString = 0x82;
295     pin_verify -> bmPINBlockString = 0x04;
296     pin_verify -> bmPINLengthFormat = 0x00;
297 rousseau 1669 pin_verify -> wPINMaxExtraDigit = HOST_TO_CCID_16(0x0408); /* Min Max */
298 rousseau 1711 pin_verify -> bEntryValidationCondition = 0x02; /* validation key pressed */
299 rousseau 1712 pin_verify -> bNumberMessage = 0x01;
300 rousseau 1669 pin_verify -> wLangId = HOST_TO_CCID_16(0x0904);
301 rousseau 1631 pin_verify -> bMsgIndex = 0x00;
302     pin_verify -> bTeoPrologue[0] = 0x00;
303     pin_verify -> bTeoPrologue[1] = 0x00;
304     pin_verify -> bTeoPrologue[2] = 0x00;
305     /* pin_verify -> ulDataLength = 0x00; we don't know the size yet */
306    
307     /* APDU: 00 20 00 00 08 30 30 30 30 00 00 00 00 */
308 rousseau 889 offset = 0;
309 rousseau 1631 pin_verify -> abData[offset++] = 0x00; /* CLA */
310     pin_verify -> abData[offset++] = 0x20; /* INS: VERIFY */
311     pin_verify -> abData[offset++] = 0x00; /* P1 */
312     pin_verify -> abData[offset++] = 0x00; /* P2 */
313     pin_verify -> abData[offset++] = 0x08; /* Lc: 8 data bytes */
314     pin_verify -> abData[offset++] = 0x30; /* '0' */
315     pin_verify -> abData[offset++] = 0x30; /* '0' */
316     pin_verify -> abData[offset++] = 0x30; /* '0' */
317     pin_verify -> abData[offset++] = 0x30; /* '0' */
318     pin_verify -> abData[offset++] = 0x00; /* '\0' */
319     pin_verify -> abData[offset++] = 0x00; /* '\0' */
320     pin_verify -> abData[offset++] = 0x00; /* '\0' */
321     pin_verify -> abData[offset++] = 0x00; /* '\0' */
322 rousseau 1669 pin_verify -> ulDataLength = HOST_TO_CCID_32(offset); /* APDU size */
323 rousseau 889
324 rousseau 1631 length = sizeof(PIN_VERIFY_STRUCTURE) + offset -1; /* -1 because PIN_VERIFY_STRUCTURE contains the first byte of abData[] */
325 rousseau 889
326 rousseau 1631 printf(" command:");
327     for (i=0; i<length; i++)
328     printf(" %02X", bSendBuffer[i]);
329     printf("\n");
330     printf("Enter your PIN: ");
331     fflush(stdout);
332     rv = SCardControl(hCard, verify_ioctl, bSendBuffer,
333     length, bRecvBuffer, sizeof(bRecvBuffer), &length);
334    
335     {
336     #ifndef S_SPLINT_S
337     fd_set fd;
338     #endif
339     struct timeval timeout;
340    
341     FD_ZERO(&fd);
342     FD_SET(STDIN_FILENO, &fd); /* stdin */
343     timeout.tv_sec = 0; /* timeout = 0 */
344     timeout.tv_usec = 0;
345    
346     /* we only try to read stdin if the pinpad is on a keyboard
347     * we do not read stdin for a SPR 532 for example */
348     if (select(1, &fd, NULL, NULL, &timeout) > 0)
349     {
350     /* read the fake digits */
351     char in[10]; /* 4 digits + \n + \0 */
352     (void)fgets(in, sizeof(in), stdin);
353    
354     printf("keyboard sent: %s", in);
355     }
356 rousseau 1676 else
357     /* if it is not a keyboard */
358     printf("\n");
359 rousseau 1631 }
360    
361 rousseau 1676 printf(" card response:");
362     for (i=0; i<length; i++)
363     printf(" %02X", bRecvBuffer[i]);
364     printf("\n");
365     PCSC_ERROR_CONT(rv, "SCardControl")
366    
367     /* verify PIN dump */
368     printf("\nverify PIN dump: ");
369     send_length = 5;
370     memcpy(bSendBuffer, "\x00\x40\x00\x00\xFF",
371     send_length);
372     for (i=0; i<send_length; i++)
373     printf(" %02X", bSendBuffer[i]);
374     printf("\n");
375     length = sizeof(bRecvBuffer);
376     rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length,
377     &pioRecvPci, bRecvBuffer, &length);
378     printf(" card response:");
379     for (i=0; i<length; i++)
380     printf(" %02X", bRecvBuffer[i]);
381     printf("\n");
382     PCSC_ERROR_EXIT(rv, "SCardTransmit")
383    
384     if ((2 == length) && (0x6C == bRecvBuffer[0]))
385     {
386     printf("\nverify PIN dump: ");
387     send_length = 5;
388     memcpy(bSendBuffer, "\x00\x40\x00\x00\xFF",
389     send_length);
390     bSendBuffer[4] = bRecvBuffer[1];
391     for (i=0; i<send_length; i++)
392     printf(" %02X", bSendBuffer[i]);
393     printf("\n");
394     length = sizeof(bRecvBuffer);
395     rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length,
396     &pioRecvPci, bRecvBuffer, &length);
397     printf(" card response:");
398     for (i=0; i<length; i++)
399     printf(" %02X", bRecvBuffer[i]);
400     printf("\n");
401     PCSC_ERROR_EXIT(rv, "SCardTransmit")
402     }
403     #endif
404    
405     /* check if the reader supports Modify PIN */
406 rousseau 1631 if (0 == modify_ioctl)
407     {
408     printf("Reader %s does not support PIN modification\n",
409     readers[reader_nb]);
410     goto end;
411     }
412    
413 rousseau 1676 #ifdef MODIFY_PIN
414 rousseau 1631 /* Modify PIN */
415     printf(" Secure modify PIN\n");
416     pin_modify = (PIN_MODIFY_STRUCTURE *)bSendBuffer;
417    
418     /* PC/SC v2.0.2 Part 10 PIN verification data structure */
419     pin_modify -> bTimerOut = 0x00;
420     pin_modify -> bTimerOut2 = 0x00;
421     pin_modify -> bmFormatString = 0x82;
422     pin_modify -> bmPINBlockString = 0x04;
423     pin_modify -> bmPINLengthFormat = 0x00;
424 rousseau 1716 pin_modify -> bInsertionOffsetOld = 0x00; /* offset from APDU start */
425 rousseau 1717 pin_modify -> bInsertionOffsetNew = 0x04; /* offset from APDU start */
426     pin_modify -> wPINMaxExtraDigit = HOST_TO_CCID_16(0x0404); /* Min Max */
427 rousseau 1634 pin_modify -> bConfirmPIN = 0x03; /* b0 set = confirmation requested */
428     /* b1 set = current PIN entry requested */
429     pin_modify -> bEntryValidationCondition = 0x02; /* validation key pressed */
430 rousseau 1714 pin_modify -> bNumberMessage = 0x03; /* 3 for GemPC Pinpad, 0 for SPR532 */
431 rousseau 1669 pin_modify -> wLangId = HOST_TO_CCID_16(0x0904);
432 rousseau 1631 pin_modify -> bMsgIndex1 = 0x00;
433     pin_modify -> bMsgIndex2 = 0x00;
434     pin_modify -> bMsgIndex3 = 0x00;
435     pin_modify -> bTeoPrologue[0] = 0x00;
436     pin_modify -> bTeoPrologue[1] = 0x00;
437     pin_modify -> bTeoPrologue[2] = 0x00;
438 rousseau 1634 /* pin_modify -> ulDataLength = 0x00; we don't know the size yet */
439 rousseau 1631
440 rousseau 1300 /* APDU: 00 20 00 00 08 30 30 30 30 00 00 00 00 */
441 rousseau 1631 offset = 0;
442     pin_modify -> abData[offset++] = 0x00; /* CLA */
443 rousseau 1634 pin_modify -> abData[offset++] = 0x24; /* INS: CHANGE/UNBLOCK */
444 rousseau 1631 pin_modify -> abData[offset++] = 0x00; /* P1 */
445     pin_modify -> abData[offset++] = 0x00; /* P2 */
446 rousseau 1717 pin_modify -> abData[offset++] = 0x08; /* Lc: 2x8 data bytes */
447 rousseau 1634 pin_modify -> abData[offset++] = 0x30; /* '0' old PIN */
448 rousseau 1631 pin_modify -> abData[offset++] = 0x30; /* '0' */
449     pin_modify -> abData[offset++] = 0x30; /* '0' */
450     pin_modify -> abData[offset++] = 0x30; /* '0' */
451 rousseau 1634 pin_modify -> abData[offset++] = 0x30; /* '0' new PIN */
452 rousseau 1631 pin_modify -> abData[offset++] = 0x30; /* '0' */
453 rousseau 1634 pin_modify -> abData[offset++] = 0x30; /* '0' */
454     pin_modify -> abData[offset++] = 0x30; /* '0' */
455 rousseau 1669 pin_modify -> ulDataLength = HOST_TO_CCID_32(offset); /* APDU size */
456 rousseau 1300
457 rousseau 1634 length = sizeof(PIN_MODIFY_STRUCTURE) + offset -1; /* -1 because PIN_MODIFY_STRUCTURE contains the first byte of abData[] */
458    
459 rousseau 889 printf(" command:");
460 rousseau 1631 for (i=0; i<length; i++)
461 rousseau 889 printf(" %02X", bSendBuffer[i]);
462     printf("\n");
463 rousseau 972 printf("Enter your PIN: ");
464 rousseau 900 fflush(stdout);
465 rousseau 1634 rv = SCardControl(hCard, modify_ioctl, bSendBuffer,
466 rousseau 1631 length, bRecvBuffer, sizeof(bRecvBuffer), &length);
467 rousseau 889
468     printf(" card response:");
469     for (i=0; i<length; i++)
470     printf(" %02X", bRecvBuffer[i]);
471     printf("\n");
472     PCSC_ERROR_CONT(rv, "SCardControl")
473    
474 rousseau 972 {
475 rousseau 1067 #ifndef S_SPLINT_S
476 rousseau 972 fd_set fd;
477 rousseau 1067 #endif
478 rousseau 972 struct timeval timeout;
479    
480     FD_ZERO(&fd);
481     FD_SET(STDIN_FILENO, &fd); /* stdin */
482     timeout.tv_sec = 0; /* timeout = 0 */
483     timeout.tv_usec = 0;
484    
485     /* we only try to read stdin if the pinpad is on a keyboard
486     * we do not read stdin for a SPR 532 for example */
487     if (select(1, &fd, NULL, NULL, &timeout) > 0)
488     {
489     /* read the fake digits */
490     char in[10]; /* 4 digits + \n + \0 */
491 rousseau 1059 (void)fgets(in, sizeof(in), stdin);
492 rousseau 972
493     printf("keyboard sent: %s", in);
494     }
495     }
496 rousseau 1715
497     /* modify PIN dump */
498     printf("\nmodify PIN dump: ");
499     send_length = 5;
500     memcpy(bSendBuffer, "\x00\x40\x00\x00\xFF",
501     send_length);
502     for (i=0; i<send_length; i++)
503     printf(" %02X", bSendBuffer[i]);
504     printf("\n");
505     length = sizeof(bRecvBuffer);
506     rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length,
507     &pioRecvPci, bRecvBuffer, &length);
508     printf(" card response:");
509     for (i=0; i<length; i++)
510     printf(" %02X", bRecvBuffer[i]);
511     printf("\n");
512     PCSC_ERROR_EXIT(rv, "SCardTransmit")
513    
514     if ((2 == length) && (0x6C == bRecvBuffer[0]))
515     {
516     printf("\nverify PIN dump: ");
517     send_length = 5;
518     memcpy(bSendBuffer, "\x00\x40\x00\x00\xFF",
519     send_length);
520     bSendBuffer[4] = bRecvBuffer[1];
521     for (i=0; i<send_length; i++)
522     printf(" %02X", bSendBuffer[i]);
523     printf("\n");
524     length = sizeof(bRecvBuffer);
525     rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length,
526     &pioRecvPci, bRecvBuffer, &length);
527     printf(" card response:");
528     for (i=0; i<length; i++)
529     printf(" %02X", bRecvBuffer[i]);
530     printf("\n");
531     PCSC_ERROR_EXIT(rv, "SCardTransmit")
532     }
533 rousseau 1676 #endif
534 rousseau 972
535 rousseau 889 /* card disconnect */
536     rv = SCardDisconnect(hCard, SCARD_UNPOWER_CARD);
537     PCSC_ERROR_CONT(rv, "SCardDisconnect")
538    
539     end:
540     /* We try to leave things as clean as possible */
541     rv = SCardReleaseContext(hContext);
542     if (rv != SCARD_S_SUCCESS)
543     printf("SCardReleaseContext: %s (0x%lX)\n", pcsc_stringify_error(rv),
544     rv);
545    
546     /* free allocated memory */
547     free(mszReaders);
548     free(readers);
549    
550     return 0;
551     } /* main */
552    

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.5