You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

288 lines
7.7 KiB

  1. /*
  2. * Sample program to use PC/SC API.
  3. *
  4. * MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
  5. *
  6. * Copyright (C) 2003-2011
  7. * Ludovic Rousseau <ludovic.rousseau@free.fr>
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 3 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License along
  20. * with this program; if not, see <http://www.gnu.org/licenses/>.
  21. *
  22. * $Id: pcsc_demo.c 6851 2014-02-14 15:43:32Z rousseau $
  23. */
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <time.h>
  27. #include <unistd.h>
  28. #include <string.h>
  29. #include <PCSC/wintypes.h>
  30. #include <PCSC/winscard.h>
  31. #ifndef TRUE
  32. #define TRUE 1
  33. #define FALSE 0
  34. #endif
  35. /* PCSC error message pretty print */
  36. #define PCSC_ERROR(rv, text) \
  37. if (rv != SCARD_S_SUCCESS) \
  38. { \
  39. printf(text ": %s (0x%lX)\n", pcsc_stringify_error(rv), rv); \
  40. goto end; \
  41. } \
  42. else \
  43. { \
  44. printf(text ": OK\n\n"); \
  45. }
  46. int main(int argc, char *argv[])
  47. {
  48. LONG rv;
  49. SCARDCONTEXT hContext;
  50. DWORD dwReaders;
  51. LPSTR mszReaders = NULL;
  52. char *ptr, **readers = NULL;
  53. int nbReaders;
  54. SCARDHANDLE hCard;
  55. DWORD dwActiveProtocol, dwReaderLen, dwState, dwProt, dwAtrLen;
  56. BYTE pbAtr[MAX_ATR_SIZE] = "";
  57. char pbReader[MAX_READERNAME] = "";
  58. int reader_nb;
  59. unsigned int i;
  60. const SCARD_IO_REQUEST *pioSendPci;
  61. SCARD_IO_REQUEST pioRecvPci;
  62. BYTE pbRecvBuffer[10];
  63. BYTE pbSendBuffer[] = { 0x00, 0xA4, 0x00, 0x00, 0x02, 0x3F, 0x00 };
  64. DWORD dwSendLength, dwRecvLength;
  65. printf("PC/SC sample code\n");
  66. printf("V 1.4 2003-2009, Ludovic Rousseau <ludovic.rousseau@free.fr>\n");
  67. printf("\nTHIS PROGRAM IS NOT DESIGNED AS A TESTING TOOL FOR END USERS!\n");
  68. printf("Do NOT use it unless you really know what you do.\n\n");
  69. rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
  70. if (rv != SCARD_S_SUCCESS)
  71. {
  72. printf("SCardEstablishContext: Cannot Connect to Resource Manager %lX\n", rv);
  73. return EXIT_FAILURE;
  74. }
  75. /* Retrieve the available readers list. */
  76. dwReaders = SCARD_AUTOALLOCATE;
  77. rv = SCardListReaders(hContext, NULL, (LPSTR)&mszReaders, &dwReaders);
  78. PCSC_ERROR(rv, "SCardListReaders")
  79. /* Extract readers from the null separated string and get the total
  80. * number of readers */
  81. nbReaders = 0;
  82. ptr = mszReaders;
  83. while (*ptr != '\0')
  84. {
  85. ptr += strlen(ptr)+1;
  86. nbReaders++;
  87. }
  88. if (nbReaders == 0)
  89. {
  90. printf("No reader found\n");
  91. goto end;
  92. }
  93. /* allocate the readers table */
  94. readers = calloc(nbReaders, sizeof(char *));
  95. if (NULL == readers)
  96. {
  97. printf("Not enough memory for readers[]\n");
  98. goto end;
  99. }
  100. /* fill the readers table */
  101. nbReaders = 0;
  102. ptr = mszReaders;
  103. while (*ptr != '\0')
  104. {
  105. printf("%d: %s\n", nbReaders, ptr);
  106. readers[nbReaders] = ptr;
  107. ptr += strlen(ptr)+1;
  108. nbReaders++;
  109. }
  110. if (argc > 1)
  111. {
  112. reader_nb = atoi(argv[1]);
  113. if (reader_nb < 0 || reader_nb >= nbReaders)
  114. {
  115. printf("Wrong reader index: %d\n", reader_nb);
  116. goto end;
  117. }
  118. }
  119. else
  120. reader_nb = 0;
  121. /* connect to a card */
  122. dwActiveProtocol = -1;
  123. rv = SCardConnect(hContext, readers[reader_nb], SCARD_SHARE_SHARED,
  124. SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol);
  125. printf(" Protocol: %ld\n", dwActiveProtocol);
  126. PCSC_ERROR(rv, "SCardConnect")
  127. /* get card status */
  128. dwAtrLen = sizeof(pbAtr);
  129. dwReaderLen = sizeof(pbReader);
  130. rv = SCardStatus(hCard, /*NULL*/ pbReader, &dwReaderLen, &dwState, &dwProt,
  131. pbAtr, &dwAtrLen);
  132. printf(" Reader: %s (length %ld bytes)\n", pbReader, dwReaderLen);
  133. printf(" State: 0x%lX\n", dwState);
  134. printf(" Prot: %ld\n", dwProt);
  135. printf(" ATR (length %ld bytes):", dwAtrLen);
  136. for (i=0; i<dwAtrLen; i++)
  137. printf(" %02X", pbAtr[i]);
  138. printf("\n");
  139. PCSC_ERROR(rv, "SCardStatus")
  140. switch(dwActiveProtocol)
  141. {
  142. case SCARD_PROTOCOL_T0:
  143. pioSendPci = SCARD_PCI_T0;
  144. break;
  145. case SCARD_PROTOCOL_T1:
  146. pioSendPci = SCARD_PCI_T1;
  147. break;
  148. default:
  149. printf("Unknown protocol\n");
  150. goto end;
  151. }
  152. /* exchange APDU */
  153. dwSendLength = sizeof(pbSendBuffer);
  154. dwRecvLength = sizeof(pbRecvBuffer);
  155. printf("Sending: ");
  156. for (i=0; i<dwSendLength; i++)
  157. printf("%02X ", pbSendBuffer[i]);
  158. printf("\n");
  159. rv = SCardTransmit(hCard, pioSendPci, pbSendBuffer, dwSendLength,
  160. &pioRecvPci, pbRecvBuffer, &dwRecvLength);
  161. printf("Received: ");
  162. for (i=0; i<dwRecvLength; i++)
  163. printf("%02X ", pbRecvBuffer[i]);
  164. printf("\n");
  165. PCSC_ERROR(rv, "SCardTransmit")
  166. /* card disconnect */
  167. rv = SCardDisconnect(hCard, SCARD_LEAVE_CARD);
  168. PCSC_ERROR(rv, "SCardDisconnect")
  169. /* connect to a card */
  170. dwActiveProtocol = -1;
  171. rv = SCardConnect(hContext, readers[reader_nb], SCARD_SHARE_SHARED,
  172. SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol);
  173. printf(" Protocol: %ld\n", dwActiveProtocol);
  174. PCSC_ERROR(rv, "SCardConnect")
  175. /* exchange APDU */
  176. dwSendLength = sizeof(pbSendBuffer);
  177. dwRecvLength = sizeof(pbRecvBuffer);
  178. printf("Sending: ");
  179. for (i=0; i<dwSendLength; i++)
  180. printf("%02X ", pbSendBuffer[i]);
  181. printf("\n");
  182. rv = SCardTransmit(hCard, pioSendPci, pbSendBuffer, dwSendLength,
  183. &pioRecvPci, pbRecvBuffer, &dwRecvLength);
  184. printf("Received: ");
  185. for (i=0; i<dwRecvLength; i++)
  186. printf("%02X ", pbRecvBuffer[i]);
  187. printf("\n");
  188. PCSC_ERROR(rv, "SCardTransmit")
  189. /* card reconnect */
  190. rv = SCardReconnect(hCard, SCARD_SHARE_SHARED,
  191. SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, SCARD_LEAVE_CARD,
  192. &dwActiveProtocol);
  193. PCSC_ERROR(rv, "SCardReconnect")
  194. /* get card status */
  195. dwAtrLen = sizeof(pbAtr);
  196. dwReaderLen = sizeof(pbReader);
  197. rv = SCardStatus(hCard, /*NULL*/ pbReader, &dwReaderLen, &dwState, &dwProt,
  198. pbAtr, &dwAtrLen);
  199. printf(" Reader: %s (length %ld bytes)\n", pbReader, dwReaderLen);
  200. printf(" State: 0x%lX\n", dwState);
  201. printf(" Prot: %ld\n", dwProt);
  202. printf(" ATR (length %ld bytes):", dwAtrLen);
  203. for (i=0; i<dwAtrLen; i++)
  204. printf(" %02X", pbAtr[i]);
  205. printf("\n");
  206. PCSC_ERROR(rv, "SCardStatus")
  207. /* get card status change */
  208. {
  209. /* check only one reader */
  210. SCARD_READERSTATE rgReaderStates[1];
  211. rgReaderStates[0].szReader = pbReader;
  212. rgReaderStates[0].dwCurrentState = SCARD_STATE_UNAWARE;
  213. rv = SCardGetStatusChange(hContext, 0, rgReaderStates, 1);
  214. printf(" state: 0x%04lX\n", rgReaderStates[0].dwEventState);
  215. PCSC_ERROR(rv, "SCardGetStatusChange")
  216. }
  217. /* begin transaction */
  218. rv = SCardBeginTransaction(hCard);
  219. PCSC_ERROR(rv, "SCardBeginTransaction")
  220. /* exchange APDU */
  221. dwSendLength = sizeof(pbSendBuffer);
  222. dwRecvLength = sizeof(pbRecvBuffer);
  223. printf("Sending: ");
  224. for (i=0; i<dwSendLength; i++)
  225. printf("%02X ", pbSendBuffer[i]);
  226. printf("\n");
  227. rv = SCardTransmit(hCard, pioSendPci, pbSendBuffer, dwSendLength,
  228. &pioRecvPci, pbRecvBuffer, &dwRecvLength);
  229. printf("Received: ");
  230. for (i=0; i<dwRecvLength; i++)
  231. printf("%02X ", pbRecvBuffer[i]);
  232. printf("\n");
  233. PCSC_ERROR(rv, "SCardTransmit")
  234. /* end transaction */
  235. rv = SCardEndTransaction(hCard, SCARD_LEAVE_CARD);
  236. PCSC_ERROR(rv, "SCardEndTransaction")
  237. /* card disconnect */
  238. rv = SCardDisconnect(hCard, SCARD_UNPOWER_CARD);
  239. PCSC_ERROR(rv, "SCardDisconnect")
  240. end:
  241. /* free allocated memory */
  242. if (mszReaders)
  243. SCardFreeMemory(hContext, mszReaders);
  244. /* We try to leave things as clean as possible */
  245. rv = SCardReleaseContext(hContext);
  246. if (rv != SCARD_S_SUCCESS)
  247. printf("SCardReleaseContext: %s (0x%lX)\n", pcsc_stringify_error(rv),
  248. rv);
  249. if (readers)
  250. free(readers);
  251. return EXIT_SUCCESS;
  252. } /* main */