ccid: convert to QEMU Object Model
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
parent
62aed76583
commit
ba7c05205c
|
@ -564,16 +564,23 @@ static int emulated_exitfn(CCIDCardState *base)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CCIDCardInfo emulated_card_info = {
|
static void emulated_class_initfn(ObjectClass *klass, void *data)
|
||||||
.qdev.name = EMULATED_DEV_NAME,
|
{
|
||||||
.qdev.desc = "emulated smartcard",
|
CCIDCardClass *cc = CCID_CARD_CLASS(klass);
|
||||||
.qdev.size = sizeof(EmulatedState),
|
|
||||||
.initfn = emulated_initfn,
|
cc->initfn = emulated_initfn;
|
||||||
.exitfn = emulated_exitfn,
|
cc->exitfn = emulated_exitfn;
|
||||||
.get_atr = emulated_get_atr,
|
cc->get_atr = emulated_get_atr;
|
||||||
.apdu_from_guest = emulated_apdu_from_guest,
|
cc->apdu_from_guest = emulated_apdu_from_guest;
|
||||||
.qdev.unplug = qdev_simple_unplug_cb,
|
}
|
||||||
.qdev.props = (Property[]) {
|
|
||||||
|
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("backend", EmulatedState, backend_str),
|
||||||
DEFINE_PROP_STRING("cert1", EmulatedState, cert1),
|
DEFINE_PROP_STRING("cert1", EmulatedState, cert1),
|
||||||
DEFINE_PROP_STRING("cert2", EmulatedState, cert2),
|
DEFINE_PROP_STRING("cert2", EmulatedState, cert2),
|
||||||
|
|
|
@ -316,16 +316,23 @@ static VMStateDescription passthru_vmstate = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static CCIDCardInfo passthru_card_info = {
|
static void passthru_class_initfn(ObjectClass *klass, void *data)
|
||||||
.qdev.name = PASSTHRU_DEV_NAME,
|
{
|
||||||
.qdev.desc = "passthrough smartcard",
|
CCIDCardClass *cc = CCID_CARD_CLASS(klass);
|
||||||
.qdev.size = sizeof(PassthruState),
|
|
||||||
.qdev.vmsd = &passthru_vmstate,
|
cc->initfn = passthru_initfn;
|
||||||
.initfn = passthru_initfn,
|
cc->exitfn = passthru_exitfn;
|
||||||
.exitfn = passthru_exitfn,
|
cc->get_atr = passthru_get_atr;
|
||||||
.get_atr = passthru_get_atr,
|
cc->apdu_from_guest = passthru_apdu_from_guest;
|
||||||
.apdu_from_guest = passthru_apdu_from_guest,
|
}
|
||||||
.qdev.props = (Property[]) {
|
|
||||||
|
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_CHR("chardev", PassthruState, cs),
|
||||||
DEFINE_PROP_UINT8("debug", PassthruState, debug, 0),
|
DEFINE_PROP_UINT8("debug", PassthruState, debug, 0),
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
|
|
28
hw/ccid.h
28
hw/ccid.h
|
@ -15,26 +15,34 @@
|
||||||
typedef struct CCIDCardState CCIDCardState;
|
typedef struct CCIDCardState CCIDCardState;
|
||||||
typedef struct CCIDCardInfo CCIDCardInfo;
|
typedef struct CCIDCardInfo CCIDCardInfo;
|
||||||
|
|
||||||
/*
|
#define TYPE_CCID_CARD "ccid-card"
|
||||||
* state of the CCID Card device (i.e. hw/ccid-card-*.c)
|
#define CCID_CARD(obj) \
|
||||||
*/
|
OBJECT_CHECK(CCIDCardState, (obj), TYPE_CCID_CARD)
|
||||||
struct CCIDCardState {
|
#define CCID_CARD_CLASS(klass) \
|
||||||
DeviceState qdev;
|
OBJECT_CLASS_CHECK(CCIDCardClass, (klass), TYPE_CCID_CARD)
|
||||||
uint32_t slot; /* For future use with multiple slot reader. */
|
#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
|
* callbacks to be used by the CCID device (hw/usb-ccid.c) to call
|
||||||
* into the smartcard device (hw/ccid-card-*.c)
|
* into the smartcard device (hw/ccid-card-*.c)
|
||||||
*/
|
*/
|
||||||
struct CCIDCardInfo {
|
typedef struct CCIDCardClass {
|
||||||
DeviceInfo qdev;
|
DeviceClass parent_class;
|
||||||
const uint8_t *(*get_atr)(CCIDCardState *card, uint32_t *len);
|
const uint8_t *(*get_atr)(CCIDCardState *card, uint32_t *len);
|
||||||
void (*apdu_from_guest)(CCIDCardState *card,
|
void (*apdu_from_guest)(CCIDCardState *card,
|
||||||
const uint8_t *apdu,
|
const uint8_t *apdu,
|
||||||
uint32_t len);
|
uint32_t len);
|
||||||
int (*exitfn)(CCIDCardState *card);
|
int (*exitfn)(CCIDCardState *card);
|
||||||
int (*initfn)(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_removed(CCIDCardState *card);
|
||||||
void ccid_card_card_inserted(CCIDCardState *card);
|
void ccid_card_card_inserted(CCIDCardState *card);
|
||||||
void ccid_card_card_error(CCIDCardState *card, uint64_t error);
|
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
|
* support guest visible insertion/removal of ccid devices based on actual
|
||||||
|
|
|
@ -269,7 +269,6 @@ typedef struct USBCCIDState {
|
||||||
USBDevice dev;
|
USBDevice dev;
|
||||||
CCIDBus bus;
|
CCIDBus bus;
|
||||||
CCIDCardState *card;
|
CCIDCardState *card;
|
||||||
CCIDCardInfo *cardinfo; /* caching the info pointer */
|
|
||||||
BulkIn bulk_in_pending[BULK_IN_PENDING_NUM]; /* circular */
|
BulkIn bulk_in_pending[BULK_IN_PENDING_NUM]; /* circular */
|
||||||
uint32_t bulk_in_pending_start;
|
uint32_t bulk_in_pending_start;
|
||||||
uint32_t bulk_in_pending_end; /* first free */
|
uint32_t bulk_in_pending_end; /* first free */
|
||||||
|
@ -468,6 +467,43 @@ static const USBDesc desc_ccid = {
|
||||||
.str = desc_strings,
|
.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)
|
static bool ccid_has_pending_answers(USBCCIDState *s)
|
||||||
{
|
{
|
||||||
return s->pending_answers_num > 0;
|
return s->pending_answers_num > 0;
|
||||||
|
@ -741,7 +777,7 @@ static void ccid_write_data_block_atr(USBCCIDState *s, CCID_Header *recv)
|
||||||
uint32_t len = 0;
|
uint32_t len = 0;
|
||||||
|
|
||||||
if (s->card) {
|
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);
|
ccid_write_data_block(s, recv->bSlot, recv->bSeq, atr, len);
|
||||||
}
|
}
|
||||||
|
@ -827,7 +863,7 @@ static void ccid_on_apdu_from_guest(USBCCIDState *s, CCID_XferBlock *recv)
|
||||||
recv->hdr.bSeq, len);
|
recv->hdr.bSeq, len);
|
||||||
ccid_add_pending_answer(s, (CCID_Header *)recv);
|
ccid_add_pending_answer(s, (CCID_Header *)recv);
|
||||||
if (s->card) {
|
if (s->card) {
|
||||||
s->cardinfo->apdu_from_guest(s->card, recv->abData, len);
|
ccid_card_apdu_from_guest(s->card, recv->abData, len);
|
||||||
} else {
|
} else {
|
||||||
DPRINTF(s, D_WARN, "warning: discarded apdu\n");
|
DPRINTF(s, D_WARN, "warning: discarded apdu\n");
|
||||||
}
|
}
|
||||||
|
@ -1113,26 +1149,21 @@ void ccid_card_card_inserted(CCIDCardState *card)
|
||||||
static int ccid_card_exit(DeviceState *qdev)
|
static int ccid_card_exit(DeviceState *qdev)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
CCIDCardState *card = DO_UPCAST(CCIDCardState, qdev, qdev);
|
CCIDCardState *card = CCID_CARD(qdev);
|
||||||
CCIDCardInfo *info = DO_UPCAST(CCIDCardInfo, qdev, qdev_get_info(qdev));
|
|
||||||
USBCCIDState *s =
|
USBCCIDState *s =
|
||||||
DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
|
DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
|
||||||
|
|
||||||
if (ccid_card_inserted(s)) {
|
if (ccid_card_inserted(s)) {
|
||||||
ccid_card_card_removed(card);
|
ccid_card_card_removed(card);
|
||||||
}
|
}
|
||||||
if (info->exitfn) {
|
ret = ccid_card_exitfn(card);
|
||||||
ret = info->exitfn(card);
|
|
||||||
}
|
|
||||||
s->card = NULL;
|
s->card = NULL;
|
||||||
s->cardinfo = NULL;
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ccid_card_init(DeviceState *qdev, DeviceInfo *base)
|
static int ccid_card_init(DeviceState *qdev, DeviceInfo *base)
|
||||||
{
|
{
|
||||||
CCIDCardState *card = DO_UPCAST(CCIDCardState, qdev, qdev);
|
CCIDCardState *card = CCID_CARD(qdev);
|
||||||
CCIDCardInfo *info = DO_UPCAST(CCIDCardInfo, qdev, base);
|
|
||||||
USBCCIDState *s =
|
USBCCIDState *s =
|
||||||
DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
|
DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
@ -1146,20 +1177,19 @@ static int ccid_card_init(DeviceState *qdev, DeviceInfo *base)
|
||||||
error_report("Warning: usb-ccid card already full, not adding");
|
error_report("Warning: usb-ccid card already full, not adding");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ret = info->initfn ? info->initfn(card) : ret;
|
ret = ccid_card_initfn(card);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
s->card = card;
|
s->card = card;
|
||||||
s->cardinfo = info;
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ccid_card_qdev_register(CCIDCardInfo *card)
|
void ccid_card_qdev_register(DeviceInfo *info)
|
||||||
{
|
{
|
||||||
card->qdev.bus_info = &ccid_bus_info;
|
info->bus_info = &ccid_bus_info;
|
||||||
card->qdev.init = ccid_card_init;
|
info->init = ccid_card_init;
|
||||||
card->qdev.exit = ccid_card_exit;
|
info->exit = ccid_card_exit;
|
||||||
qdev_register(&card->qdev);
|
qdev_register_subclass(info, TYPE_CCID_CARD);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ccid_initfn(USBDevice *dev)
|
static int ccid_initfn(USBDevice *dev)
|
||||||
|
@ -1170,7 +1200,6 @@ static int ccid_initfn(USBDevice *dev)
|
||||||
qbus_create_inplace(&s->bus.qbus, &ccid_bus_info, &dev->qdev, NULL);
|
qbus_create_inplace(&s->bus.qbus, &ccid_bus_info, &dev->qdev, NULL);
|
||||||
s->bus.qbus.allow_hotplug = 1;
|
s->bus.qbus.allow_hotplug = 1;
|
||||||
s->card = NULL;
|
s->card = NULL;
|
||||||
s->cardinfo = NULL;
|
|
||||||
s->migration_state = MIGRATION_NONE;
|
s->migration_state = MIGRATION_NONE;
|
||||||
s->migration_target_ip = 0;
|
s->migration_target_ip = 0;
|
||||||
s->migration_target_port = 0;
|
s->migration_target_port = 0;
|
||||||
|
@ -1312,8 +1341,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)
|
static void ccid_register_devices(void)
|
||||||
{
|
{
|
||||||
|
type_register_static(&ccid_card_type_info);
|
||||||
usb_qdev_register(&ccid_info, "ccid", NULL);
|
usb_qdev_register(&ccid_info, "ccid", NULL);
|
||||||
}
|
}
|
||||||
device_init(ccid_register_devices)
|
device_init(ccid_register_devices)
|
||||||
|
|
Loading…
Reference in a new issue