bankd_pcsc: Add CSV based mapping of bank-id/slot-nr to PC/SC reader name
In the PC/SC world, each slot is associated with a string name. In the bankd for PC/SC readers, we need to establish a mapping which bank_id/slot_nr maps to which given string name. We use a minimalistic CSV file for defining those mappings. The file is read only once at bankd startup time. Change-Id: Ifd2caab670625e2e3fbc57b966dce2f43b690417
This commit is contained in:
parent
1266952242
commit
45c948cc10
|
@ -19,9 +19,9 @@ pcsc_test_SOURCES = driver_core.c driver_pcsc.c main.c
|
|||
pcsc_test_LDADD = $(OSMOCORE_LIBS) \
|
||||
$(ASN1C_LIBS) $(PCSC_LIBS) libosmo-rspro.la
|
||||
|
||||
remsim_bankd_SOURCES = bankd_slotmap.c bankd_main.c
|
||||
remsim_bankd_LDADD = $(OSMOCORE_LIBS) \
|
||||
$(ASN1C_LIBS) $(PCSC_LIBS) libosmo-rspro.la
|
||||
remsim_bankd_SOURCES = bankd_slotmap.c bankd_main.c bankd_pcsc.c
|
||||
remsim_bankd_LDADD = $(OSMOCORE_LIBS) $(OSMOGSM_LIBS) \
|
||||
$(ASN1C_LIBS) $(PCSC_LIBS) libosmo-rspro.la -lcsv
|
||||
|
||||
remsim_client_SOURCES = remsim_client.c remsim_client_fsm.c
|
||||
remsim_client_LDADD = $(OSMOCORE_LIBS) $(OSMOGSM_LIBS) $(OSMOABIS_LIBS) \
|
||||
|
|
|
@ -138,4 +138,9 @@ struct bankd {
|
|||
/* list of bankd_workers. accessed/modified by multiple threads; protected by mutex */
|
||||
struct llist_head workers;
|
||||
pthread_mutex_t workers_mutex;
|
||||
|
||||
struct llist_head pcsc_slot_names;
|
||||
};
|
||||
|
||||
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);
|
||||
|
|
|
@ -38,6 +38,12 @@ static void bankd_init(struct bankd *bankd)
|
|||
pthread_rwlock_init(&bankd->slot_mappings_rwlock, NULL);
|
||||
INIT_LLIST_HEAD(&bankd->workers);
|
||||
pthread_mutex_init(&bankd->workers_mutex, NULL);
|
||||
|
||||
/* Np lock or mutex required for the pcsc_slot_names list, as this is only
|
||||
* read once during bankd initialization, when the worker threads haven't
|
||||
* started yet */
|
||||
INIT_LLIST_HEAD(&bankd->pcsc_slot_names);
|
||||
OSMO_ASSERT(bankd_pcsc_read_slotnames(bankd, "bankd_pcsc_slots.csv") == 0);
|
||||
}
|
||||
|
||||
/* create + start a new bankd_worker thread */
|
||||
|
@ -154,6 +160,12 @@ static int worker_open_card(struct bankd_worker *worker)
|
|||
{
|
||||
long rc;
|
||||
|
||||
/* resolve PC/SC reader name from slot_id -> name map */
|
||||
worker->reader.name = bankd_pcsc_get_slot_name(worker->bankd, &worker->slot);
|
||||
OSMO_ASSERT(worker->reader.name);
|
||||
|
||||
LOGW(worker, "Attempting to open card/slot '%s'\n", worker->reader.name);
|
||||
|
||||
/* 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")
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/core/utils.h>
|
||||
|
||||
#include <csv.h>
|
||||
|
||||
#include "bankd.h"
|
||||
|
||||
struct pcsc_slot_name {
|
||||
struct llist_head list;
|
||||
/* RSPRO bank slot number */
|
||||
struct bank_slot slot;
|
||||
/* String name of the reader in PC/SC world */
|
||||
const char *name;
|
||||
};
|
||||
|
||||
enum parser_state_name {
|
||||
ST_NONE,
|
||||
ST_BANK_NR,
|
||||
ST_SLOT_NR,
|
||||
ST_PCSC_NAME,
|
||||
};
|
||||
struct parser_state {
|
||||
struct bankd *bankd;
|
||||
enum parser_state_name state;
|
||||
struct pcsc_slot_name *cur;
|
||||
};
|
||||
|
||||
|
||||
static void parser_state_init(struct parser_state *ps)
|
||||
{
|
||||
ps->state = ST_BANK_NR;
|
||||
ps->cur = NULL;
|
||||
}
|
||||
|
||||
static void cb1(void *s, size_t len, void *data)
|
||||
{
|
||||
char *field = (char *) s;
|
||||
struct parser_state *ps = data;
|
||||
|
||||
switch (ps->state) {
|
||||
case ST_BANK_NR:
|
||||
OSMO_ASSERT(!ps->cur);
|
||||
ps->cur = talloc_zero(ps->bankd, struct pcsc_slot_name);
|
||||
OSMO_ASSERT(ps->cur);
|
||||
ps->cur->slot.bank_id = atoi(field);
|
||||
ps->state = ST_SLOT_NR;
|
||||
break;
|
||||
case ST_SLOT_NR:
|
||||
OSMO_ASSERT(ps->cur);
|
||||
ps->cur->slot.slot_nr = atoi(field);
|
||||
ps->state = ST_PCSC_NAME;
|
||||
break;
|
||||
case ST_PCSC_NAME:
|
||||
OSMO_ASSERT(ps->cur);
|
||||
ps->cur->name = talloc_strdup(ps->cur, field);
|
||||
break;
|
||||
default:
|
||||
OSMO_ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void cb2(int c, void *data)
|
||||
{
|
||||
struct parser_state *ps = data;
|
||||
struct pcsc_slot_name *sn = ps->cur;
|
||||
|
||||
printf("PC/SC slot name: %u/%u -> '%s'\n", sn->slot.bank_id, sn->slot.slot_nr, sn->name);
|
||||
llist_add_tail(&sn->list, &ps->bankd->pcsc_slot_names);
|
||||
|
||||
ps->state = ST_BANK_NR;
|
||||
ps->cur = NULL;
|
||||
}
|
||||
|
||||
int bankd_pcsc_read_slotnames(struct bankd *bankd, const char *csv_file)
|
||||
{
|
||||
FILE *fp;
|
||||
struct csv_parser p;
|
||||
char buf[1024];
|
||||
size_t bytes_read;
|
||||
struct parser_state ps;
|
||||
|
||||
if (csv_init(&p, CSV_APPEND_NULL) != 0)
|
||||
return -1;
|
||||
|
||||
fp = fopen(csv_file, "rb");
|
||||
if (!fp)
|
||||
return -1;
|
||||
|
||||
parser_state_init(&ps);
|
||||
ps.bankd = bankd;
|
||||
|
||||
while ((bytes_read = fread(buf, 1, sizeof(buf), fp)) > 0) {
|
||||
if (csv_parse(&p, buf, bytes_read, cb1, cb2, &ps) != bytes_read) {
|
||||
fprintf(stderr, "Error parsing CSV: %s\n", csv_strerror(csv_error(&p)));
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
csv_fini(&p, cb1, cb2, &ps);
|
||||
fclose(fp);
|
||||
csv_free(&p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *bankd_pcsc_get_slot_name(struct bankd *bankd, const struct bank_slot *slot)
|
||||
{
|
||||
struct pcsc_slot_name *cur;
|
||||
|
||||
llist_for_each_entry(cur, &bankd->pcsc_slot_names, list) {
|
||||
if (bank_slot_equals(&cur->slot, slot))
|
||||
return cur->name;
|
||||
}
|
||||
return NULL;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
"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