2
* MUSCLE SmartCard Development ( http://www.linuxnet.com )
5
* David Corcoran <corcoran@linuxnet.com>
7
* Ludovic Rousseau <ludovic.rousseau@free.fr>
9
* $Id: eventhandler.c 1680 2005-09-28 08:06:09Z rousseau $
14
* @brief This keeps track of card insertion/removal events
15
* and updates ATR, protocol, and status information.
19
#include <sys/types.h>
27
#include "ifdhandler.h"
29
#include "thread_generic.h"
30
#include "readerfactory.h"
31
#include "eventhandler.h"
32
#include "dyn_generic.h"
33
#include "sys_generic.h"
34
#include "ifdwrapper.h"
35
#include "prothandler.h"
36
#include "strlcpycat.h"
38
static PREADER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS];
40
void EHStatusHandlerThread(PREADER_CONTEXT);
42
LONG EHInitializeEventStructures(void)
50
SYS_RemoveFile(PCSCLITE_PUBSHM_FILE);
52
fd = SYS_OpenFile(PCSCLITE_PUBSHM_FILE, O_RDWR | O_CREAT, 00644);
55
Log3(PCSC_LOG_CRITICAL, "Cannot create public shared file %s: %s",
56
PCSCLITE_PUBSHM_FILE, strerror(errno));
60
SYS_Chmod(PCSCLITE_PUBSHM_FILE,
61
S_IRGRP | S_IREAD | S_IWRITE | S_IROTH);
63
pageSize = SYS_GetPageSize();
66
* Jump to end of file space and allocate zero's
68
SYS_SeekFile(fd, pageSize * PCSCLITE_MAX_READERS_CONTEXTS);
69
SYS_WriteFile(fd, "", 1);
72
* Allocate each reader structure
74
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
76
readerStates[i] = (PREADER_STATE)
77
SYS_MemoryMap(sizeof(READER_STATE), fd, (i * pageSize));
78
if (readerStates[i] == 0)
80
Log3(PCSC_LOG_CRITICAL, "Cannot memory map public shared file %s: %s",
81
PCSCLITE_PUBSHM_FILE, strerror(errno));
86
* Zero out each value in the struct
88
memset((readerStates[i])->readerName, 0, MAX_READERNAME);
89
memset((readerStates[i])->cardAtr, 0, MAX_ATR_SIZE);
90
(readerStates[i])->readerID = 0;
91
(readerStates[i])->readerState = 0;
92
(readerStates[i])->lockState = 0;
93
(readerStates[i])->readerSharing = 0;
94
(readerStates[i])->cardAtrLength = 0;
95
(readerStates[i])->cardProtocol = SCARD_PROTOCOL_UNSET;
98
return SCARD_S_SUCCESS;
101
LONG EHDestroyEventHandler(PREADER_CONTEXT rContext)
103
if (NULL == rContext->readerState)
105
Log1(PCSC_LOG_ERROR, "Thread never started (reader init failed?)");
106
return SCARD_S_SUCCESS;
109
if ('\0' == rContext->readerState->readerName[0])
111
Log1(PCSC_LOG_INFO, "Thread already stomped.");
112
return SCARD_S_SUCCESS;
116
* Set the thread to 0 to exit thread
118
rContext->dwLockId = 0xFFFF;
120
Log1(PCSC_LOG_INFO, "Stomping thread.");
125
* Wait 0.05 seconds for the child to respond
129
while (rContext->dwLockId == 0xFFFF);
131
* Zero out the public status struct to allow it to be recycled and
135
memset(rContext->readerState->readerName, 0,
136
sizeof(rContext->readerState->readerName));
137
memset(rContext->readerState->cardAtr, 0,
138
sizeof(rContext->readerState->cardAtr));
139
rContext->readerState->readerID = 0;
140
rContext->readerState->readerState = 0;
141
rContext->readerState->lockState = 0;
142
rContext->readerState->readerSharing = 0;
143
rContext->readerState->cardAtrLength = 0;
144
rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNSET;
146
/* Zero the thread */
147
rContext->pthThread = 0;
149
Log1(PCSC_LOG_INFO, "Thread stomped.");
151
return SCARD_S_SUCCESS;
154
LONG EHSpawnEventHandler(PREADER_CONTEXT rContext)
159
UCHAR ucAtr[MAX_ATR_SIZE];
162
rv = IFDStatusICC(rContext, &dwStatus, ucAtr, &dwAtrLen);
163
if (rv != SCARD_S_SUCCESS)
165
Log2(PCSC_LOG_ERROR, "Initial Check Failed on %s", rContext->lpcReader);
166
return SCARD_F_UNKNOWN_ERROR;
170
* Find an empty reader slot and insert the new reader
172
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
174
if ((readerStates[i])->readerID == 0)
178
if (i == PCSCLITE_MAX_READERS_CONTEXTS)
179
return SCARD_F_INTERNAL_ERROR;
182
* Set all the attributes to this reader
184
rContext->readerState = readerStates[i];
185
strlcpy(rContext->readerState->readerName, rContext->lpcReader,
186
sizeof(rContext->readerState->readerName));
187
memcpy(rContext->readerState->cardAtr, ucAtr, dwAtrLen);
188
rContext->readerState->readerID = i + 100;
189
rContext->readerState->readerState = dwStatus;
190
rContext->readerState->readerSharing = rContext->dwContexts;
191
rContext->readerState->cardAtrLength = dwAtrLen;
192
rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNSET;
194
rv = SYS_ThreadCreate(&rContext->pthThread, THREAD_ATTR_DETACHED,
195
(PCSCLITE_THREAD_FUNCTION( ))EHStatusHandlerThread, (LPVOID) rContext);
197
return SCARD_S_SUCCESS;
199
return SCARD_E_NO_MEMORY;
202
void EHStatusHandlerThread(PREADER_CONTEXT rContext)
206
DWORD dwStatus, dwReaderSharing;
207
DWORD dwCurrentState;
211
* Zero out everything
217
lpcReader = rContext->lpcReader;
219
pageSize = SYS_GetPageSize();
221
rv = IFDStatusICC(rContext, &dwStatus, rContext->readerState->cardAtr,
222
&rContext->readerState->cardAtrLength);
223
if (dwStatus & SCARD_PRESENT)
225
rContext->readerState->cardAtrLength = MAX_ATR_SIZE;
226
rv = IFDPowerICC(rContext, IFD_POWER_UP,
227
rContext->readerState->cardAtr,
228
&rContext->readerState->cardAtrLength);
230
/* the protocol is unset after a power on */
231
rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNSET;
233
if (rv == IFD_SUCCESS)
235
dwStatus |= SCARD_PRESENT;
236
dwStatus &= ~SCARD_ABSENT;
237
dwStatus |= SCARD_POWERED;
238
dwStatus |= SCARD_NEGOTIABLE;
239
dwStatus &= ~SCARD_SPECIFIC;
240
dwStatus &= ~SCARD_SWALLOWED;
241
dwStatus &= ~SCARD_UNKNOWN;
243
if (rContext->readerState->cardAtrLength > 0)
245
LogXxd(PCSC_LOG_INFO, "Card ATR: ",
246
rContext->readerState->cardAtr,
247
rContext->readerState->cardAtrLength);
250
Log1(PCSC_LOG_INFO, "Card ATR: (NULL)");
254
dwStatus |= SCARD_PRESENT;
255
dwStatus &= ~SCARD_ABSENT;
256
dwStatus |= SCARD_SWALLOWED;
257
dwStatus &= ~SCARD_POWERED;
258
dwStatus &= ~SCARD_NEGOTIABLE;
259
dwStatus &= ~SCARD_SPECIFIC;
260
dwStatus &= ~SCARD_UNKNOWN;
261
Log2(PCSC_LOG_ERROR, "Error powering up card: %d", rv);
264
dwCurrentState = SCARD_PRESENT;
268
dwStatus |= SCARD_ABSENT;
269
dwStatus &= ~SCARD_PRESENT;
270
dwStatus &= ~SCARD_POWERED;
271
dwStatus &= ~SCARD_NEGOTIABLE;
272
dwStatus &= ~SCARD_SPECIFIC;
273
dwStatus &= ~SCARD_SWALLOWED;
274
dwStatus &= ~SCARD_UNKNOWN;
275
rContext->readerState->cardAtrLength = 0;
276
rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNSET;
278
dwCurrentState = SCARD_ABSENT;
282
* Set all the public attributes to this reader
284
rContext->readerState->readerState = dwStatus;
285
rContext->readerState->readerSharing = dwReaderSharing =
286
rContext->dwContexts;
288
SYS_MMapSynchronize((void *) rContext->readerState, pageSize);
294
rv = IFDStatusICC(rContext, &dwStatus,
295
rContext->readerState->cardAtr,
296
&rContext->readerState->cardAtrLength);
298
if (rv != SCARD_S_SUCCESS)
300
Log2(PCSC_LOG_ERROR, "Error communicating to: %s", lpcReader);
303
* Set error status on this reader while errors occur
306
rContext->readerState->readerState &= ~SCARD_ABSENT;
307
rContext->readerState->readerState &= ~SCARD_PRESENT;
308
rContext->readerState->readerState &= ~SCARD_POWERED;
309
rContext->readerState->readerState &= ~SCARD_NEGOTIABLE;
310
rContext->readerState->readerState &= ~SCARD_SPECIFIC;
311
rContext->readerState->readerState &= ~SCARD_SWALLOWED;
312
rContext->readerState->readerState |= SCARD_UNKNOWN;
313
rContext->readerState->cardAtrLength = 0;
314
rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNSET;
316
dwCurrentState = SCARD_UNKNOWN;
318
SYS_MMapSynchronize((void *) rContext->readerState, pageSize);
321
* This code causes race conditions on G4's with USB
325
* dwErrorCount += 1; SYS_Sleep(1);
328
* After 10 seconds of errors, try to reinitialize the reader
329
* This sometimes helps bring readers out of *crazy* states.
332
* if ( dwErrorCount == 10 ) { RFUnInitializeReader( rContext
333
* ); RFInitializeReader( rContext ); dwErrorCount = 0; }
337
* End of race condition code block
341
if (dwStatus & SCARD_ABSENT)
343
if (dwCurrentState == SCARD_PRESENT ||
344
dwCurrentState == SCARD_UNKNOWN)
347
* Change the status structure
349
Log2(PCSC_LOG_INFO, "Card Removed From %s", lpcReader);
351
* Notify the card has been removed
353
RFSetReaderEventState(rContext, SCARD_REMOVED);
355
rContext->readerState->cardAtrLength = 0;
356
rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNSET;
357
rContext->readerState->readerState |= SCARD_ABSENT;
358
rContext->readerState->readerState &= ~SCARD_UNKNOWN;
359
rContext->readerState->readerState &= ~SCARD_PRESENT;
360
rContext->readerState->readerState &= ~SCARD_POWERED;
361
rContext->readerState->readerState &= ~SCARD_NEGOTIABLE;
362
rContext->readerState->readerState &= ~SCARD_SWALLOWED;
363
rContext->readerState->readerState &= ~SCARD_SPECIFIC;
364
dwCurrentState = SCARD_ABSENT;
366
SYS_MMapSynchronize((void *) rContext->readerState, pageSize);
370
else if (dwStatus & SCARD_PRESENT)
372
if (dwCurrentState == SCARD_ABSENT ||
373
dwCurrentState == SCARD_UNKNOWN)
376
* Power and reset the card
378
SYS_USleep(PCSCLITE_STATUS_WAIT);
379
rContext->readerState->cardAtrLength = MAX_ATR_SIZE;
380
rv = IFDPowerICC(rContext, IFD_POWER_UP,
381
rContext->readerState->cardAtr,
382
&rContext->readerState->cardAtrLength);
384
/* the protocol is unset after a power on */
385
rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNSET;
387
if (rv == IFD_SUCCESS)
389
rContext->readerState->readerState |= SCARD_PRESENT;
390
rContext->readerState->readerState &= ~SCARD_ABSENT;
391
rContext->readerState->readerState |= SCARD_POWERED;
392
rContext->readerState->readerState |= SCARD_NEGOTIABLE;
393
rContext->readerState->readerState &= ~SCARD_SPECIFIC;
394
rContext->readerState->readerState &= ~SCARD_UNKNOWN;
395
rContext->readerState->readerState &= ~SCARD_SWALLOWED;
398
* Notify the card has been reset
400
RFSetReaderEventState(rContext, SCARD_RESET);
404
rContext->readerState->readerState |= SCARD_PRESENT;
405
rContext->readerState->readerState &= ~SCARD_ABSENT;
406
rContext->readerState->readerState |= SCARD_SWALLOWED;
407
rContext->readerState->readerState &= ~SCARD_POWERED;
408
rContext->readerState->readerState &= ~SCARD_NEGOTIABLE;
409
rContext->readerState->readerState &= ~SCARD_SPECIFIC;
410
rContext->readerState->readerState &= ~SCARD_UNKNOWN;
411
rContext->readerState->cardAtrLength = 0;
414
dwCurrentState = SCARD_PRESENT;
416
SYS_MMapSynchronize((void *) rContext->readerState, pageSize);
418
Log2(PCSC_LOG_INFO, "Card inserted into %s", lpcReader);
420
if (rv == IFD_SUCCESS)
422
if (rContext->readerState->cardAtrLength > 0)
424
LogXxd(PCSC_LOG_INFO, "Card ATR: ",
425
rContext->readerState->cardAtr,
426
rContext->readerState->cardAtrLength);
429
Log1(PCSC_LOG_INFO, "Card ATR: (NULL)");
432
Log1(PCSC_LOG_ERROR,"Error powering up card.");
436
if (rContext->dwLockId == 0xFFFF)
439
* Exit and notify the caller
441
rContext->dwLockId = 0;
442
SYS_ThreadDetach(rContext->pthThread);
447
* Sharing may change w/o an event pass it on
450
if (dwReaderSharing != rContext->dwContexts)
452
dwReaderSharing = rContext->dwContexts;
453
rContext->readerState->readerSharing = dwReaderSharing;
454
SYS_MMapSynchronize((void *) rContext->readerState, pageSize);
457
SYS_USleep(PCSCLITE_STATUS_POLL_RATE);
461
void EHSetSharingEvent(PREADER_CONTEXT rContext, DWORD dwValue)
463
rContext->readerState->lockState = dwValue;