Signed-off-by: Anthony Liguori <aligu...@us.ibm.com> --- hw/ccid-card-emulated.c | 27 ++++++++++------ hw/ccid-card-passthru.c | 27 ++++++++++------ hw/ccid.h | 28 +++++++++++------ hw/usb-ccid.c | 76 +++++++++++++++++++++++++++++++++++------------ 4 files changed, 109 insertions(+), 49 deletions(-)
diff --git a/hw/ccid-card-emulated.c b/hw/ccid-card-emulated.c index 2d2ebce..6dabe7a 100644 --- a/hw/ccid-card-emulated.c +++ b/hw/ccid-card-emulated.c @@ -564,16 +564,23 @@ static int emulated_exitfn(CCIDCardState *base) return 0; } -static CCIDCardInfo emulated_card_info = { - .qdev.name = EMULATED_DEV_NAME, - .qdev.desc = "emulated smartcard", - .qdev.size = sizeof(EmulatedState), - .initfn = emulated_initfn, - .exitfn = emulated_exitfn, - .get_atr = emulated_get_atr, - .apdu_from_guest = emulated_apdu_from_guest, - .qdev.unplug = qdev_simple_unplug_cb, - .qdev.props = (Property[]) { +static void emulated_class_initfn(ObjectClass *klass, void *data) +{ + CCIDCardClass *cc = CCID_CARD_CLASS(klass); + + cc->initfn = emulated_initfn; + cc->exitfn = emulated_exitfn; + cc->get_atr = emulated_get_atr; + cc->apdu_from_guest = emulated_apdu_from_guest; +} + +static DeviceInfo emulated_card_info = { + .name = EMULATED_DEV_NAME, + .desc = "emulated smartcard", + .size = sizeof(EmulatedState), + .unplug = qdev_simple_unplug_cb, + .class_init = emulated_class_initfn, + .props = (Property[]) { DEFINE_PROP_STRING("backend", EmulatedState, backend_str), DEFINE_PROP_STRING("cert1", EmulatedState, cert1), DEFINE_PROP_STRING("cert2", EmulatedState, cert2), diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c index 9f51c6c..f563d97 100644 --- a/hw/ccid-card-passthru.c +++ b/hw/ccid-card-passthru.c @@ -316,16 +316,23 @@ static VMStateDescription passthru_vmstate = { } }; -static CCIDCardInfo passthru_card_info = { - .qdev.name = PASSTHRU_DEV_NAME, - .qdev.desc = "passthrough smartcard", - .qdev.size = sizeof(PassthruState), - .qdev.vmsd = &passthru_vmstate, - .initfn = passthru_initfn, - .exitfn = passthru_exitfn, - .get_atr = passthru_get_atr, - .apdu_from_guest = passthru_apdu_from_guest, - .qdev.props = (Property[]) { +static void passthru_class_initfn(ObjectClass *klass, void *data) +{ + CCIDCardClass *cc = CCID_CARD_CLASS(klass); + + cc->initfn = passthru_initfn; + cc->exitfn = passthru_exitfn; + cc->get_atr = passthru_get_atr; + cc->apdu_from_guest = passthru_apdu_from_guest; +} + +static DeviceInfo passthru_card_info = { + .name = PASSTHRU_DEV_NAME, + .desc = "passthrough smartcard", + .size = sizeof(PassthruState), + .vmsd = &passthru_vmstate, + .class_init = passthru_class_initfn, + .props = (Property[]) { DEFINE_PROP_CHR("chardev", PassthruState, cs), DEFINE_PROP_UINT8("debug", PassthruState, debug, 0), DEFINE_PROP_END_OF_LIST(), diff --git a/hw/ccid.h b/hw/ccid.h index 9e3abe1..9e4979c 100644 --- a/hw/ccid.h +++ b/hw/ccid.h @@ -15,26 +15,34 @@ typedef struct CCIDCardState CCIDCardState; typedef struct CCIDCardInfo CCIDCardInfo; -/* - * state of the CCID Card device (i.e. hw/ccid-card-*.c) - */ -struct CCIDCardState { - DeviceState qdev; - uint32_t slot; /* For future use with multiple slot reader. */ -}; +#define TYPE_CCID_CARD "ccid-card" +#define CCID_CARD(obj) \ + OBJECT_CHECK(CCIDCardState, (obj), TYPE_CCID_CARD) +#define CCID_CARD_CLASS(klass) \ + OBJECT_CLASS_CHECK(CCIDCardClass, (klass), TYPE_CCID_CARD) +#define CCID_CARD_GET_CLASS(obj) \ + OBJECT_GET_CLASS(CCIDCardClass, (obj), TYPE_CCID_CARD) /* * callbacks to be used by the CCID device (hw/usb-ccid.c) to call * into the smartcard device (hw/ccid-card-*.c) */ -struct CCIDCardInfo { - DeviceInfo qdev; +typedef struct CCIDCardClass { + DeviceClass parent_class; const uint8_t *(*get_atr)(CCIDCardState *card, uint32_t *len); void (*apdu_from_guest)(CCIDCardState *card, const uint8_t *apdu, uint32_t len); int (*exitfn)(CCIDCardState *card); int (*initfn)(CCIDCardState *card); +} CCIDCardClass; + +/* + * state of the CCID Card device (i.e. hw/ccid-card-*.c) + */ +struct CCIDCardState { + DeviceState qdev; + uint32_t slot; /* For future use with multiple slot reader. */ }; /* @@ -46,7 +54,7 @@ void ccid_card_send_apdu_to_guest(CCIDCardState *card, void ccid_card_card_removed(CCIDCardState *card); void ccid_card_card_inserted(CCIDCardState *card); void ccid_card_card_error(CCIDCardState *card, uint64_t error); -void ccid_card_qdev_register(CCIDCardInfo *card); +void ccid_card_qdev_register(DeviceInfo *card); /* * support guest visible insertion/removal of ccid devices based on actual diff --git a/hw/usb-ccid.c b/hw/usb-ccid.c index 47b1120..a803c71 100644 --- a/hw/usb-ccid.c +++ b/hw/usb-ccid.c @@ -269,7 +269,6 @@ typedef struct USBCCIDState { USBDevice dev; CCIDBus bus; CCIDCardState *card; - CCIDCardInfo *cardinfo; /* caching the info pointer */ BulkIn bulk_in_pending[BULK_IN_PENDING_NUM]; /* circular */ uint32_t bulk_in_pending_start; uint32_t bulk_in_pending_end; /* first free */ @@ -468,6 +467,43 @@ static const USBDesc desc_ccid = { .str = desc_strings, }; +static const uint8_t *ccid_card_get_atr(CCIDCardState *card, uint32_t *len) +{ + CCIDCardClass *cc = CCID_CARD_GET_CLASS(card); + if (cc->get_atr) { + return cc->get_atr(card, len); + } + return NULL; +} + +static void ccid_card_apdu_from_guest(CCIDCardState *card, + const uint8_t *apdu, + uint32_t len) +{ + CCIDCardClass *cc = CCID_CARD_GET_CLASS(card); + if (cc->apdu_from_guest) { + cc->apdu_from_guest(card, apdu, len); + } +} + +static int ccid_card_exitfn(CCIDCardState *card) +{ + CCIDCardClass *cc = CCID_CARD_GET_CLASS(card); + if (cc->exitfn) { + return cc->exitfn(card); + } + return 0; +} + +static int ccid_card_initfn(CCIDCardState *card) +{ + CCIDCardClass *cc = CCID_CARD_GET_CLASS(card); + if (cc->initfn) { + return cc->initfn(card); + } + return 0; +} + static bool ccid_has_pending_answers(USBCCIDState *s) { return s->pending_answers_num > 0; @@ -749,7 +785,7 @@ static void ccid_write_data_block_atr(USBCCIDState *s, CCID_Header *recv) uint32_t len = 0; if (s->card) { - atr = s->cardinfo->get_atr(s->card, &len); + atr = ccid_card_get_atr(s->card, &len); } ccid_write_data_block(s, recv->bSlot, recv->bSeq, atr, len); } @@ -835,7 +871,7 @@ static void ccid_on_apdu_from_guest(USBCCIDState *s, CCID_XferBlock *recv) recv->hdr.bSeq, len); ccid_add_pending_answer(s, (CCID_Header *)recv); if (s->card) { - s->cardinfo->apdu_from_guest(s->card, recv->abData, len); + ccid_card_apdu_from_guest(s->card, recv->abData, len); } else { DPRINTF(s, D_WARN, "warning: discarded apdu\n"); } @@ -1121,26 +1157,21 @@ void ccid_card_card_inserted(CCIDCardState *card) static int ccid_card_exit(DeviceState *qdev) { int ret = 0; - CCIDCardState *card = DO_UPCAST(CCIDCardState, qdev, qdev); - CCIDCardInfo *info = DO_UPCAST(CCIDCardInfo, qdev, qdev_get_info(qdev)); + CCIDCardState *card = CCID_CARD(qdev); USBCCIDState *s = DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent); if (ccid_card_inserted(s)) { ccid_card_card_removed(card); } - if (info->exitfn) { - ret = info->exitfn(card); - } + ret = ccid_card_exitfn(card); s->card = NULL; - s->cardinfo = NULL; return ret; } static int ccid_card_init(DeviceState *qdev, DeviceInfo *base) { - CCIDCardState *card = DO_UPCAST(CCIDCardState, qdev, qdev); - CCIDCardInfo *info = DO_UPCAST(CCIDCardInfo, qdev, base); + CCIDCardState *card = CCID_CARD(qdev); USBCCIDState *s = DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent); int ret = 0; @@ -1154,20 +1185,19 @@ static int ccid_card_init(DeviceState *qdev, DeviceInfo *base) error_report("Warning: usb-ccid card already full, not adding"); return -1; } - ret = info->initfn ? info->initfn(card) : ret; + ret = ccid_card_initfn(card); if (ret == 0) { s->card = card; - s->cardinfo = info; } return ret; } -void ccid_card_qdev_register(CCIDCardInfo *card) +void ccid_card_qdev_register(DeviceInfo *info) { - card->qdev.bus_info = &ccid_bus_info; - card->qdev.init = ccid_card_init; - card->qdev.exit = ccid_card_exit; - qdev_register(&card->qdev); + info->bus_info = &ccid_bus_info; + info->init = ccid_card_init; + info->exit = ccid_card_exit; + qdev_register_subclass(info, TYPE_CCID_CARD); } static int ccid_initfn(USBDevice *dev) @@ -1178,7 +1208,6 @@ static int ccid_initfn(USBDevice *dev) qbus_create_inplace(&s->bus.qbus, &ccid_bus_info, &dev->qdev, NULL); s->bus.qbus.allow_hotplug = 1; s->card = NULL; - s->cardinfo = NULL; s->migration_state = MIGRATION_NONE; s->migration_target_ip = 0; s->migration_target_port = 0; @@ -1320,8 +1349,17 @@ static struct DeviceInfo ccid_info = { }, }; +static TypeInfo ccid_card_type_info = { + .name = TYPE_CCID_CARD, + .parent = TYPE_DEVICE, + .instance_size = sizeof(CCIDCardState), + .abstract = true, + .class_size = sizeof(CCIDCardClass), +}; + static void ccid_register_devices(void) { + type_register_static(&ccid_card_type_info); usb_qdev_register(&ccid_info, "ccid", NULL); } device_init(ccid_register_devices) -- 1.7.4.1