* See the COPYING file in the top-level directory.
*/
-#include "sysemu/char.h"
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qemu/units.h"
+#include <libcacard.h>
+#include "chardev/char-fe.h"
+#include "qemu/error-report.h"
+#include "qemu/module.h"
#include "qemu/sockets.h"
-#include "monitor/monitor.h"
#include "ccid.h"
-#include "libcacard/vscard_common.h"
+#include "qapi/error.h"
#define DPRINTF(card, lvl, fmt, ...) \
do { \
0x13, 0x08
};
-
-#define PASSTHRU_DEV_NAME "ccid-card-passthru"
-#define VSCARD_IN_SIZE 65536
+#define VSCARD_IN_SIZE (64 * KiB)
/* maximum size of ATR - from 7816-3 */
#define MAX_ATR_SIZE 40
struct PassthruState {
CCIDCardState base;
- CharDriverState *cs;
+ CharBackend cs;
uint8_t vscard_in_data[VSCARD_IN_SIZE];
uint32_t vscard_in_pos;
uint32_t vscard_in_hdr;
uint8_t debug;
};
+#define TYPE_CCID_PASSTHRU "ccid-card-passthru"
+#define PASSTHRU_CCID_CARD(obj) \
+ OBJECT_CHECK(PassthruState, (obj), TYPE_CCID_PASSTHRU)
+
/*
* VSCard protocol over chardev
* This code should not depend on the card type.
scr_msg_header.type = htonl(type);
scr_msg_header.reader_id = htonl(reader_id);
scr_msg_header.length = htonl(length);
- qemu_chr_fe_write(s->cs, (uint8_t *)&scr_msg_header, sizeof(VSCMsgHeader));
- qemu_chr_fe_write(s->cs, payload, length);
+ /* XXX this blocks entire thread. Rewrite to use
+ * qemu_chr_fe_write and background I/O callbacks */
+ qemu_chr_fe_write_all(&s->cs, (uint8_t *)&scr_msg_header,
+ sizeof(VSCMsgHeader));
+ qemu_chr_fe_write_all(&s->cs, payload, length);
}
static void ccid_card_vscard_send_apdu(PassthruState *s,
static void ccid_card_vscard_drop_connection(PassthruState *card)
{
- qemu_chr_delete(card->cs);
+ qemu_chr_fe_deinit(&card->cs, true);
card->vscard_in_pos = card->vscard_in_hdr = 0;
}
VSCMsgHeader *hdr;
if (card->vscard_in_pos + size > VSCARD_IN_SIZE) {
- error_report(
- "no room for data: pos %d + size %d > %d. dropping connection.",
- card->vscard_in_pos, size, VSCARD_IN_SIZE);
+ error_report("no room for data: pos %u + size %d > %" PRId64 "."
+ " dropping connection.",
+ card->vscard_in_pos, size, VSCARD_IN_SIZE);
ccid_card_vscard_drop_connection(card);
return;
}
case CHR_EVENT_BREAK:
card->vscard_in_pos = card->vscard_in_hdr = 0;
break;
- case CHR_EVENT_FOCUS:
- break;
case CHR_EVENT_OPENED:
DPRINTF(card, D_INFO, "%s: CHR_EVENT_OPENED\n", __func__);
break;
static void passthru_apdu_from_guest(
CCIDCardState *base, const uint8_t *apdu, uint32_t len)
{
- PassthruState *card = DO_UPCAST(PassthruState, base, base);
+ PassthruState *card = PASSTHRU_CCID_CARD(base);
- if (!card->cs) {
+ if (!qemu_chr_fe_backend_connected(&card->cs)) {
printf("ccid-passthru: no chardev, discarding apdu length %d\n", len);
return;
}
static const uint8_t *passthru_get_atr(CCIDCardState *base, uint32_t *len)
{
- PassthruState *card = DO_UPCAST(PassthruState, base, base);
+ PassthruState *card = PASSTHRU_CCID_CARD(base);
*len = card->atr_length;
return card->atr;
}
-static int passthru_initfn(CCIDCardState *base)
+static void passthru_realize(CCIDCardState *base, Error **errp)
{
- PassthruState *card = DO_UPCAST(PassthruState, base, base);
+ PassthruState *card = PASSTHRU_CCID_CARD(base);
card->vscard_in_pos = 0;
card->vscard_in_hdr = 0;
- if (card->cs) {
- DPRINTF(card, D_INFO, "initing chardev\n");
- qemu_chr_add_handlers(card->cs,
+ if (qemu_chr_fe_backend_connected(&card->cs)) {
+ DPRINTF(card, D_INFO, "ccid-card-passthru: initing chardev");
+ qemu_chr_fe_set_handlers(&card->cs,
ccid_card_vscard_can_read,
ccid_card_vscard_read,
- ccid_card_vscard_event, card);
+ ccid_card_vscard_event, NULL, card, NULL, true);
ccid_card_vscard_send_init(card);
} else {
- error_report("missing chardev");
- return -1;
+ error_setg(errp, "missing chardev");
+ return;
}
card->debug = parse_debug_env("QEMU_CCID_PASSTHRU_DEBUG", D_VERBOSE,
card->debug);
assert(sizeof(DEFAULT_ATR) <= MAX_ATR_SIZE);
memcpy(card->atr, DEFAULT_ATR, sizeof(DEFAULT_ATR));
card->atr_length = sizeof(DEFAULT_ATR);
- return 0;
-}
-
-static int passthru_exitfn(CCIDCardState *base)
-{
- return 0;
}
static VMStateDescription passthru_vmstate = {
DeviceClass *dc = DEVICE_CLASS(klass);
CCIDCardClass *cc = CCID_CARD_CLASS(klass);
- cc->initfn = passthru_initfn;
- cc->exitfn = passthru_exitfn;
+ cc->realize = passthru_realize;
cc->get_atr = passthru_get_atr;
cc->apdu_from_guest = passthru_apdu_from_guest;
+ set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
dc->desc = "passthrough smartcard";
dc->vmsd = &passthru_vmstate;
dc->props = passthru_card_properties;
}
static const TypeInfo passthru_card_info = {
- .name = PASSTHRU_DEV_NAME,
+ .name = TYPE_CCID_PASSTHRU,
.parent = TYPE_CCID_CARD,
.instance_size = sizeof(PassthruState),
.class_init = passthru_class_initfn,