bankd: Implement card reset based on clientSlotStatusInd
If a client is sending us a clientSlotStatusInd indicating that the modem has switched off VCC or activated RST, bankd will now issue a respective PC/SC command to perform a cold or warm reset of the card. Change-Id: Ifa615d239ec3ad6daebd8e99e4f7d5b99d32c0e1 Closes: OS#4330
This commit is contained in:
parent
0e0e932ce9
commit
bbd18bd7fe
|
@ -102,6 +102,8 @@ struct bankd_worker {
|
||||||
struct bankd_driver_ops {
|
struct bankd_driver_ops {
|
||||||
/* open a given card/slot: called once client + mapping exists */
|
/* open a given card/slot: called once client + mapping exists */
|
||||||
int (*open_card)(struct bankd_worker *worker);
|
int (*open_card)(struct bankd_worker *worker);
|
||||||
|
/* reset a given card/slot with either cold or warm reset */
|
||||||
|
int (*reset_card)(struct bankd_worker *worker, bool cold_reset);
|
||||||
int (*transceive)(struct bankd_worker *worker, const uint8_t *out, size_t out_len,
|
int (*transceive)(struct bankd_worker *worker, const uint8_t *out, size_t out_len,
|
||||||
uint8_t *in, size_t *in_len);
|
uint8_t *in, size_t *in_len);
|
||||||
/* called at cleanup time of a worker thread: clear any driver related state */
|
/* called at cleanup time of a worker thread: clear any driver related state */
|
||||||
|
|
|
@ -727,6 +727,26 @@ static int worker_handle_tpduModemToCard(struct bankd_worker *worker, const Rspr
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int worker_handle_clientSlotStatusInd(struct bankd_worker *worker, const RsproPDU_t *pdu)
|
||||||
|
{
|
||||||
|
const struct ClientSlotStatusInd *cssi = &pdu->msg.choice.clientSlotStatusInd;
|
||||||
|
const struct SlotPhysStatus *sps = &cssi->slotPhysStatus;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
LOGW(worker, "clientSlotStatusInd(RST=%s, VCC=%s, CLK=%s)\n",
|
||||||
|
sps->resetActive ? "ACTIVE" : "INACTIVE",
|
||||||
|
sps->vccPresent ? *sps->vccPresent ? "PRESENT" : "ABSENT" : "NULL",
|
||||||
|
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);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/* handle one incoming RSPRO message from a client inside a worker thread */
|
/* handle one incoming RSPRO message from a client inside a worker thread */
|
||||||
static int worker_handle_rspro(struct bankd_worker *worker, const RsproPDU_t *pdu)
|
static int worker_handle_rspro(struct bankd_worker *worker, const RsproPDU_t *pdu)
|
||||||
{
|
{
|
||||||
|
@ -742,7 +762,7 @@ static int worker_handle_rspro(struct bankd_worker *worker, const RsproPDU_t *pd
|
||||||
rc = worker_handle_tpduModemToCard(worker, pdu);
|
rc = worker_handle_tpduModemToCard(worker, pdu);
|
||||||
break;
|
break;
|
||||||
case RsproPDUchoice_PR_clientSlotStatusInd:
|
case RsproPDUchoice_PR_clientSlotStatusInd:
|
||||||
/* FIXME */
|
rc = worker_handle_clientSlotStatusInd(worker, pdu);
|
||||||
rc = 0;
|
rc = 0;
|
||||||
break;
|
break;
|
||||||
case RsproPDUchoice_PR_setAtrRes:
|
case RsproPDUchoice_PR_setAtrRes:
|
||||||
|
|
|
@ -152,6 +152,24 @@ if (rv != SCARD_S_SUCCESS) { \
|
||||||
LOGW((w), ": OK\n"); \
|
LOGW((w), ": OK\n"); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int pcsc_get_atr(struct bankd_worker *worker)
|
||||||
|
{
|
||||||
|
long rc;
|
||||||
|
char pbReader[MAX_READERNAME];
|
||||||
|
/* use DWORD type as this is what the PC/SC API expects */
|
||||||
|
DWORD dwReaderLen = sizeof(pbReader);
|
||||||
|
DWORD dwAtrLen = worker->card.atr_len = sizeof(worker->card.atr);
|
||||||
|
DWORD dwState, dwProt;
|
||||||
|
|
||||||
|
rc = SCardStatus(worker->reader.pcsc.hCard, pbReader, &dwReaderLen, &dwState, &dwProt,
|
||||||
|
worker->card.atr, &dwAtrLen);
|
||||||
|
PCSC_ERROR(worker, rc, "SCardStatus")
|
||||||
|
worker->card.atr_len = dwAtrLen;
|
||||||
|
LOGW(worker, "Card ATR: %s\n", osmo_hexdump_nospc(worker->card.atr, worker->card.atr_len));
|
||||||
|
end:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static int pcsc_open_card(struct bankd_worker *worker)
|
static int pcsc_open_card(struct bankd_worker *worker)
|
||||||
{
|
{
|
||||||
long rc;
|
long rc;
|
||||||
|
@ -171,16 +189,23 @@ static int pcsc_open_card(struct bankd_worker *worker)
|
||||||
PCSC_ERROR(worker, rc, "SCardConnect")
|
PCSC_ERROR(worker, rc, "SCardConnect")
|
||||||
}
|
}
|
||||||
|
|
||||||
/* use DWORD type as this is what the PC/SC API expects */
|
rc = pcsc_get_atr(worker);
|
||||||
char pbReader[MAX_READERNAME];
|
end:
|
||||||
DWORD dwReaderLen = sizeof(pbReader);
|
return rc;
|
||||||
DWORD dwAtrLen = worker->card.atr_len = sizeof(worker->card.atr);
|
}
|
||||||
DWORD dwState, dwProt;
|
|
||||||
rc = SCardStatus(worker->reader.pcsc.hCard, pbReader, &dwReaderLen, &dwState, &dwProt,
|
static int pcsc_reset_card(struct bankd_worker *worker, bool cold_reset)
|
||||||
worker->card.atr, &dwAtrLen);
|
{
|
||||||
PCSC_ERROR(worker, rc, "SCardStatus")
|
long rc;
|
||||||
worker->card.atr_len = dwAtrLen;
|
DWORD dwActiveProtocol;
|
||||||
LOGW(worker, "Card ATR: %s\n", osmo_hexdump_nospc(worker->card.atr, worker->card.atr_len));
|
|
||||||
|
LOGW(worker, "Resetting card in '%s' (%s)\n", worker->reader.name,
|
||||||
|
cold_reset ? "cold reset" : "warm reset");
|
||||||
|
rc = SCardReconnect(worker->reader.pcsc.hCard, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0,
|
||||||
|
cold_reset ? SCARD_UNPOWER_CARD : SCARD_RESET_CARD, &dwActiveProtocol);
|
||||||
|
PCSC_ERROR(worker, rc, "SCardReconnect");
|
||||||
|
|
||||||
|
rc = pcsc_get_atr(worker);
|
||||||
end:
|
end:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -213,6 +238,7 @@ static void pcsc_cleanup(struct bankd_worker *worker)
|
||||||
|
|
||||||
const struct bankd_driver_ops pcsc_driver_ops = {
|
const struct bankd_driver_ops pcsc_driver_ops = {
|
||||||
.open_card = pcsc_open_card,
|
.open_card = pcsc_open_card,
|
||||||
|
.reset_card = pcsc_reset_card,
|
||||||
.transceive = pcsc_transceive,
|
.transceive = pcsc_transceive,
|
||||||
.cleanup = pcsc_cleanup,
|
.cleanup = pcsc_cleanup,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue