From 55790aa09a8f92d437ea06b3ef2c74465612fa8b Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 26 Oct 2014 18:46:50 +0100 Subject: [PATCH] sim: Prepare infrastructure for protocols != T=0 and other drivers --- include/osmocom/sim/sim.h | 19 ++++++++++++++-- src/sim/reader.c | 48 +++++++++++++++++++++++++++------------ src/sim/reader_pcsc.c | 6 ++++- src/sim/sim_int.h | 2 +- utils/osmo-sim-test.c | 4 ++-- 5 files changed, 59 insertions(+), 20 deletions(-) diff --git a/include/osmocom/sim/sim.h b/include/osmocom/sim/sim.h index 4c47afc41..d68d7c2c7 100644 --- a/include/osmocom/sim/sim.h +++ b/include/osmocom/sim/sim.h @@ -320,10 +320,22 @@ struct msgb *osim_new_apdumsg(uint8_t cla, uint8_t ins, uint8_t p1, struct osim_reader_ops; +enum osim_proto { + OSIM_PROTO_T0 = 0, + OSIM_PROTO_T1 = 1, +}; + +enum osim_reader_driver { + OSIM_READER_DRV_PCSC = 0, + OSIM_READER_DRV_OPENCT = 1, + OSIM_READER_DRV_SERIAL = 2, +}; + struct osim_reader_hdl { /*! \brief member in global list of readers */ struct llist_head list; struct osim_reader_ops *ops; + uint32_t proto_supported; void *priv; /*! \brief current card, if any */ struct osim_card_hdl *card; @@ -336,6 +348,8 @@ struct osim_card_hdl { struct osim_reader_hdl *reader; /*! \brief card profile */ struct osim_card_profile *prof; + /*! \brief card protocol */ + enum osim_proto proto; /*! \brief list of channels for this card */ struct llist_head channels; @@ -351,6 +365,7 @@ struct osim_chan_hdl { /* reader.c */ int osim_transceive_apdu(struct osim_chan_hdl *st, struct msgb *amsg); -struct osim_reader_hdl *osim_reader_open(int idx, const char *name, void *ctx); -struct osim_card_hdl *osim_card_open(struct osim_reader_hdl *rh); +struct osim_reader_hdl *osim_reader_open(enum osim_reader_driver drv, int idx, + const char *name, void *ctx); +struct osim_card_hdl *osim_card_open(struct osim_reader_hdl *rh, enum osim_proto proto); #endif /* _OSMOCOM_SIM_H */ diff --git a/src/sim/reader.c b/src/sim/reader.c index 4f72dd0f4..160f1758a 100644 --- a/src/sim/reader.c +++ b/src/sim/reader.c @@ -217,35 +217,55 @@ case_2s: return sw; } -/* According to ISO7816-4 Annex B */ -static int transceive_apdu_t1(struct osim_card_hdl *st, struct msgb *amsg) -{ - return -1; -} +/* FIXME: T=1 According to ISO7816-4 Annex B */ int osim_transceive_apdu(struct osim_chan_hdl *st, struct msgb *amsg) { - /* FIXME: check for protocol */ - return transceive_apdu_t0(st->card, amsg); + switch (st->card->proto) { + case OSIM_PROTO_T0: + return transceive_apdu_t0(st->card, amsg); + default: + return -ENOTSUP; + } } - - -struct osim_reader_hdl *osim_reader_open(int idx, const char *name, void *ctx) +struct osim_reader_hdl *osim_reader_open(enum osim_reader_driver driver, int idx, + const char *name, void *ctx) { - /* FIXME: support multiple drivers */ - const struct osim_reader_ops *ops = &pcsc_reader_ops; + const struct osim_reader_ops *ops; struct osim_reader_hdl *rh; + switch (driver) { + case OSIM_READER_DRV_PCSC: + ops = &pcsc_reader_ops; + break; + default: + return NULL; + } + rh = ops->reader_open(idx, name, ctx); if (!rh) return NULL; rh->ops = ops; + /* FIXME: for now we only do T=0 on all readers */ + rh->proto_supported = (1 << OSIM_PROTO_T0); + return rh; } -struct osim_card_hdl *osim_card_open(struct osim_reader_hdl *rh) +struct osim_card_hdl *osim_card_open(struct osim_reader_hdl *rh, enum osim_proto proto) { - return rh->ops->card_open(rh); + struct osim_card_hdl *ch; + + if (!(rh->proto_supported & (1 << proto))) + return NULL; + + ch = rh->ops->card_open(rh, proto); + if (!ch) + return NULL; + + ch->proto = proto; + + return ch; } diff --git a/src/sim/reader_pcsc.c b/src/sim/reader_pcsc.c index c5b8112b3..5e670912b 100644 --- a/src/sim/reader_pcsc.c +++ b/src/sim/reader_pcsc.c @@ -97,13 +97,17 @@ end: return NULL; } -static struct osim_card_hdl *pcsc_card_open(struct osim_reader_hdl *rh) +static struct osim_card_hdl *pcsc_card_open(struct osim_reader_hdl *rh, + enum osim_proto proto) { struct pcsc_reader_state *st = rh->priv; struct osim_card_hdl *card; struct osim_chan_hdl *chan; LONG rc; + if (proto != OSIM_PROTO_T0) + return NULL; + rc = SCardConnect(st->hContext, st->name, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &st->hCard, &st->dwActiveProtocol); PCSC_ERROR(rc, "SCardConnect"); diff --git a/src/sim/sim_int.h b/src/sim/sim_int.h index 0a3772bc2..c10c5f080 100644 --- a/src/sim/sim_int.h +++ b/src/sim/sim_int.h @@ -32,7 +32,7 @@ add_adf_with_ef(struct osim_file_desc *parent, struct osim_reader_ops { const char *name; struct osim_reader_hdl *(*reader_open)(int idx, const char *name, void *ctx); - struct osim_card_hdl *(*card_open)(struct osim_reader_hdl *rh); + struct osim_card_hdl *(*card_open)(struct osim_reader_hdl *rh, enum osim_proto proto); int (*transceive)(struct osim_reader_hdl *rh, struct msgb *msg); }; diff --git a/utils/osmo-sim-test.c b/utils/osmo-sim-test.c index 3acbd71d1..244c2df35 100644 --- a/utils/osmo-sim-test.c +++ b/utils/osmo-sim-test.c @@ -374,10 +374,10 @@ int main(int argc, char **argv) struct msgb *msg; int rc; - reader = osim_reader_open(0, "", NULL); + reader = osim_reader_open(OSIM_READER_DRV_PCSC, 0, "", NULL); if (!reader) exit(1); - card = osim_card_open(reader); + card = osim_card_open(reader, OSIM_PROTO_T0); if (!card) exit(2); chan = llist_entry(card->channels.next, struct osim_chan_hdl, list);