2
* This keeps track of card insertion/removal events
3
* and updates ATR, protocol, and status information.
5
* MUSCLE SmartCard Development ( http://www.linuxnet.com )
8
* David Corcoran <corcoran@linuxnet.com>
10
* Ludovic Rousseau <ludovic.rousseau@free.fr>
12
* $Id: eventhandler.c,v 1.31 2005/02/22 14:40:26 rousseau Exp $
16
#include <sys/types.h>
24
#include "ifdhandler.h"
26
#include "thread_generic.h"
27
#include "readerfactory.h"
28
#include "eventhandler.h"
29
#include "dyn_generic.h"
30
#include "sys_generic.h"
31
#include "ifdwrapper.h"
32
#include "prothandler.h"
33
#include "strlcpycat.h"
35
static PREADER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS];
37
void EHStatusHandlerThread(PREADER_CONTEXT);
39
LONG EHInitializeEventStructures(void)
47
SYS_RemoveFile(PCSCLITE_PUBSHM_FILE);
49
fd = SYS_OpenFile(PCSCLITE_PUBSHM_FILE, O_RDWR | O_CREAT, 00644);
52
Log3(PCSC_LOG_CRITICAL, "Cannot create public shared file %s: %s",
53
PCSCLITE_PUBSHM_FILE, strerror(errno));
57
SYS_Chmod(PCSCLITE_PUBSHM_FILE,
58
S_IRGRP | S_IREAD | S_IWRITE | S_IROTH);
60
pageSize = SYS_GetPageSize();
63
* Jump to end of file space and allocate zero's
65
SYS_SeekFile(fd, pageSize * PCSCLITE_MAX_READERS_CONTEXTS);
66
SYS_WriteFile(fd, "", 1);
69
* Allocate each reader structure
71
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
73
readerStates[i] = (PREADER_STATE)
74
SYS_MemoryMap(sizeof(READER_STATE), fd, (i * pageSize));
75
if (readerStates[i] == 0)
77
Log3(PCSC_LOG_CRITICAL, "Cannot memory map public shared file %s: %s",
78
PCSCLITE_PUBSHM_FILE, strerror(errno));
83
* Zero out each value in the struct
85
memset((readerStates[i])->readerName, 0, MAX_READERNAME);
86
memset((readerStates[i])->cardAtr, 0, MAX_ATR_SIZE);
87
(readerStates[i])->readerID = 0;
88
(readerStates[i])->readerState = 0;
89
(readerStates[i])->lockState = 0;
90
(readerStates[i])->readerSharing = 0;
91
(readerStates[i])->cardAtrLength = 0;
92
(readerStates[i])->cardProtocol = SCARD_PROTOCOL_UNSET;
95
return SCARD_S_SUCCESS;
98
LONG EHDestroyEventHandler(PREADER_CONTEXT rContext)
100
if (NULL == rContext->readerState)
102
Log1(PCSC_LOG_ERROR, "Thread never started (reader init failed?)");
103
return SCARD_S_SUCCESS;
106
if ('\0' == rContext->readerState->readerName[0])
108
Log1(PCSC_LOG_INFO, "Thread already stomped.");
109
return SCARD_S_SUCCESS;
113
* Set the thread to 0 to exit thread
115
rContext->dwLockId = 0xFFFF;
117
Log1(PCSC_LOG_INFO, "Stomping thread.");
122
* Wait 0.05 seconds for the child to respond
126
while (rContext->dwLockId == 0xFFFF);
128
* Zero out the public status struct to allow it to be recycled and
132
memset(rContext->readerState->readerName, 0,
133
sizeof(rContext->readerState->readerName));
134
memset(rContext->readerState->cardAtr, 0,
135
sizeof(rContext->readerState->cardAtr));
136
rContext->readerState->readerID = 0;
137
rContext->readerState->readerState = 0;
138
rContext->readerState->lockState = 0;
139
rContext->readerState->readerSharing = 0;
140
rContext->readerState->cardAtrLength = 0;
141
rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNSET;
143
/* Zero the thread */
144
rContext->pthThread = 0;
146
Log1(PCSC_LOG_INFO, "Thread stomped.");
148
return SCARD_S_SUCCESS;
151
LONG EHSpawnEventHandler(PREADER_CONTEXT rContext)
156
UCHAR ucAtr[MAX_ATR_SIZE];
159
rv = IFDStatusICC(rContext, &dwStatus, ucAtr, &dwAtrLen);
160
if (rv != SCARD_S_SUCCESS)
162
Log2(PCSC_LOG_ERROR, "Initial Check Failed on %s", rContext->lpcReader);
163
return SCARD_F_UNKNOWN_ERROR;
167
* Find an empty reader slot and insert the new reader
169
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
171
if ((readerStates[i])->readerID == 0)
175
if (i == PCSCLITE_MAX_READERS_CONTEXTS)
176
return SCARD_F_INTERNAL_ERROR;
179
* Set all the attributes to this reader
181
rContext->readerState = readerStates[i];
182
strlcpy(rContext->readerState->readerName, rContext->lpcReader,
183
sizeof(rContext->readerState->readerName));
184
memcpy(rContext->readerState->cardAtr, ucAtr, dwAtrLen);
185
rContext->readerState->readerID = i + 100;
186
rContext->readerState->readerState = dwStatus;
187
rContext->readerState->readerSharing = rContext->dwContexts;
188
rContext->readerState->cardAtrLength = dwAtrLen;
189
rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNSET;
191
rv = SYS_ThreadCreate(&rContext->pthThread, THREAD_ATTR_DETACHED,
192
(PCSCLITE_THREAD_FUNCTION( ))EHStatusHandlerThread, (LPVOID) rContext);
194
return SCARD_S_SUCCESS;
196
return SCARD_E_NO_MEMORY;
199
void EHStatusHandlerThread(PREADER_CONTEXT rContext)
203
DWORD dwStatus, dwReaderSharing;
204
DWORD dwCurrentState;
208
* Zero out everything
214
lpcReader = rContext->lpcReader;
216
pageSize = SYS_GetPageSize();
218
rv = IFDStatusICC(rContext, &dwStatus, rContext->readerState->cardAtr,
219
&rContext->readerState->cardAtrLength);
220
if (dwStatus & SCARD_PRESENT)
222
rv = IFDPowerICC(rContext, IFD_POWER_UP,
223
rContext->readerState->cardAtr,
224
&rContext->readerState->cardAtrLength);
226
/* the protocol is unset after a power on */
227
rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNSET;
229
if (rv == IFD_SUCCESS)
231
dwStatus |= SCARD_PRESENT;
232
dwStatus &= ~SCARD_ABSENT;
233
dwStatus |= SCARD_POWERED;
234
dwStatus |= SCARD_NEGOTIABLE;
235
dwStatus &= ~SCARD_SPECIFIC;
236
dwStatus &= ~SCARD_SWALLOWED;
237
dwStatus &= ~SCARD_UNKNOWN;
239
if (rContext->readerState->cardAtrLength > 0)
241
LogXxd(PCSC_LOG_INFO, "Card ATR: ",
242
rContext->readerState->cardAtr,
243
rContext->readerState->cardAtrLength);
246
Log1(PCSC_LOG_INFO, "Card ATR: (NULL)");
250
dwStatus |= SCARD_PRESENT;
251
dwStatus &= ~SCARD_ABSENT;
252
dwStatus |= SCARD_SWALLOWED;
253
dwStatus &= ~SCARD_POWERED;
254
dwStatus &= ~SCARD_NEGOTIABLE;
255
dwStatus &= ~SCARD_SPECIFIC;
256
dwStatus &= ~SCARD_UNKNOWN;
257
Log1(PCSC_LOG_ERROR, "Error powering up card.");
260
dwCurrentState = SCARD_PRESENT;
264
dwStatus |= SCARD_ABSENT;
265
dwStatus &= ~SCARD_PRESENT;
266
dwStatus &= ~SCARD_POWERED;
267
dwStatus &= ~SCARD_NEGOTIABLE;
268
dwStatus &= ~SCARD_SPECIFIC;
269
dwStatus &= ~SCARD_SWALLOWED;
270
dwStatus &= ~SCARD_UNKNOWN;
271
rContext->readerState->cardAtrLength = 0;
272
rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNSET;
274
dwCurrentState = SCARD_ABSENT;
278
* Set all the public attributes to this reader
280
rContext->readerState->readerState = dwStatus;
281
rContext->readerState->readerSharing = dwReaderSharing =
282
rContext->dwContexts;
284
SYS_MMapSynchronize((void *) rContext->readerState, pageSize);
290
rv = IFDStatusICC(rContext, &dwStatus,
291
rContext->readerState->cardAtr,
292
&rContext->readerState->cardAtrLength);
294
if (rv != SCARD_S_SUCCESS)
296
Log2(PCSC_LOG_ERROR, "Error communicating to: %s", lpcReader);
299
* Set error status on this reader while errors occur
302
rContext->readerState->readerState &= ~SCARD_ABSENT;
303
rContext->readerState->readerState &= ~SCARD_PRESENT;
304
rContext->readerState->readerState &= ~SCARD_POWERED;
305
rContext->readerState->readerState &= ~SCARD_NEGOTIABLE;
306
rContext->readerState->readerState &= ~SCARD_SPECIFIC;
307
rContext->readerState->readerState &= ~SCARD_SWALLOWED;
308
rContext->readerState->readerState |= SCARD_UNKNOWN;
309
rContext->readerState->cardAtrLength = 0;
310
rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNSET;
312
dwCurrentState = SCARD_UNKNOWN;
314
SYS_MMapSynchronize((void *) rContext->readerState, pageSize);
317
* This code causes race conditions on G4's with USB
321
* dwErrorCount += 1; SYS_Sleep(1);
324
* After 10 seconds of errors, try to reinitialize the reader
325
* This sometimes helps bring readers out of *crazy* states.
328
* if ( dwErrorCount == 10 ) { RFUnInitializeReader( rContext
329
* ); RFInitializeReader( rContext ); dwErrorCount = 0; }
333
* End of race condition code block
337
if (dwStatus & SCARD_ABSENT)
339
if (dwCurrentState == SCARD_PRESENT ||
340
dwCurrentState == SCARD_UNKNOWN)
343
* Change the status structure
345
Log2(PCSC_LOG_INFO, "Card Removed From %s", lpcReader);
347
* Notify the card has been removed
349
RFSetReaderEventState(rContext, SCARD_REMOVED);
351
rContext->readerState->cardAtrLength = 0;
352
rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNSET;
353
rContext->readerState->readerState |= SCARD_ABSENT;
354
rContext->readerState->readerState &= ~SCARD_UNKNOWN;
355
rContext->readerState->readerState &= ~SCARD_PRESENT;
356
rContext->readerState->readerState &= ~SCARD_POWERED;
357
rContext->readerState->readerState &= ~SCARD_NEGOTIABLE;
358
rContext->readerState->readerState &= ~SCARD_SWALLOWED;
359
rContext->readerState->readerState &= ~SCARD_SPECIFIC;
360
dwCurrentState = SCARD_ABSENT;
362
SYS_MMapSynchronize((void *) rContext->readerState, pageSize);
366
else if (dwStatus & SCARD_PRESENT)
368
if (dwCurrentState == SCARD_ABSENT ||
369
dwCurrentState == SCARD_UNKNOWN)
372
* Power and reset the card
374
SYS_USleep(PCSCLITE_STATUS_WAIT);
375
rv = IFDPowerICC(rContext, IFD_POWER_UP,
376
rContext->readerState->cardAtr,
377
&rContext->readerState->cardAtrLength);
379
/* the protocol is unset after a power on */
380
rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNSET;
382
if (rv == IFD_SUCCESS)
384
rContext->readerState->readerState |= SCARD_PRESENT;
385
rContext->readerState->readerState &= ~SCARD_ABSENT;
386
rContext->readerState->readerState |= SCARD_POWERED;
387
rContext->readerState->readerState |= SCARD_NEGOTIABLE;
388
rContext->readerState->readerState &= ~SCARD_SPECIFIC;
389
rContext->readerState->readerState &= ~SCARD_UNKNOWN;
390
rContext->readerState->readerState &= ~SCARD_SWALLOWED;
393
* Notify the card has been reset
395
RFSetReaderEventState(rContext, SCARD_RESET);
399
rContext->readerState->readerState |= SCARD_PRESENT;
400
rContext->readerState->readerState &= ~SCARD_ABSENT;
401
rContext->readerState->readerState |= SCARD_SWALLOWED;
402
rContext->readerState->readerState &= ~SCARD_POWERED;
403
rContext->readerState->readerState &= ~SCARD_NEGOTIABLE;
404
rContext->readerState->readerState &= ~SCARD_SPECIFIC;
405
rContext->readerState->readerState &= ~SCARD_UNKNOWN;
406
rContext->readerState->cardAtrLength = 0;
409
dwCurrentState = SCARD_PRESENT;
411
SYS_MMapSynchronize((void *) rContext->readerState, pageSize);
413
Log2(PCSC_LOG_INFO, "Card inserted into %s", lpcReader);
415
if (rv == IFD_SUCCESS)
417
if (rContext->readerState->cardAtrLength > 0)
419
LogXxd(PCSC_LOG_INFO, "Card ATR: ",
420
rContext->readerState->cardAtr,
421
rContext->readerState->cardAtrLength);
424
Log1(PCSC_LOG_INFO, "Card ATR: (NULL)");
427
Log1(PCSC_LOG_ERROR,"Error powering up card.");
431
if (rContext->dwLockId == 0xFFFF)
434
* Exit and notify the caller
436
rContext->dwLockId = 0;
437
SYS_ThreadDetach(rContext->pthThread);
442
* Sharing may change w/o an event pass it on
445
if (dwReaderSharing != rContext->dwContexts)
447
dwReaderSharing = rContext->dwContexts;
448
rContext->readerState->readerSharing = dwReaderSharing;
449
SYS_MMapSynchronize((void *) rContext->readerState, pageSize);
452
SYS_USleep(PCSCLITE_STATUS_POLL_RATE);
456
void EHSetSharingEvent(PREADER_CONTEXT rContext, DWORD dwValue)
458
rContext->readerState->lockState = dwValue;