#ifndef _H_PCSC_PP
#define _H_PCSC_PP
#include <security_utilities/utilities.h>
#include <security_utilities/errors.h>
#include <security_utilities/transactions.h>
#include <security_utilities/debugging.h>
#include <PCSC/winscard.h>
#include <vector>
#include <string>
#include <cstdio>
namespace Security {
namespace PCSC {
class Error : public CommonError {
public:
Error(unsigned long err);
const unsigned long error;
OSStatus osStatus() const;
int unixError() const;
const char *what () const throw ();
static void check(unsigned long err) { if (err != SCARD_S_SUCCESS) throwMe(err); }
static void throwMe(unsigned long err);
};
class ReaderState : public PodWrapper<ReaderState, SCARD_READERSTATE> {
public:
void set(const char *name, unsigned long known = SCARD_STATE_UNAWARE);
const char *name() const { return szReader; }
void name(const char *s) { szReader = s; }
unsigned long lastKnown() const { return dwCurrentState; }
void lastKnown(unsigned long s);
unsigned long state() const { return dwEventState; }
bool state(unsigned long it) const { return state() & it; }
bool changed() const { return state(SCARD_STATE_CHANGED); }
template <class T>
T * &userData() { return reinterpret_cast<T * &>(pvUserData); }
const void *data() const { return rgbAtr; }
size_t length() const { return cbAtr; }
void setATR(const void *atr, size_t size);
IFDUMP(void dump());
};
class Session {
friend class Card;
public:
Session();
virtual ~Session();
void open();
void close();
bool isOpen() const { return mIsOpen; }
void listReaders(vector<string> &readers, const char *groups = NULL);
void statusChange(ReaderState *readers, unsigned int nReaders, long timeout = 0);
void statusChange(ReaderState &reader, long timeout = 0)
{ return statusChange(&reader, 1, timeout); }
void statusChange(vector<ReaderState> &readers, long timeout = 0)
{ return statusChange(&readers[0], (unsigned int)readers.size(), timeout); }
private:
bool check(long rc);
private:
bool mIsOpen;
SCARDCONTEXT mContext;
std::vector<char> mReaderBuffer;
};
class Card {
public:
static const unsigned long defaultProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
Card();
virtual ~Card();
void connect(Session &session, const char *reader,
unsigned long share = SCARD_SHARE_SHARED,
unsigned long protocols = defaultProtocols);
void reconnect(unsigned long share = SCARD_SHARE_SHARED,
unsigned long protocols = defaultProtocols,
unsigned long initialization = SCARD_LEAVE_CARD);
void disconnect(unsigned long disposition = SCARD_LEAVE_CARD);
virtual void didDisconnect();
virtual void didEnd();
void checkReset(unsigned int rv);
bool isConnected() const { return mConnectedState == kConnected; }
bool isInTransaction() const { return mTransactionNestLevel > 0; }
void transmit(const unsigned char *pbSendBuffer, size_t cbSendLength,
unsigned char *pbRecvBuffer, size_t &pcbRecvLength);
void begin();
void end(unsigned long disposition = SCARD_LEAVE_CARD);
void cancel();
protected:
void setIOType(unsigned long activeProtocol);
IFDUMP(void dump(const char *direction, const unsigned char *buffer, size_t length);)
private:
enum
{
kInitial,
kConnected,
kDisconnected
} mConnectedState;
int32_t mHandle;
int mTransactionNestLevel;
SCARD_IO_REQUEST *mIOType;
};
class Transaction : public ManagedTransaction<Card> {
public:
Transaction(Card &card, Outcome outcome = conditional)
: ManagedTransaction<Card>(card, outcome), mDisposition(SCARD_LEAVE_CARD) { }
void disposition(unsigned long disp);
protected:
void commitAction();
private:
unsigned long mDisposition; };
} }
#endif //_H_PCSC_PP