bankd: edge detect RESET and VCC indications
- perform edge detection on RESET and VCC client indications to filter out duplicate resets - prior to this change, unrelated changes in the client slot status indication (such as CLK change) could trigger duplicate resets - these resets could happen in rapid succession and lead to reader libusb communication errors that lock-up the PC/SC daemon - a drop in VCC will always induce a cold reset, even if a warm reset is already in progress. - overall, this change better matches what the hardware would do Change-Id: I36d30d176c0a03d97554112ca712d658d986c752
This commit is contained in:
parent
f75843d9d2
commit
f74d1dab7a
|
@ -96,6 +96,12 @@ struct bankd_worker {
|
|||
uint8_t atr[MAX_ATR_SIZE];
|
||||
unsigned int atr_len;
|
||||
} card;
|
||||
|
||||
/* last known state of the SIM card VCC indication */
|
||||
bool last_vccPresent;
|
||||
|
||||
/* last known state of the SIM card reset indication */
|
||||
bool last_resetActive;
|
||||
};
|
||||
|
||||
/* bankd card reader driver operations */
|
||||
|
|
|
@ -115,6 +115,8 @@ static struct bankd_worker *bankd_create_worker(struct bankd *bankd, unsigned in
|
|||
worker->bankd = bankd;
|
||||
worker->num = i;
|
||||
worker->ops = &pcsc_driver_ops;
|
||||
worker->last_vccPresent = true; /* allow cold reset should first indication be false */
|
||||
worker->last_resetActive = false; /* allow warm reset should first indication be true */
|
||||
|
||||
/* in the initial state, the worker has no client.fd, bank_slot or pcsc handle yet */
|
||||
|
||||
|
@ -774,10 +776,26 @@ static int worker_handle_clientSlotStatusInd(struct bankd_worker *worker, const
|
|||
sps->clkActive ? *sps->clkActive ? "ACTIVE" : "INACTIVE" : "NULL");
|
||||
|
||||
/* perform cold or warm reset */
|
||||
if (sps->vccPresent && *sps->vccPresent == 0)
|
||||
rc = worker->ops->reset_card(worker, true);
|
||||
else if (sps->resetActive)
|
||||
rc = worker->ops->reset_card(worker, false);
|
||||
if (sps->vccPresent && *sps->vccPresent == 0) {
|
||||
/* VCC is not present */
|
||||
|
||||
if (worker->last_vccPresent) {
|
||||
/* falling edge detected on VCC; perform cold reset */
|
||||
rc = worker->ops->reset_card(worker, true);
|
||||
}
|
||||
} else if (sps->resetActive) {
|
||||
if (!worker->last_resetActive) {
|
||||
/* VCC is present (or not reported) and rising edge detected on reset; perform warm reset */
|
||||
rc = worker->ops->reset_card(worker, false);
|
||||
}
|
||||
}
|
||||
|
||||
/* update last known states */
|
||||
if (sps->vccPresent) {
|
||||
worker->last_vccPresent = *sps->vccPresent != 0;
|
||||
}
|
||||
|
||||
worker->last_resetActive = sps->resetActive != 0;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue