#include <sys/types.h>
#include <sys/stat.h>
#include <sys/errno.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include "config.h"
#include "wintypes.h"
#include "pcsclite.h"
#include "thread_generic.h"
#include "readerfactory.h"
#include "eventhandler.h"
#include "dyn_generic.h"
#include "sys_generic.h"
#include "ifdhandler.h"
#include "ifdwrapper.h"
#include "debuglog.h"
#include "prothandler.h"
#include <security_utilities/debugging.h>
static PREADER_STATES readerStates[PCSCLITE_MAX_CONTEXTS];
void EHStatusHandlerThread(PREADER_CONTEXT);
LONG EHInitializeEventStructures()
{
int fd, i, pageSize;
fd = 0;
i = 0;
pageSize = 0;
SYS_RemoveFile(PCSCLITE_PUBSHM_FILE);
fd = SYS_OpenFile(PCSCLITE_PUBSHM_FILE, O_RDWR | O_CREAT, 00644);
if (fd < 0)
{
DebugLogA("Error: Cannot open public shared file");
exit(1);
}
SYS_Chmod(PCSCLITE_PUBSHM_FILE,
S_IRGRP | S_IREAD | S_IWRITE | S_IROTH);
pageSize = SYS_GetPageSize();
SYS_SeekFile(fd, pageSize * PCSCLITE_MAX_CONTEXTS);
SYS_WriteFile(fd, "", 1);
for (i = 0; i < PCSCLITE_MAX_CONTEXTS; i++)
{
readerStates[i] = (PREADER_STATES)
SYS_MemoryMap(sizeof(READER_STATES), fd, (i * pageSize));
if (readerStates[i] == 0)
{
DebugLogA("Error: Cannot public memory map");
exit(1);
}
memset((readerStates[i])->readerName, 0, MAX_READERNAME);
memset((readerStates[i])->cardAtr, 0, MAX_ATR_SIZE);
(readerStates[i])->readerID = 0;
(readerStates[i])->readerState = 0;
(readerStates[i])->lockState = 0;
(readerStates[i])->readerSharing = 0;
(readerStates[i])->cardAtrLength = 0;
(readerStates[i])->cardProtocol = 0;
}
return SCARD_S_SUCCESS;
}
LONG EHDestroyEventHandler(PREADER_CONTEXT rContext)
{
LONG rv;
int i;
i = 0;
rv = 0;
i = rContext->dwPublicID;
if ((readerStates[i])->readerName[0] == 0)
{
DebugLogA("EHDestroyEventHandler: Thread already stomped.");
return SCARD_S_SUCCESS;
}
rContext->dwLockId = 0xFFFF;
DebugLogA("EHDestroyEventHandler: Stomping thread.");
do
{
SYS_USleep(50000);
}
while (rContext->dwLockId == 0xFFFF);
memset((readerStates[i])->readerName, 0, MAX_READERNAME);
memset((readerStates[i])->cardAtr, 0, MAX_ATR_SIZE);
(readerStates[i])->readerID = 0;
(readerStates[i])->readerState = 0;
(readerStates[i])->lockState = 0;
(readerStates[i])->readerSharing = 0;
(readerStates[i])->cardAtrLength = 0;
(readerStates[i])->cardProtocol = 0;
SYS_MMapSynchronize((void *) readerStates[i], SYS_GetPageSize());
rContext->pthThread = 0;
DebugLogA("EHDestroyEventHandler: Thread stomped.");
return SCARD_S_SUCCESS;
}
LONG EHSpawnEventHandler(PREADER_CONTEXT rContext)
{
LONG rv;
LPCSTR lpcReader;
DWORD dwStatus, dwProtocol;
int i;
rv = 0;
lpcReader = 0;
dwStatus = 0;
dwProtocol = 0;
i = 0;
lpcReader = rContext->lpcReader;
rv = IFDStatusICC(rContext, &dwStatus,
&dwProtocol, rContext->ucAtr, &rContext->dwAtrLen);
if (rv != SCARD_S_SUCCESS)
{
DebugLogB("EHSpawnEventHandler: Initial Check Failed on %s",
lpcReader);
return SCARD_F_UNKNOWN_ERROR;
}
for (i = 0; i < PCSCLITE_MAX_CONTEXTS; i++)
{
if ((readerStates[i])->readerID == 0)
{
break;
}
}
if (i == PCSCLITE_MAX_CONTEXTS)
{
return SCARD_F_INTERNAL_ERROR;
}
strcpy((readerStates[i])->readerName, rContext->lpcReader);
memcpy((readerStates[i])->cardAtr, rContext->ucAtr,
rContext->dwAtrLen);
(readerStates[i])->readerID = htonl(i + 100);
(readerStates[i])->readerState = htonl(rContext->dwStatus);
(readerStates[i])->readerSharing = htonl(rContext->dwContexts);
(readerStates[i])->cardAtrLength = htonl(rContext->dwAtrLen);
(readerStates[i])->cardProtocol = htonl(rContext->dwProtocol);
rContext->dwPublicID = i;
rv = SYS_ThreadCreate(&rContext->pthThread, NULL,
(LPVOID) EHStatusHandlerThread, (LPVOID) rContext);
secdebug("pcscd", "EHSpawnEventHandler after thread create: %d [%04X]", rv, rv);
if (rv == 1)
{
return SCARD_S_SUCCESS;
} else
{
return SCARD_E_NO_MEMORY;
}
}
void EHStatusHandlerThread(PREADER_CONTEXT rContext)
{
LONG rv;
LPCSTR lpcReader;
DWORD dwStatus, dwProtocol, dwReaderSharing;
DWORD dwErrorCount, dwCurrentState;
int i, pageSize;
rv = 0;
lpcReader = 0;
dwStatus = 0;
dwProtocol = 0;
dwReaderSharing = 0;
dwCurrentState = 0;
dwErrorCount = 0;
i = 0;
pageSize = 0;
lpcReader = rContext->lpcReader;
i = rContext->dwPublicID;
pageSize = SYS_GetPageSize();
rv = IFDStatusICC(rContext, &dwStatus,
&dwProtocol, rContext->ucAtr, &rContext->dwAtrLen);
secdebug("pcscd", "EHStatusHandlerThread: initial call to IFDStatusICC: %d [%04X]", rv, rv);
if (dwStatus & SCARD_PRESENT)
{
rv = IFDPowerICC(rContext, IFD_POWER_UP,
rContext->ucAtr, &rContext->dwAtrLen);
secdebug("pcscd", "EHStatusHandlerThread: initial call to IFDPowerICC: %d [%04X]", rv, rv);
if (rv == IFD_SUCCESS)
{
rContext->dwProtocol = PHGetDefaultProtocol(rContext->ucAtr,
rContext->dwAtrLen);
rContext->dwStatus |= SCARD_PRESENT;
rContext->dwStatus &= ~SCARD_ABSENT;
rContext->dwStatus |= SCARD_POWERED;
rContext->dwStatus |= SCARD_NEGOTIABLE;
rContext->dwStatus &= ~SCARD_SPECIFIC;
rContext->dwStatus &= ~SCARD_SWALLOWED;
rContext->dwStatus &= ~SCARD_UNKNOWN;
} else
{
rContext->dwStatus |= SCARD_PRESENT;
rContext->dwStatus &= ~SCARD_ABSENT;
rContext->dwStatus |= SCARD_SWALLOWED;
rContext->dwStatus &= ~SCARD_POWERED;
rContext->dwStatus &= ~SCARD_NEGOTIABLE;
rContext->dwStatus &= ~SCARD_SPECIFIC;
rContext->dwStatus &= ~SCARD_UNKNOWN;
rContext->dwProtocol = 0;
rContext->dwAtrLen = 0;
}
dwCurrentState = SCARD_PRESENT;
} else
{
dwCurrentState = SCARD_ABSENT;
rContext->dwStatus |= SCARD_ABSENT;
rContext->dwStatus &= ~SCARD_PRESENT;
rContext->dwStatus &= ~SCARD_POWERED;
rContext->dwStatus &= ~SCARD_NEGOTIABLE;
rContext->dwStatus &= ~SCARD_SPECIFIC;
rContext->dwStatus &= ~SCARD_SWALLOWED;
rContext->dwStatus &= ~SCARD_UNKNOWN;
rContext->dwAtrLen = 0;
rContext->dwProtocol = 0;
}
(readerStates[i])->readerState = htonl(rContext->dwStatus);
(readerStates[i])->cardAtrLength = htonl(rContext->dwAtrLen);
(readerStates[i])->cardProtocol = htonl(rContext->dwProtocol);
dwReaderSharing = rContext->dwContexts;
(readerStates[i])->readerSharing = htonl(dwReaderSharing);
memcpy((readerStates[i])->cardAtr, rContext->ucAtr,
rContext->dwAtrLen);
SYS_MMapSynchronize((void *) readerStates[i], pageSize);
while (1)
{
dwStatus = 0;
rv = IFDStatusICC(rContext, &dwStatus,
&dwProtocol, rContext->ucAtr, &rContext->dwAtrLen);
if (rv != SCARD_S_SUCCESS)
{
DebugLogB("EHSpawnEventHandler: Error communicating to: %s",
lpcReader);
rContext->dwStatus &= ~SCARD_ABSENT;
rContext->dwStatus &= ~SCARD_PRESENT;
rContext->dwStatus &= ~SCARD_POWERED;
rContext->dwStatus &= ~SCARD_NEGOTIABLE;
rContext->dwStatus &= ~SCARD_SPECIFIC;
rContext->dwStatus &= ~SCARD_SWALLOWED;
rContext->dwStatus |= SCARD_UNKNOWN;
rContext->dwAtrLen = 0;
rContext->dwProtocol = 0;
dwCurrentState = SCARD_UNKNOWN;
(readerStates[i])->readerState = htonl(rContext->dwStatus);
(readerStates[i])->cardAtrLength = htonl(rContext->dwAtrLen);
(readerStates[i])->cardProtocol = htonl(rContext->dwProtocol);
memcpy((readerStates[i])->cardAtr, rContext->ucAtr,
rContext->dwAtrLen);
SYS_MMapSynchronize((void *) readerStates[i], pageSize);
}
if (dwStatus & SCARD_ABSENT)
{
if (dwCurrentState == SCARD_PRESENT ||
dwCurrentState == SCARD_UNKNOWN)
{
DebugLogB("EHSpawnEventHandler: Card Removed From %s",
lpcReader);
RFSetReaderEventState(rContext, SCARD_REMOVED);
rContext->dwAtrLen = 0;
rContext->dwProtocol = 0;
rContext->dwStatus |= SCARD_ABSENT;
rContext->dwStatus &= ~SCARD_UNKNOWN;
rContext->dwStatus &= ~SCARD_PRESENT;
rContext->dwStatus &= ~SCARD_POWERED;
rContext->dwStatus &= ~SCARD_NEGOTIABLE;
rContext->dwStatus &= ~SCARD_SWALLOWED;
rContext->dwStatus &= ~SCARD_SPECIFIC;
dwCurrentState = SCARD_ABSENT;
(readerStates[i])->readerState = htonl(rContext->dwStatus);
(readerStates[i])->cardAtrLength = htonl(rContext->dwAtrLen);
(readerStates[i])->cardProtocol = htonl(rContext->dwProtocol);
memcpy((readerStates[i])->cardAtr, rContext->ucAtr,
rContext->dwAtrLen);
SYS_MMapSynchronize((void *) readerStates[i], pageSize);
}
} else if (dwStatus & SCARD_PRESENT)
{
if (dwCurrentState == SCARD_ABSENT ||
dwCurrentState == SCARD_UNKNOWN)
{
SYS_USleep(PCSCLITE_STATUS_WAIT);
rv = IFDPowerICC(rContext, IFD_POWER_UP,
rContext->ucAtr, &rContext->dwAtrLen);
secdebug("pcscd", "EHStatusHandlerThread: power-and-reset call to IFDPowerICC: %d [%04X]", rv, rv);
if (rv == IFD_SUCCESS)
{
rContext->dwProtocol =
PHGetDefaultProtocol(rContext->ucAtr,
rContext->dwAtrLen);
rContext->dwStatus |= SCARD_PRESENT;
rContext->dwStatus &= ~SCARD_ABSENT;
rContext->dwStatus |= SCARD_POWERED;
rContext->dwStatus |= SCARD_NEGOTIABLE;
rContext->dwStatus &= ~SCARD_SPECIFIC;
rContext->dwStatus &= ~SCARD_UNKNOWN;
rContext->dwStatus &= ~SCARD_SWALLOWED;
} else
{
rContext->dwStatus |= SCARD_PRESENT;
rContext->dwStatus &= ~SCARD_ABSENT;
rContext->dwStatus |= SCARD_SWALLOWED;
rContext->dwStatus &= ~SCARD_POWERED;
rContext->dwStatus &= ~SCARD_NEGOTIABLE;
rContext->dwStatus &= ~SCARD_SPECIFIC;
rContext->dwStatus &= ~SCARD_UNKNOWN;
rContext->dwAtrLen = 0;
rContext->dwProtocol = 0;
}
dwCurrentState = SCARD_PRESENT;
(readerStates[i])->readerState = htonl(rContext->dwStatus);
(readerStates[i])->cardAtrLength = htonl(rContext->dwAtrLen);
(readerStates[i])->cardProtocol = htonl(rContext->dwProtocol);
memcpy((readerStates[i])->cardAtr, rContext->ucAtr,
rContext->dwAtrLen);
SYS_MMapSynchronize((void *) readerStates[i], pageSize);
DebugLogB("EHSpawnEventHandler: Card inserted into %s",
lpcReader);
if (rv == IFD_SUCCESS)
{
if (rContext->dwAtrLen > 0)
{
DebugXxd("EHSpawnEventHandler: Card ATR: ",
rContext->ucAtr, rContext->dwAtrLen);
} else
{
DebugLogA("EHSpawnEventHandler: Card ATR: (NULL)");
}
} else
{
DebugLogA
("EHSpawnEventHandler: Error powering up card.");
}
}
}
if (rContext->dwLockId == 0xFFFF)
{
secdebug("pcscd", "EHStatusHandlerThread: lockid is -1?? - exiting");
rContext->dwLockId = 0;
SYS_ThreadDetach(rContext->pthThread);
SYS_ThreadExit(0);
}
if (dwReaderSharing != rContext->dwContexts)
{
dwReaderSharing = rContext->dwContexts;
(readerStates[i])->readerSharing = htonl(dwReaderSharing);
SYS_MMapSynchronize((void *) readerStates[i], pageSize);
}
SYS_USleep(PCSCLITE_STATUS_POLL_RATE);
}
}
void EHSetSharingEvent(PREADER_CONTEXT rContext, DWORD dwValue)
{
(readerStates[rContext->dwPublicID])->lockState = htonl(dwValue);
}