bankd: Move all PC/SC specific code to bankd_pcsc
Change-Id: I435b42982b54d74447c435dcefa26d1e317d15e0
This commit is contained in:
parent
1f699b405a
commit
297d72ef47
19
src/bankd.h
19
src/bankd.h
|
@ -17,6 +17,12 @@
|
|||
#include "client.h"
|
||||
#include "debug.h"
|
||||
|
||||
extern struct value_string worker_state_names[];
|
||||
|
||||
#define LOGW(w, fmt, args...) \
|
||||
printf("[%03u %s] %s:%u " fmt, (w)->num, get_value_string(worker_state_names, (w)->state), \
|
||||
__FILE__, __LINE__, ## args)
|
||||
|
||||
struct bankd;
|
||||
|
||||
enum bankd_worker_state {
|
||||
|
@ -64,6 +70,8 @@ struct bankd_worker {
|
|||
/* top talloc context for this worker/thread */
|
||||
void *tall_ctx;
|
||||
|
||||
const struct bankd_driver_ops *ops;
|
||||
|
||||
/* File descriptor of the TCP connection to the remsim-client (modem) */
|
||||
struct {
|
||||
int fd;
|
||||
|
@ -90,6 +98,15 @@ struct bankd_worker {
|
|||
} card;
|
||||
};
|
||||
|
||||
/* bankd card reader driver operations */
|
||||
struct bankd_driver_ops {
|
||||
/* open a given card/slot: called once client + mapping exists */
|
||||
int (*open_card)(struct bankd_worker *worker);
|
||||
int (*transceive)(struct bankd_worker *worker, const uint8_t *out, size_t out_len,
|
||||
uint8_t *in, size_t *in_len);
|
||||
/* called at cleanup time of a worker thread: clear any driver related state */
|
||||
void (*cleanup)(struct bankd_worker *worker);
|
||||
};
|
||||
|
||||
/* global bank deamon */
|
||||
struct bankd {
|
||||
|
@ -120,3 +137,5 @@ struct bankd {
|
|||
|
||||
int bankd_pcsc_read_slotnames(struct bankd *bankd, const char *csv_file);
|
||||
const char *bankd_pcsc_get_slot_name(struct bankd *bankd, const struct bank_slot *slot);
|
||||
|
||||
extern const struct bankd_driver_ops pcsc_driver_ops;
|
||||
|
|
|
@ -31,10 +31,6 @@
|
|||
|
||||
#include <pthread.h>
|
||||
|
||||
#include <wintypes.h>
|
||||
#include <winscard.h>
|
||||
#include <pcsclite.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
|
||||
|
@ -113,6 +109,7 @@ static struct bankd_worker *bankd_create_worker(struct bankd *bankd, unsigned in
|
|||
|
||||
worker->bankd = bankd;
|
||||
worker->num = i;
|
||||
worker->ops = &pcsc_driver_ops;
|
||||
|
||||
/* in the initial state, the worker has no client.fd, bank_slot or pcsc handle yet */
|
||||
|
||||
|
@ -299,18 +296,6 @@ struct value_string worker_state_names[] = {
|
|||
{ 0, NULL }
|
||||
};
|
||||
|
||||
#define LOGW(w, fmt, args...) \
|
||||
printf("[%03u %s] %s:%u " fmt, (w)->num, get_value_string(worker_state_names, (w)->state), \
|
||||
__FILE__, __LINE__, ## args)
|
||||
|
||||
#define PCSC_ERROR(w, rv, text) \
|
||||
if (rv != SCARD_S_SUCCESS) { \
|
||||
LOGW((w), text ": %s (0x%lX)\n", pcsc_stringify_error(rv), rv); \
|
||||
goto end; \
|
||||
} else { \
|
||||
LOGW((w), ": OK\n"); \
|
||||
}
|
||||
|
||||
static int worker_send_rspro(struct bankd_worker *worker, RsproPDU_t *pdu);
|
||||
|
||||
static void worker_set_state(struct bankd_worker *worker, enum bankd_worker_state new_state)
|
||||
|
@ -372,10 +357,9 @@ static void worker_cleanup(void *arg)
|
|||
pthread_mutex_unlock(&bankd->workers_mutex);
|
||||
}
|
||||
|
||||
|
||||
static int worker_open_card(struct bankd_worker *worker)
|
||||
{
|
||||
long rc;
|
||||
int rc;
|
||||
|
||||
OSMO_ASSERT(worker->state == BW_ST_CONN_CLIENT_MAPPED);
|
||||
|
||||
|
@ -385,44 +369,19 @@ static int worker_open_card(struct bankd_worker *worker)
|
|||
if (!worker->reader.name) {
|
||||
LOGW(worker, "No PC/SC reader name configured for %u/%u, fix your config\n",
|
||||
worker->slot.bank_id, worker->slot.slot_nr);
|
||||
rc = -1;
|
||||
goto end;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
OSMO_ASSERT(worker->reader.name);
|
||||
|
||||
if (!worker->reader.pcsc.hContext) {
|
||||
LOGW(worker, "Attempting to open PC/SC context\n");
|
||||
/* The PC/SC context must be created inside the thread where we'll later use it */
|
||||
rc = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &worker->reader.pcsc.hContext);
|
||||
PCSC_ERROR(worker, rc, "SCardEstablishContext")
|
||||
}
|
||||
|
||||
if (!worker->reader.pcsc.hCard) {
|
||||
LOGW(worker, "Attempting to open card/slot '%s'\n", worker->reader.name);
|
||||
DWORD dwActiveProtocol;
|
||||
rc = SCardConnect(worker->reader.pcsc.hContext, worker->reader.name, SCARD_SHARE_SHARED,
|
||||
SCARD_PROTOCOL_T0, &worker->reader.pcsc.hCard, &dwActiveProtocol);
|
||||
PCSC_ERROR(worker, rc, "SCardConnect")
|
||||
}
|
||||
|
||||
/* use DWORD type as this is what the PC/SC API expects */
|
||||
char pbReader[MAX_READERNAME];
|
||||
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));
|
||||
rc = worker->ops->open_card(worker);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
worker_set_state(worker, BW_ST_CONN_CLIENT_MAPPED_CARD);
|
||||
/* FIXME: notify client about this state change */
|
||||
|
||||
return 0;
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
@ -588,14 +547,12 @@ respond_and_err:
|
|||
static int worker_handle_tpduModemToCard(struct bankd_worker *worker, const RsproPDU_t *pdu)
|
||||
{
|
||||
const struct TpduModemToCard *mdm2sim = &pdu->msg.choice.tpduModemToCard;
|
||||
const SCARD_IO_REQUEST *pioSendPci = SCARD_PCI_T0;
|
||||
SCARD_IO_REQUEST pioRecvPci;
|
||||
uint8_t rx_buf[1024];
|
||||
DWORD rx_buf_len = sizeof(rx_buf);
|
||||
RsproPDU_t *pdu_resp;
|
||||
struct client_slot clslot;
|
||||
struct bank_slot bslot;
|
||||
long rc;
|
||||
int rc;
|
||||
|
||||
LOGW(worker, "tpduModemToCard(%s)\n", osmo_hexdump_nospc(mdm2sim->data.buf, mdm2sim->data.size));
|
||||
|
||||
|
@ -618,10 +575,10 @@ static int worker_handle_tpduModemToCard(struct bankd_worker *worker, const Rspr
|
|||
return -106;
|
||||
}
|
||||
|
||||
rc = SCardTransmit(worker->reader.pcsc.hCard,
|
||||
pioSendPci, mdm2sim->data.buf, mdm2sim->data.size,
|
||||
&pioRecvPci, rx_buf, &rx_buf_len);
|
||||
PCSC_ERROR(worker, rc, "SCardTransmit");
|
||||
rc = worker->ops->transceive(worker, mdm2sim->data.buf, mdm2sim->data.size,
|
||||
rx_buf, &rx_buf_len);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
/* encode response PDU and send it */
|
||||
pdu_resp = rspro_gen_TpduCard2Modem(&mdm2sim->toBankSlot, &mdm2sim->fromClientSlot,
|
||||
|
@ -629,8 +586,6 @@ static int worker_handle_tpduModemToCard(struct bankd_worker *worker, const Rspr
|
|||
worker_send_rspro(worker, pdu_resp);
|
||||
|
||||
return 0;
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* handle one incoming RSPRO message from a client inside a worker thread */
|
||||
|
@ -828,14 +783,7 @@ static void *worker_main(void *arg)
|
|||
|
||||
/* clean-up: reset to sane state */
|
||||
memset(&g_worker->card, 0, sizeof(g_worker->card));
|
||||
if (g_worker->reader.pcsc.hCard) {
|
||||
SCardDisconnect(g_worker->reader.pcsc.hCard, SCARD_UNPOWER_CARD);
|
||||
g_worker->reader.pcsc.hCard = 0;
|
||||
}
|
||||
if (g_worker->reader.pcsc.hContext) {
|
||||
SCardReleaseContext(g_worker->reader.pcsc.hContext);
|
||||
g_worker->reader.pcsc.hContext = 0;
|
||||
}
|
||||
g_worker->ops->cleanup(g_worker);
|
||||
if (g_worker->reader.name)
|
||||
g_worker->reader.name = NULL;
|
||||
if (g_worker->client.fd >= 0)
|
||||
|
|
|
@ -138,3 +138,81 @@ const char *bankd_pcsc_get_slot_name(struct bankd *bankd, const struct bank_slot
|
|||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
#include <wintypes.h>
|
||||
#include <winscard.h>
|
||||
#include <pcsclite.h>
|
||||
|
||||
#define PCSC_ERROR(w, rv, text) \
|
||||
if (rv != SCARD_S_SUCCESS) { \
|
||||
LOGW((w), text ": %s (0x%lX)\n", pcsc_stringify_error(rv), rv); \
|
||||
goto end; \
|
||||
} else { \
|
||||
LOGW((w), ": OK\n"); \
|
||||
}
|
||||
|
||||
static int pcsc_open_card(struct bankd_worker *worker)
|
||||
{
|
||||
long rc;
|
||||
|
||||
if (!worker->reader.pcsc.hContext) {
|
||||
LOGW(worker, "Attempting to open PC/SC context\n");
|
||||
/* The PC/SC context must be created inside the thread where we'll later use it */
|
||||
rc = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &worker->reader.pcsc.hContext);
|
||||
PCSC_ERROR(worker, rc, "SCardEstablishContext")
|
||||
}
|
||||
|
||||
if (!worker->reader.pcsc.hCard) {
|
||||
LOGW(worker, "Attempting to open card/slot '%s'\n", worker->reader.name);
|
||||
DWORD dwActiveProtocol;
|
||||
rc = SCardConnect(worker->reader.pcsc.hContext, worker->reader.name, SCARD_SHARE_SHARED,
|
||||
SCARD_PROTOCOL_T0, &worker->reader.pcsc.hCard, &dwActiveProtocol);
|
||||
PCSC_ERROR(worker, rc, "SCardConnect")
|
||||
}
|
||||
|
||||
/* use DWORD type as this is what the PC/SC API expects */
|
||||
char pbReader[MAX_READERNAME];
|
||||
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_transceive(struct bankd_worker *worker, const uint8_t *out, size_t out_len,
|
||||
uint8_t *in, size_t *in_len)
|
||||
{
|
||||
const SCARD_IO_REQUEST *pioSendPci = SCARD_PCI_T0;
|
||||
SCARD_IO_REQUEST pioRecvPci;
|
||||
long rc;
|
||||
|
||||
rc = SCardTransmit(worker->reader.pcsc.hCard, pioSendPci, out, out_len, &pioRecvPci, in, in_len);
|
||||
PCSC_ERROR(worker, rc, "SCardTransmit");
|
||||
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void pcsc_cleanup(struct bankd_worker *worker)
|
||||
{
|
||||
if (worker->reader.pcsc.hCard) {
|
||||
SCardDisconnect(worker->reader.pcsc.hCard, SCARD_UNPOWER_CARD);
|
||||
worker->reader.pcsc.hCard = 0;
|
||||
}
|
||||
if (worker->reader.pcsc.hContext) {
|
||||
SCardReleaseContext(worker->reader.pcsc.hContext);
|
||||
worker->reader.pcsc.hContext = 0;
|
||||
}
|
||||
}
|
||||
|
||||
const struct bankd_driver_ops pcsc_driver_ops = {
|
||||
.open_card = pcsc_open_card,
|
||||
.transceive = pcsc_transceive,
|
||||
.cleanup = pcsc_cleanup,
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
"1","0","ACS ACR33 ICC Reader 01 00"
|
||||
"1","1","ACS ACR33 ICC Reader 01 01"
|
||||
"1","2","ACS ACR33 ICC Reader 01 02"
|
||||
"1","3","ACS ACR33 ICC Reader 01 03"
|
||||
"1","4","ACS ACR33 ICC Reader 01 04"
|
||||
"1","0","ACS ACR33 ICC Reader 00 00"
|
||||
"1","1","ACS ACR33 ICC Reader 00 01"
|
||||
"1","2","ACS ACR33 ICC Reader 00 02"
|
||||
"1","3","ACS ACR33 ICC Reader 00 03"
|
||||
"1","4","ACS ACR33 ICC Reader 00 04"
|
||||
"1","23","Alcor Micro AU9560 00 00"
|
||||
|
|
|
Loading…
Reference in New Issue