pcsc-lite  1.8.6
ifdwrapper.c
Go to the documentation of this file.
1 /*
2  * MUSCLE SmartCard Development ( http://www.linuxnet.com )
3  *
4  * Copyright (C) 1999-2004
5  * David Corcoran <corcoran@linuxnet.com>
6  * Copyright (C) 2003-2004
7  * Damien Sauveron <damien.sauveron@labri.fr>
8  * Copyright (C) 2002-2011
9  * Ludovic Rousseau <ludovic.rousseau@free.fr>
10  *
11  * $Id: ifdwrapper.c 6315 2012-06-02 13:08:05Z rousseau $
12  */
13 
19 #include <errno.h>
20 #include <unistd.h>
21 #include <pthread.h>
22 
23 #include "config.h"
24 #include "misc.h"
25 #include "pcscd.h"
26 #include "debuglog.h"
27 #include "readerfactory.h"
28 #include "ifdwrapper.h"
29 #include "atrhandler.h"
30 #include "dyn_generic.h"
31 #include "sys_generic.h"
32 #include "utils.h"
33 
34 #ifdef PCSCLITE_STATIC_DRIVER
35 /* check that either IFDHANDLERv2 or IFDHANDLERv3 is
36  * defined */
37  #if ! (defined(IFDHANDLERv2) || defined(IFDHANDLERv3))
38  #error IFDHANDLER version not defined
39  #endif
40 #endif
41 
46 LONG IFDSetPTS(READER_CONTEXT * rContext, DWORD dwProtocol, UCHAR ucFlags,
47  UCHAR ucPTS1, UCHAR ucPTS2, UCHAR ucPTS3)
48 {
49  RESPONSECODE rv = IFD_SUCCESS;
50 
51 #ifndef PCSCLITE_STATIC_DRIVER
52  RESPONSECODE(*IFDH_set_protocol_parameters) (DWORD, DWORD, UCHAR,
53  UCHAR, UCHAR, UCHAR) = NULL;
54 
55  IFDH_set_protocol_parameters = (RESPONSECODE(*)(DWORD, DWORD, UCHAR,
56  UCHAR, UCHAR, UCHAR))
57  rContext->psFunctions.psFunctions_v2.pvfSetProtocolParameters;
58 
59  if (NULL == IFDH_set_protocol_parameters)
61 #endif
62 
63  /*
64  * Locking is done in winscard.c SCardConnect() and SCardReconnect()
65  *
66  * This avoids to renegotiate the protocol and confuse the card
67  * Error returned by CCID driver is: CCID_Receive Procedure byte conflict
68  */
69 
70 #ifndef PCSCLITE_STATIC_DRIVER
71  rv = (*IFDH_set_protocol_parameters) (rContext->slot,
72  dwProtocol, ucFlags, ucPTS1, ucPTS2, ucPTS3);
73 #else
74  rv = IFDHSetProtocolParameters(rContext->slot, dwProtocol, ucFlags,
75  ucPTS1, ucPTS2, ucPTS3);
76 #endif
77 
78  return rv;
79 }
80 
84 LONG IFDOpenIFD(READER_CONTEXT * rContext)
85 {
86  RESPONSECODE rv = 0;
87 
88 #ifndef PCSCLITE_STATIC_DRIVER
89  RESPONSECODE(*IFDH_create_channel) (DWORD, DWORD) = NULL;
90  RESPONSECODE(*IFDH_create_channel_by_name) (DWORD, LPSTR) = NULL;
91 
92  if (rContext->version == IFD_HVERSION_2_0)
93  IFDH_create_channel =
94  rContext->psFunctions.psFunctions_v2.pvfCreateChannel;
95  else
96  {
97  IFDH_create_channel =
98  rContext->psFunctions.psFunctions_v3.pvfCreateChannel;
99  IFDH_create_channel_by_name =
100  rContext->psFunctions.psFunctions_v3.pvfCreateChannelByName;
101  }
102 #endif
103 
104  /* LOCK THIS CODE REGION */
105  (void)pthread_mutex_lock(rContext->mMutex);
106 
107 #ifndef PCSCLITE_STATIC_DRIVER
108  if (rContext->version == IFD_HVERSION_2_0)
109  {
110  rv = (*IFDH_create_channel) (rContext->slot, rContext->port);
111  } else
112  {
113  /* use device name only if defined */
114  if (rContext->device[0] != '\0')
115  rv = (*IFDH_create_channel_by_name) (rContext->slot, rContext->device);
116  else
117  rv = (*IFDH_create_channel) (rContext->slot, rContext->port);
118  }
119 #else
120 #if defined(IFDHANDLERv2)
121  rv = IFDHCreateChannel(rContext->slot, rContext->port);
122 #else
123  {
124  /* Use device name only if defined */
125  if (rContext->device[0] != '\0')
126  rv = IFDHCreateChannelByName(rContext->slot, rContext->device);
127  else
128  rv = IFDHCreateChannel(rContext->slot, rContext->port);
129  }
130 #endif
131 #endif
132 
133  /* END OF LOCKED REGION */
134  (void)pthread_mutex_unlock(rContext->mMutex);
135 
136  return rv;
137 }
138 
142 LONG IFDCloseIFD(READER_CONTEXT * rContext)
143 {
144  RESPONSECODE rv = IFD_SUCCESS;
145  int repeat;
146 
147 #ifndef PCSCLITE_STATIC_DRIVER
148  RESPONSECODE(*IFDH_close_channel) (DWORD) = NULL;
149 
150  IFDH_close_channel = rContext->psFunctions.psFunctions_v2.pvfCloseChannel;
151 #endif
152 
153  /* TRY TO LOCK THIS CODE REGION */
154  repeat = 5;
155 again:
156  rv = pthread_mutex_trylock(rContext->mMutex);
157  if (EBUSY == rv)
158  {
159  Log1(PCSC_LOG_ERROR, "Locking failed");
160  repeat--;
161  if (repeat)
162  {
163  (void)SYS_USleep(100*1000); /* 100 ms */
164  goto again;
165  }
166  }
167 
168 #ifndef PCSCLITE_STATIC_DRIVER
169  rv = (*IFDH_close_channel) (rContext->slot);
170 #else
171  rv = IFDHCloseChannel(rContext->slot);
172 #endif
173 
174  /* END OF LOCKED REGION */
175  (void)pthread_mutex_unlock(rContext->mMutex);
176 
177  return rv;
178 }
179 
183 LONG IFDSetCapabilities(READER_CONTEXT * rContext, DWORD dwTag,
184  DWORD dwLength, PUCHAR pucValue)
185 {
186  RESPONSECODE rv = IFD_SUCCESS;
187 
188 #ifndef PCSCLITE_STATIC_DRIVER
189  RESPONSECODE(*IFDH_set_capabilities) (DWORD, DWORD, DWORD, PUCHAR) = NULL;
190 
191  IFDH_set_capabilities = rContext->psFunctions.psFunctions_v2.pvfSetCapabilities;
192 #endif
193 
194  /*
195  * Let the calling function lock this otherwise a deadlock will
196  * result
197  */
198 
199 #ifndef PCSCLITE_STATIC_DRIVER
200  rv = (*IFDH_set_capabilities) (rContext->slot, dwTag,
201  dwLength, pucValue);
202 #else
203  rv = IFDHSetCapabilities(rContext->slot, dwTag, dwLength, pucValue);
204 #endif
205 
206  return rv;
207 }
208 
214 LONG IFDGetCapabilities(READER_CONTEXT * rContext, DWORD dwTag,
215  PDWORD pdwLength, PUCHAR pucValue)
216 {
217  RESPONSECODE rv = IFD_SUCCESS;
218 
219 #ifndef PCSCLITE_STATIC_DRIVER
220  RESPONSECODE(*IFDH_get_capabilities) (DWORD, DWORD, PDWORD, /*@out@*/ PUCHAR) = NULL;
221 
222  IFDH_get_capabilities =
223  rContext->psFunctions.psFunctions_v2.pvfGetCapabilities;
224 #endif
225 
226  /* LOCK THIS CODE REGION */
227  (void)pthread_mutex_lock(rContext->mMutex);
228 
229 #ifndef PCSCLITE_STATIC_DRIVER
230  rv = (*IFDH_get_capabilities) (rContext->slot, dwTag, pdwLength, pucValue);
231 #else
232  rv = IFDHGetCapabilities(rContext->slot, dwTag, pdwLength, pucValue);
233 #endif
234 
235  /* END OF LOCKED REGION */
236  (void)pthread_mutex_unlock(rContext->mMutex);
237 
238  return rv;
239 }
240 
244 LONG IFDPowerICC(READER_CONTEXT * rContext, DWORD dwAction,
245  PUCHAR pucAtr, PDWORD pdwAtrLen)
246 {
247  RESPONSECODE rv;
248  DWORD dwStatus;
249  UCHAR dummyAtr[MAX_ATR_SIZE];
250  DWORD dummyAtrLen = sizeof(dummyAtr);
251 
252 #ifndef PCSCLITE_STATIC_DRIVER
253  RESPONSECODE(*IFDH_power_icc) (DWORD, DWORD, PUCHAR, PDWORD) = NULL;
254 #endif
255 
256  /*
257  * Zero out everything
258  */
259  dwStatus = 0;
260 
261  if (NULL == pucAtr)
262  pucAtr = dummyAtr;
263  if (NULL == pdwAtrLen)
264  pdwAtrLen = &dummyAtrLen;
265 
266  /*
267  * Check that the card is inserted first
268  */
269  rv = IFDStatusICC(rContext, &dwStatus);
270  if (rv != IFD_SUCCESS)
271  {
272  if (rv == IFD_NO_SUCH_DEVICE)
274 
275  return SCARD_E_NOT_TRANSACTED;
276  }
277 
278  if (dwStatus & SCARD_ABSENT)
279  return SCARD_W_REMOVED_CARD;
280 #ifndef PCSCLITE_STATIC_DRIVER
281  IFDH_power_icc = rContext->psFunctions.psFunctions_v2.pvfPowerICC;
282 #endif
283 
284  /* LOCK THIS CODE REGION */
285  (void)pthread_mutex_lock(rContext->mMutex);
286 
287 #ifndef PCSCLITE_STATIC_DRIVER
288  rv = (*IFDH_power_icc) (rContext->slot, dwAction, pucAtr, pdwAtrLen);
289 #else
290  rv = IFDHPowerICC(rContext->slot, dwAction, pucAtr, pdwAtrLen);
291 #endif
292 
293  /* END OF LOCKED REGION */
294  (void)pthread_mutex_unlock(rContext->mMutex);
295 
296  /* use clean values in case of error */
297  if (rv != IFD_SUCCESS)
298  {
299  *pdwAtrLen = 0;
300  pucAtr[0] = '\0';
301 
302  if (rv == IFD_NO_SUCH_DEVICE)
303  {
304  (void)SendHotplugSignal();
306  }
307 
308  return SCARD_E_NOT_TRANSACTED;
309  }
310 
311  return rv;
312 }
313 
318 LONG IFDStatusICC(READER_CONTEXT * rContext, PDWORD pdwStatus)
319 {
320  RESPONSECODE rv = IFD_SUCCESS;
321  DWORD dwCardStatus = 0;
322 
323 #ifndef PCSCLITE_STATIC_DRIVER
324  RESPONSECODE(*IFDH_icc_presence) (DWORD) = NULL;
325 
326  IFDH_icc_presence = rContext->psFunctions.psFunctions_v2.pvfICCPresence;
327 #endif
328 
329  /* LOCK THIS CODE REGION */
330  (void)pthread_mutex_lock(rContext->mMutex);
331 
332 #ifndef PCSCLITE_STATIC_DRIVER
333  rv = (*IFDH_icc_presence) (rContext->slot);
334 #else
335  rv = IFDHICCPresence(rContext->slot);
336 #endif
337 
338  /* END OF LOCKED REGION */
339  (void)pthread_mutex_unlock(rContext->mMutex);
340 
341  if (rv == IFD_SUCCESS || rv == IFD_ICC_PRESENT)
342  dwCardStatus |= SCARD_PRESENT;
343  else
344  if (rv == IFD_ICC_NOT_PRESENT)
345  dwCardStatus |= SCARD_ABSENT;
346  else
347  {
348  Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv);
349  *pdwStatus = SCARD_UNKNOWN;
350 
351  if (rv == IFD_NO_SUCH_DEVICE)
352  {
353  (void)SendHotplugSignal();
355  }
356 
357  return SCARD_E_NOT_TRANSACTED;
358  }
359 
360  *pdwStatus = dwCardStatus;
361 
362  return SCARD_S_SUCCESS;
363 }
364 
365 /*
366  * Function: IFDControl Purpose : This function provides a means for
367  * toggling a specific action on the reader such as swallow, eject,
368  * biometric.
369  */
370 
371 /*
372  * Valid only for IFDHandler version 2.0
373  */
374 
375 LONG IFDControl_v2(READER_CONTEXT * rContext, PUCHAR TxBuffer,
376  DWORD TxLength, PUCHAR RxBuffer, PDWORD RxLength)
377 {
378  RESPONSECODE rv = IFD_SUCCESS;
379 
380 #ifndef PCSCLITE_STATIC_DRIVER
381  RESPONSECODE(*IFDH_control_v2) (DWORD, PUCHAR, DWORD, /*@out@*/ PUCHAR,
382  PDWORD);
383 #endif
384 
385  if (rContext->version != IFD_HVERSION_2_0)
387 
388 #ifndef PCSCLITE_STATIC_DRIVER
389  IFDH_control_v2 = rContext->psFunctions.psFunctions_v2.pvfControl;
390 #endif
391 
392  /* LOCK THIS CODE REGION */
393  (void)pthread_mutex_lock(rContext->mMutex);
394 
395 #ifndef PCSCLITE_STATIC_DRIVER
396  rv = (*IFDH_control_v2) (rContext->slot, TxBuffer, TxLength,
397  RxBuffer, RxLength);
398 #elif defined(IFDHANDLERv2)
399  rv = IFDHControl(rContext->slot, TxBuffer, TxLength,
400  RxBuffer, RxLength);
401 #endif
402 
403  /* END OF LOCKED REGION */
404  (void)pthread_mutex_unlock(rContext->mMutex);
405 
406  if (rv == IFD_SUCCESS)
407  return SCARD_S_SUCCESS;
408  else
409  {
410  Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv);
411  LogXxd(PCSC_LOG_DEBUG, "TxBuffer ", TxBuffer, TxLength);
412  LogXxd(PCSC_LOG_DEBUG, "RxBuffer ", RxBuffer, *RxLength);
413  return SCARD_E_NOT_TRANSACTED;
414  }
415 }
416 
422 /*
423  * Valid only for IFDHandler version 3.0 and up
424  */
425 
426 LONG IFDControl(READER_CONTEXT * rContext, DWORD ControlCode,
427  LPCVOID TxBuffer, DWORD TxLength, LPVOID RxBuffer, DWORD RxLength,
428  LPDWORD BytesReturned)
429 {
430  RESPONSECODE rv = IFD_SUCCESS;
431 
432 #ifndef PCSCLITE_STATIC_DRIVER
433  RESPONSECODE(*IFDH_control) (DWORD, DWORD, LPCVOID, DWORD, LPVOID, DWORD, LPDWORD);
434 #endif
435 
436  if (rContext->version < IFD_HVERSION_3_0)
438 
439 #ifndef PCSCLITE_STATIC_DRIVER
440  IFDH_control = rContext->psFunctions.psFunctions_v3.pvfControl;
441 #endif
442 
443  /* LOCK THIS CODE REGION */
444  (void)pthread_mutex_lock(rContext->mMutex);
445 
446 #ifndef PCSCLITE_STATIC_DRIVER
447  rv = (*IFDH_control) (rContext->slot, ControlCode, TxBuffer,
448  TxLength, RxBuffer, RxLength, BytesReturned);
449 #elif defined(IFDHANDLERv3)
450  rv = IFDHControl(rContext->slot, ControlCode, TxBuffer,
451  TxLength, RxBuffer, RxLength, BytesReturned);
452 #endif
453 
454  /* END OF LOCKED REGION */
455  (void)pthread_mutex_unlock(rContext->mMutex);
456 
457  if (rv == IFD_SUCCESS)
458  return SCARD_S_SUCCESS;
459  else
460  {
461  Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv);
462  Log3(PCSC_LOG_DEBUG, "ControlCode: 0x%.8lX BytesReturned: %ld",
463  ControlCode, *BytesReturned);
464  LogXxd(PCSC_LOG_DEBUG, "TxBuffer ", TxBuffer, TxLength);
465  LogXxd(PCSC_LOG_DEBUG, "RxBuffer ", RxBuffer, *BytesReturned);
466 
467  if (rv == IFD_NO_SUCH_DEVICE)
468  {
469  (void)SendHotplugSignal();
471  }
472 
473  if ((IFD_ERROR_NOT_SUPPORTED == rv) || (IFD_NOT_SUPPORTED == rv))
475 
478 
479  return SCARD_E_NOT_TRANSACTED;
480  }
481 }
482 
486 LONG IFDTransmit(READER_CONTEXT * rContext, SCARD_IO_HEADER pioTxPci,
487  PUCHAR pucTxBuffer, DWORD dwTxLength, PUCHAR pucRxBuffer,
488  PDWORD pdwRxLength, PSCARD_IO_HEADER pioRxPci)
489 {
490  RESPONSECODE rv = IFD_SUCCESS;
491 
492 #ifndef PCSCLITE_STATIC_DRIVER
493  RESPONSECODE(*IFDH_transmit_to_icc) (DWORD, SCARD_IO_HEADER, PUCHAR,
494  DWORD, /*@out@*/ PUCHAR, PDWORD, PSCARD_IO_HEADER) = NULL;
495 #endif
496 
497  /* log the APDU */
498  DebugLogCategory(DEBUG_CATEGORY_APDU, pucTxBuffer, dwTxLength);
499 
500 #ifndef PCSCLITE_STATIC_DRIVER
501  IFDH_transmit_to_icc =
502  rContext->psFunctions.psFunctions_v2.pvfTransmitToICC;
503 #endif
504 
505  /* LOCK THIS CODE REGION */
506  (void)pthread_mutex_lock(rContext->mMutex);
507 
508 #ifndef PCSCLITE_STATIC_DRIVER
509  rv = (*IFDH_transmit_to_icc) (rContext->slot, pioTxPci, (LPBYTE)
510  pucTxBuffer, dwTxLength, pucRxBuffer, pdwRxLength, pioRxPci);
511 #else
512  rv = IFDHTransmitToICC(rContext->slot, pioTxPci,
513  (LPBYTE) pucTxBuffer, dwTxLength,
514  pucRxBuffer, pdwRxLength, pioRxPci);
515 #endif
516 
517  /* END OF LOCKED REGION */
518  (void)pthread_mutex_unlock(rContext->mMutex);
519 
520  /* log the returned status word */
521  DebugLogCategory(DEBUG_CATEGORY_SW, pucRxBuffer, *pdwRxLength);
522 
523  if (rv == IFD_SUCCESS)
524  return SCARD_S_SUCCESS;
525  else
526  {
527  Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv);
528 
529  if (rv == IFD_NO_SUCH_DEVICE)
530  {
531  (void)SendHotplugSignal();
533  }
534 
535  return SCARD_E_NOT_TRANSACTED;
536  }
537 }
538