src: fix for OSs not supporting PnP Notification

- Instead of waiting for the notification, it will poll every second for a new
  card reader.
- Thanks to Ludovic Rousseau for the help. See:
  https://github.com/santigimeno/node-pcsclite/issues/14
This commit is contained in:
Santiago Gimeno
2014-09-16 14:25:26 +02:00
parent f85250beb0
commit 5b10f8519c
2 changed files with 32 additions and 8 deletions

View File

@@ -21,7 +21,9 @@ void PCSCLite::init(Handle<Object> target) {
} }
PCSCLite::PCSCLite(): m_card_context(NULL), PCSCLite::PCSCLite(): m_card_context(NULL),
m_card_reader_state(),
m_status_thread(NULL) { m_status_thread(NULL) {
pthread_mutex_init(&m_mutex, NULL); pthread_mutex_init(&m_mutex, NULL);
LONG result = SCardEstablishContext(SCARD_SCOPE_SYSTEM, LONG result = SCardEstablishContext(SCARD_SCOPE_SYSTEM,
@@ -30,6 +32,19 @@ PCSCLite::PCSCLite(): m_card_context(NULL),
&m_card_context); &m_card_context);
if (result != SCARD_S_SUCCESS) { if (result != SCARD_S_SUCCESS) {
NanThrowError(error_msg("SCardEstablishContext", result).c_str()); NanThrowError(error_msg("SCardEstablishContext", result).c_str());
} else {
m_card_reader_state.szReader = "\\\\?PnP?\\Notification";
m_card_reader_state.dwCurrentState = SCARD_STATE_UNAWARE;
result = SCardGetStatusChange(m_card_context,
0,
&m_card_reader_state,
1);
if ((result != SCARD_S_SUCCESS) && (result != SCARD_E_TIMEOUT)) {
NanThrowError(pcsc_stringify_error(result));
} else {
m_pnp = !(m_card_reader_state.dwEventState & SCARD_STATE_UNKNOWN);
}
} }
} }
@@ -125,22 +140,29 @@ void* PCSCLite::HandlerFunction(void* arg) {
AsyncBaton* async_baton = static_cast<AsyncBaton*>(arg); AsyncBaton* async_baton = static_cast<AsyncBaton*>(arg);
PCSCLite* pcsclite = async_baton->pcsclite; PCSCLite* pcsclite = async_baton->pcsclite;
async_baton->async_result = new AsyncResult(); async_baton->async_result = new AsyncResult();
while (result == SCARD_S_SUCCESS) {
SCARD_READERSTATE card_reader_state = SCARD_READERSTATE();
card_reader_state.szReader = "\\\\?PnP?\\Notification";
card_reader_state.dwCurrentState = SCARD_STATE_UNAWARE;
while(result == SCARD_S_SUCCESS) {
/* Lock mutex. It'll be unlocked after the callback has been sent */ /* Lock mutex. It'll be unlocked after the callback has been sent */
pthread_mutex_lock(&pcsclite->m_mutex); pthread_mutex_lock(&pcsclite->m_mutex);
/* Get card readers */ /* Get card readers */
result = pcsclite->get_card_readers(pcsclite, async_baton->async_result); result = pcsclite->get_card_readers(pcsclite, async_baton->async_result);
if (result == SCARD_E_NO_READERS_AVAILABLE) {
result = SCARD_S_SUCCESS;
}
/* Store the result in the baton */ /* Store the result in the baton */
async_baton->async_result->result = result; async_baton->async_result->result = result;
/* Notify the nodejs thread */ /* Notify the nodejs thread */
uv_async_send(&async_baton->async); uv_async_send(&async_baton->async);
/* Start checking for status change */ if (pcsclite->m_pnp) {
result = SCardGetStatusChange(pcsclite->m_card_context, INFINITE, &card_reader_state, 1); /* Start checking for status change */
result = SCardGetStatusChange(pcsclite->m_card_context,
INFINITE,
&pcsclite->m_card_reader_state,
1);
} else {
/* If PnP is not supported, just wait for 1 second */
sleep(1);
}
} }
async_baton->async_result->do_exit = true; async_baton->async_result->do_exit = true;

View File

@@ -49,8 +49,10 @@ class PCSCLite: public node::ObjectWrap {
private: private:
SCARDCONTEXT m_card_context; SCARDCONTEXT m_card_context;
SCARD_READERSTATE m_card_reader_state;
pthread_t m_status_thread; pthread_t m_status_thread;
pthread_mutex_t m_mutex; pthread_mutex_t m_mutex;
bool m_pnp;
}; };
#endif /* PCSCLITE_H */ #endif /* PCSCLITE_H */