[PC/SC] detect other events besides card insertion/removal
* remove whitespace. * don't use SC_MAX_READERS and allocate memory dynamically. git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@3987 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
4c34f5b28c
commit
36992b4001
|
@ -2,6 +2,7 @@
|
|||
* reader-pcsc.c: Reader driver for PC/SC interface
|
||||
*
|
||||
* Copyright (C) 2002 Juha Yrjölä <juha.yrjola@iki.fi>
|
||||
* Copyright (C) 2009,2010 Martin Paljak <martin@paljak.pri.ee>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -683,6 +684,8 @@ static int pcsc_finish(sc_context_t *ctx, void *prv_data)
|
|||
{
|
||||
struct pcsc_global_private_data *gpriv = (struct pcsc_global_private_data *) prv_data;
|
||||
|
||||
SC_FUNC_CALLED(ctx, 3);
|
||||
|
||||
if (gpriv) {
|
||||
if (gpriv->pcsc_ctx != -1)
|
||||
gpriv->SCardReleaseContext(gpriv->pcsc_ctx);
|
||||
|
@ -950,30 +953,20 @@ static int pcsc_wait_for_event(sc_context_t *ctx,
|
|||
{
|
||||
struct pcsc_global_private_data *gpriv = (struct pcsc_global_private_data *)reader_data;
|
||||
LONG rv;
|
||||
SCARD_READERSTATE_A rgReaderStates[SC_MAX_READERS + 1];
|
||||
unsigned long on_bits, off_bits;
|
||||
SCARD_READERSTATE_A *rgReaderStates;
|
||||
size_t i;
|
||||
unsigned int num_watch;
|
||||
int r = SC_ERROR_INTERNAL;
|
||||
|
||||
SC_FUNC_CALLED(ctx, 3);
|
||||
on_bits = off_bits = 0;
|
||||
|
||||
if (event_mask & SC_EVENT_CARD_INSERTED) {
|
||||
event_mask &= ~SC_EVENT_CARD_INSERTED;
|
||||
on_bits |= SCARD_STATE_PRESENT;
|
||||
}
|
||||
if (event_mask & SC_EVENT_CARD_REMOVED) {
|
||||
event_mask &= ~SC_EVENT_CARD_REMOVED;
|
||||
off_bits |= SCARD_STATE_PRESENT;
|
||||
}
|
||||
|
||||
/* FIXME check for unhandled masks?
|
||||
if (event_mask != 0)
|
||||
return SC_ERROR_INVALID_ARGUMENTS; */
|
||||
rgReaderStates = (SCARD_READERSTATE_A *) calloc(sc_ctx_get_reader_count(ctx) + 1, sizeof(SCARD_READERSTATE_A));
|
||||
if (!rgReaderStates)
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
/* Find out the current status */
|
||||
num_watch = sc_ctx_get_reader_count(ctx);
|
||||
sc_debug(ctx, "Watching %d readers\n", num_watch);
|
||||
sc_debug(ctx, "Trying to watch %d readers", num_watch);
|
||||
for (i = 0; i < num_watch; i++) {
|
||||
rgReaderStates[i].szReader = sc_ctx_get_reader(ctx, i)->name;
|
||||
rgReaderStates[i].dwCurrentState = SCARD_STATE_UNAWARE;
|
||||
|
@ -993,7 +986,8 @@ static int pcsc_wait_for_event(sc_context_t *ctx,
|
|||
rv = gpriv->SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &gpriv->pcsc_wait_ctx);
|
||||
if (rv != SCARD_S_SUCCESS) {
|
||||
PCSC_LOG(ctx, "SCardEstablishContext(wait) failed", rv);
|
||||
return pcsc_to_opensc_error(rv);
|
||||
r = pcsc_to_opensc_error(rv);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
@ -1002,14 +996,16 @@ static int pcsc_wait_for_event(sc_context_t *ctx,
|
|||
if (num_watch == 0) {
|
||||
sc_debug(ctx, "No readers available, PnP notification not supported");
|
||||
*event_reader = NULL;
|
||||
return SC_ERROR_NO_READERS_FOUND;
|
||||
r = SC_ERROR_NO_READERS_FOUND;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rv = gpriv->SCardGetStatusChange(gpriv->pcsc_wait_ctx, 0, rgReaderStates, num_watch);
|
||||
if (rv != SCARD_S_SUCCESS) {
|
||||
if (rv != (LONG)SCARD_E_TIMEOUT) {
|
||||
PCSC_LOG(ctx, "SCardGetStatusChange(1) failed", rv);
|
||||
return pcsc_to_opensc_error(rv);
|
||||
r = pcsc_to_opensc_error(rv);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1027,26 +1023,43 @@ static int pcsc_wait_for_event(sc_context_t *ctx,
|
|||
sc_debug(ctx, "%s before=0x%04X now=0x%04X", rsp->szReader, rsp->dwCurrentState, rsp->dwEventState);
|
||||
prev_state = rsp->dwCurrentState;
|
||||
state = rsp->dwEventState;
|
||||
if ((state & on_bits & SCARD_STATE_PRESENT) &&
|
||||
(prev_state & SCARD_STATE_EMPTY))
|
||||
if (state & SCARD_STATE_CHANGED) {
|
||||
|
||||
/* check for hotplug events */
|
||||
if (!strcmp(rgReaderStates[i].szReader, "\\\\?PnP?\\Notification")) {
|
||||
sc_debug(ctx, "detected hotplug event");
|
||||
*event |= SC_EVENT_READER_ATTACHED;
|
||||
*event_reader = NULL;
|
||||
}
|
||||
|
||||
if ((state & SCARD_STATE_PRESENT) && !(prev_state & SCARD_STATE_PRESENT)) {
|
||||
sc_debug(ctx, "card inserted event");
|
||||
*event |= SC_EVENT_CARD_INSERTED;
|
||||
if ((~state & off_bits & SCARD_STATE_PRESENT) &&
|
||||
(prev_state & SCARD_STATE_PRESENT))
|
||||
}
|
||||
|
||||
if ((prev_state & SCARD_STATE_PRESENT) && !(state & SCARD_STATE_PRESENT)) {
|
||||
sc_debug(ctx, "card removed event");
|
||||
*event |= SC_EVENT_CARD_REMOVED;
|
||||
if (*event) {
|
||||
sc_debug(ctx, "Event 0x%02X in reader %s", *event, rsp->szReader);
|
||||
}
|
||||
|
||||
if ((state & SCARD_STATE_UNKNOWN) && !(prev_state & SCARD_STATE_UNKNOWN)) {
|
||||
sc_debug(ctx, "reader detached event");
|
||||
*event |= SC_EVENT_READER_DETACHED;
|
||||
}
|
||||
|
||||
if ((prev_state & SCARD_STATE_UNKNOWN) && !(state & SCARD_STATE_UNKNOWN)) {
|
||||
sc_debug(ctx, "reader re-attached event");
|
||||
*event |= SC_EVENT_READER_ATTACHED;
|
||||
}
|
||||
|
||||
if (*event & event_mask) {
|
||||
sc_debug(ctx, "Matching event 0x%02X in reader %s", *event, rsp->szReader);
|
||||
*event_reader = sc_ctx_get_reader_by_name(ctx, rsp->szReader);
|
||||
r = SC_SUCCESS;
|
||||
goto out;
|
||||
SC_FUNC_RETURN(ctx, 3, SC_SUCCESS);
|
||||
}
|
||||
|
||||
/* check for hotplug event */
|
||||
if (strcmp(rgReaderStates[i].szReader, "\\\\?PnP?\\Notification") == 0 && event_mask & SC_EVENT_READER_ATTACHED) {
|
||||
if (state & SCARD_STATE_CHANGED) {
|
||||
sc_debug(ctx, "detected hotplug event");
|
||||
*event = SC_EVENT_READER_ATTACHED;
|
||||
*event_reader = NULL;
|
||||
SC_FUNC_RETURN(ctx, 3, SC_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
/* No match - copy the state so pcscd knows
|
||||
|
@ -1054,29 +1067,39 @@ static int pcsc_wait_for_event(sc_context_t *ctx,
|
|||
rsp->dwCurrentState = rsp->dwEventState;
|
||||
}
|
||||
|
||||
/* Set the timeout if caller wants to time out */
|
||||
if (timeout == 0)
|
||||
return SC_ERROR_EVENT_TIMEOUT;
|
||||
if (timeout == 0) {
|
||||
r = SC_ERROR_EVENT_TIMEOUT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Set the timeout if caller wants to time out */
|
||||
if (timeout == -1) {
|
||||
timeout = INFINITE;
|
||||
}
|
||||
|
||||
sc_debug(ctx, "Sleeping call, timeout 0x%lx", timeout);
|
||||
rv = gpriv->SCardGetStatusChange(gpriv->pcsc_wait_ctx, timeout, rgReaderStates, num_watch);
|
||||
|
||||
if (rv == (LONG) SCARD_E_CANCELLED) {
|
||||
/* C_Finalize was called, events don't matter */
|
||||
return SC_ERROR_EVENT_TIMEOUT;
|
||||
r = SC_ERROR_EVENT_TIMEOUT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (rv == (LONG) SCARD_E_TIMEOUT) {
|
||||
return SC_ERROR_EVENT_TIMEOUT;
|
||||
r = SC_ERROR_EVENT_TIMEOUT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (rv != SCARD_S_SUCCESS) {
|
||||
PCSC_LOG(ctx, "SCardGetStatusChange(2) failed", rv);
|
||||
return pcsc_to_opensc_error(rv);
|
||||
r = pcsc_to_opensc_error(rv);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
out:
|
||||
free(rgReaderStates);
|
||||
SC_FUNC_RETURN(ctx, 3, r);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue