pcsc-lite  1.8.3
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 5860 2011-07-09 11:29:52Z 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->lpcDevice[0] != '\0')
126  rv = IFDHCreateChannelByName(rContext->slot, rContext->lpcDevice);
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  (void)IFDStatusICC(rContext, &dwStatus);
270 
271  if (dwStatus & SCARD_ABSENT)
272  return SCARD_W_REMOVED_CARD;
273 #ifndef PCSCLITE_STATIC_DRIVER
274  IFDH_power_icc = rContext->psFunctions.psFunctions_v2.pvfPowerICC;
275 #endif
276 
277  /* LOCK THIS CODE REGION */
278  (void)pthread_mutex_lock(rContext->mMutex);
279 
280 #ifndef PCSCLITE_STATIC_DRIVER
281  rv = (*IFDH_power_icc) (rContext->slot, dwAction, pucAtr, pdwAtrLen);
282 #else
283  rv = IFDHPowerICC(rContext->slot, dwAction, pucAtr, pdwAtrLen);
284 #endif
285 
286  /* END OF LOCKED REGION */
287  (void)pthread_mutex_unlock(rContext->mMutex);
288 
289  /* use clean values in case of error */
290  if (rv != IFD_SUCCESS)
291  {
292  *pdwAtrLen = 0;
293  pucAtr[0] = '\0';
294 
295  if (rv == IFD_NO_SUCH_DEVICE)
296  {
297  (void)SendHotplugSignal();
299  }
300 
301  return SCARD_E_NOT_TRANSACTED;
302  }
303 
304  return rv;
305 }
306 
311 LONG IFDStatusICC(READER_CONTEXT * rContext, PDWORD pdwStatus)
312 {
313  RESPONSECODE rv = IFD_SUCCESS;
314  DWORD dwCardStatus = 0;
315 
316 #ifndef PCSCLITE_STATIC_DRIVER
317  RESPONSECODE(*IFDH_icc_presence) (DWORD) = NULL;
318 
319  IFDH_icc_presence = rContext->psFunctions.psFunctions_v2.pvfICCPresence;
320 #endif
321 
322  /* LOCK THIS CODE REGION */
323  (void)pthread_mutex_lock(rContext->mMutex);
324 
325 #ifndef PCSCLITE_STATIC_DRIVER
326  rv = (*IFDH_icc_presence) (rContext->slot);
327 #else
328  rv = IFDHICCPresence(rContext->slot);
329 #endif
330 
331  /* END OF LOCKED REGION */
332  (void)pthread_mutex_unlock(rContext->mMutex);
333 
334  if (rv == IFD_SUCCESS || rv == IFD_ICC_PRESENT)
335  dwCardStatus |= SCARD_PRESENT;
336  else
337  if (rv == IFD_ICC_NOT_PRESENT)
338  dwCardStatus |= SCARD_ABSENT;
339  else
340  {
341  Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv);
342  *pdwStatus = SCARD_UNKNOWN;
343 
344  if (rv == IFD_NO_SUCH_DEVICE)
345  {
346  (void)SendHotplugSignal();
348  }
349 
350  return SCARD_E_NOT_TRANSACTED;
351  }
352 
353  *pdwStatus = dwCardStatus;
354 
355  return SCARD_S_SUCCESS;
356 }
357 
358 /*
359  * Function: IFDControl Purpose : This function provides a means for
360  * toggling a specific action on the reader such as swallow, eject,
361  * biometric.
362  */
363 
364 /*
365  * Valid only for IFDHandler version 2.0
366  */
367 
368 LONG IFDControl_v2(READER_CONTEXT * rContext, PUCHAR TxBuffer,
369  DWORD TxLength, PUCHAR RxBuffer, PDWORD RxLength)
370 {
371  RESPONSECODE rv = IFD_SUCCESS;
372 
373 #ifndef PCSCLITE_STATIC_DRIVER
374  RESPONSECODE(*IFDH_control_v2) (DWORD, PUCHAR, DWORD, /*@out@*/ PUCHAR,
375  PDWORD);
376 #endif
377 
378  if (rContext->version != IFD_HVERSION_2_0)
380 
381 #ifndef PCSCLITE_STATIC_DRIVER
382  IFDH_control_v2 = rContext->psFunctions.psFunctions_v2.pvfControl;
383 #endif
384 
385  /* LOCK THIS CODE REGION */
386  (void)pthread_mutex_lock(rContext->mMutex);
387 
388 #ifndef PCSCLITE_STATIC_DRIVER
389  rv = (*IFDH_control_v2) (rContext->slot, TxBuffer, TxLength,
390  RxBuffer, RxLength);
391 #elif defined(IFDHANDLERv2)
392  rv = IFDHControl(rContext->slot, TxBuffer, TxLength,
393  RxBuffer, RxLength);
394 #endif
395 
396  /* END OF LOCKED REGION */
397  (void)pthread_mutex_unlock(rContext->mMutex);
398 
399  if (rv == IFD_SUCCESS)
400  return SCARD_S_SUCCESS;
401  else
402  {
403  Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv);
404  LogXxd(PCSC_LOG_DEBUG, "TxBuffer ", TxBuffer, TxLength);
405  LogXxd(PCSC_LOG_DEBUG, "RxBuffer ", RxBuffer, *RxLength);
406  return SCARD_E_NOT_TRANSACTED;
407  }
408 }
409 
415 /*
416  * Valid only for IFDHandler version 3.0 and up
417  */
418 
419 LONG IFDControl(READER_CONTEXT * rContext, DWORD ControlCode,
420  LPCVOID TxBuffer, DWORD TxLength, LPVOID RxBuffer, DWORD RxLength,
421  LPDWORD BytesReturned)
422 {
423  RESPONSECODE rv = IFD_SUCCESS;
424 
425 #ifndef PCSCLITE_STATIC_DRIVER
426  RESPONSECODE(*IFDH_control) (DWORD, DWORD, LPCVOID, DWORD, LPVOID, DWORD, LPDWORD);
427 #endif
428 
429  if (rContext->version < IFD_HVERSION_3_0)
431 
432 #ifndef PCSCLITE_STATIC_DRIVER
433  IFDH_control = rContext->psFunctions.psFunctions_v3.pvfControl;
434 #endif
435 
436  /* LOCK THIS CODE REGION */
437  (void)pthread_mutex_lock(rContext->mMutex);
438 
439 #ifndef PCSCLITE_STATIC_DRIVER
440  rv = (*IFDH_control) (rContext->slot, ControlCode, TxBuffer,
441  TxLength, RxBuffer, RxLength, BytesReturned);
442 #elif defined(IFDHANDLERv3)
443  rv = IFDHControl(rContext->slot, ControlCode, TxBuffer,
444  TxLength, RxBuffer, RxLength, BytesReturned);
445 #endif
446 
447  /* END OF LOCKED REGION */
448  (void)pthread_mutex_unlock(rContext->mMutex);
449 
450  if (rv == IFD_SUCCESS)
451  return SCARD_S_SUCCESS;
452  else
453  {
454  Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv);
455  Log3(PCSC_LOG_DEBUG, "ControlCode: 0x%.8lX BytesReturned: %ld",
456  ControlCode, *BytesReturned);
457  LogXxd(PCSC_LOG_DEBUG, "TxBuffer ", TxBuffer, TxLength);
458  LogXxd(PCSC_LOG_DEBUG, "RxBuffer ", RxBuffer, *BytesReturned);
459 
460  if (rv == IFD_NO_SUCH_DEVICE)
461  {
462  (void)SendHotplugSignal();
464  }
465 
466  if ((IFD_ERROR_NOT_SUPPORTED == rv) || (IFD_NOT_SUPPORTED == rv))
468 
471 
472  return SCARD_E_NOT_TRANSACTED;
473  }
474 }
475 
479 LONG IFDTransmit(READER_CONTEXT * rContext, SCARD_IO_HEADER pioTxPci,
480  PUCHAR pucTxBuffer, DWORD dwTxLength, PUCHAR pucRxBuffer,
481  PDWORD pdwRxLength, PSCARD_IO_HEADER pioRxPci)
482 {
483  RESPONSECODE rv = IFD_SUCCESS;
484 
485 #ifndef PCSCLITE_STATIC_DRIVER
486  RESPONSECODE(*IFDH_transmit_to_icc) (DWORD, SCARD_IO_HEADER, PUCHAR,
487  DWORD, /*@out@*/ PUCHAR, PDWORD, PSCARD_IO_HEADER) = NULL;
488 #endif
489 
490  /* log the APDU */
491  DebugLogCategory(DEBUG_CATEGORY_APDU, pucTxBuffer, dwTxLength);
492 
493 #ifndef PCSCLITE_STATIC_DRIVER
494  IFDH_transmit_to_icc =
495  rContext->psFunctions.psFunctions_v2.pvfTransmitToICC;
496 #endif
497 
498  /* LOCK THIS CODE REGION */
499  (void)pthread_mutex_lock(rContext->mMutex);
500 
501 #ifndef PCSCLITE_STATIC_DRIVER
502  rv = (*IFDH_transmit_to_icc) (rContext->slot, pioTxPci, (LPBYTE)
503  pucTxBuffer, dwTxLength, pucRxBuffer, pdwRxLength, pioRxPci);
504 #else
505  rv = IFDHTransmitToICC(rContext->slot, pioTxPci,
506  (LPBYTE) pucTxBuffer, dwTxLength,
507  pucRxBuffer, pdwRxLength, pioRxPci);
508 #endif
509 
510  /* END OF LOCKED REGION */
511  (void)pthread_mutex_unlock(rContext->mMutex);
512 
513  /* log the returned status word */
514  DebugLogCategory(DEBUG_CATEGORY_SW, pucRxBuffer, *pdwRxLength);
515 
516  if (rv == IFD_SUCCESS)
517  return SCARD_S_SUCCESS;
518  else
519  {
520  Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv);
521 
522  if (rv == IFD_NO_SUCH_DEVICE)
523  {
524  (void)SendHotplugSignal();
526  }
527 
528  return SCARD_E_NOT_TRANSACTED;
529  }
530 }
531