bankd: Move all PC/SC specific code to bankd_pcsc
Change-Id: I435b42982b54d74447c435dcefa26d1e317d15e0
diff --git a/src/bankd.h b/src/bankd.h
index 6d4f675..d56734c 100644
--- a/src/bankd.h
+++ b/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 @@
/* 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 @@
} 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 @@
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;
diff --git a/src/bankd_main.c b/src/bankd_main.c
index c18a280..cb78718 100644
--- a/src/bankd_main.c
+++ b/src/bankd_main.c
@@ -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 @@
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 @@
{ 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
/* 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)
diff --git a/src/bankd_pcsc.c b/src/bankd_pcsc.c
index 671c6bf..a390782 100644
--- a/src/bankd_pcsc.c
+++ b/src/bankd_pcsc.c
@@ -138,3 +138,81 @@
}
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,
+};
diff --git a/src/bankd_pcsc_slots.csv b/src/bankd_pcsc_slots.csv
index 32fc574..38a22c9 100644
--- a/src/bankd_pcsc_slots.csv
+++ b/src/bankd_pcsc_slots.csv
@@ -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"