The passthru ccid card is a device sitting on the usb-ccid bus and
using a chardevice to communicate with a remote device using the
VSCard protocol defined in libcacard/vscard_common.h
Usage docs available in following patch in docs/ccid.txt
Signed-off-by: Alon Levy
---
Changes from v20->v21: (Jes Sorenson review)
* add reference to COPYING in header
* long comment reformatting
Changes from v19->v20:
* checkpatch.pl
Changes from v18->v19:
* add qdev.desc
* remove .qdev.unplug (no hot unplug support for ccid bus)
Changes from v16->v17:
* fix wrong cast when receiving VSC_Error
* ccid-card-passthru: force chardev user wakeup by sending Init
see lengthy comment below.
Changes from v15->v16:
Behavioral changes:
* return correct size
* return error instead of assert if client sent too large ATR
* don't assert if client sent too large a size, but add asserts for indices to
buffer
* reset vscard_in indices on chardev disconnect
* handle init from client
* error if no chardev supplied
* use ntoh, hton
* eradicate reader_id_t
* remove Reconnect usage (removed from VSCARD protocol)
* send VSC_SUCCESS on card insert/remove and reader add/remove
Style fixes:
* width of line fix
* update copyright
* remove old TODO's
* update file header comment
* use macros for debug levels
* c++ style comment replacement
* update copyright license
* fix ATR size comment
* fix whitespace in struct def
* fix DPRINTF prefix
* line width fix
ccid-card-passthru: force chardev user wakeup by sending Init
The problem: how to wakeup the user of the smartcard when the smartcard
device is initialized?
Long term solution: have a callback interface. This was done via
the deprecated so called chardev ioctl interface.
Short term solution: do a write. Specifically we write an Init message.
And we change the client to send it's own Init message regardless of
receiving this one. Additional Init messages will be regarded as
acceptable, the first one received after connection establishment is
the determining one wrt capabilities.
---
Makefile.objs |2 +-
hw/ccid-card-passthru.c | 341 +++
2 files changed, 342 insertions(+), 1 deletions(-)
create mode 100644 hw/ccid-card-passthru.c
diff --git a/Makefile.objs b/Makefile.objs
index 489a46b..744e1d3 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -200,7 +200,7 @@ hw-obj-$(CONFIG_APM) += pm_smbus.o apm.o
hw-obj-$(CONFIG_DMA) += dma.o
hw-obj-$(CONFIG_HPET) += hpet.o
hw-obj-$(CONFIG_APPLESMC) += applesmc.o
-hw-obj-$(CONFIG_SMARTCARD) += usb-ccid.o
+hw-obj-$(CONFIG_SMARTCARD) += usb-ccid.o ccid-card-passthru.o
# PPC devices
hw-obj-$(CONFIG_OPENPIC) += openpic.o
diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c
new file mode 100644
index 000..76abfb1
--- /dev/null
+++ b/hw/ccid-card-passthru.c
@@ -0,0 +1,341 @@
+/*
+ * CCID Passthru Card Device emulation
+ *
+ * Copyright (c) 2011 Red Hat.
+ * Written by Alon Levy.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.1 or later.
+ * This code is licenced under the GNU LGPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include
+
+#include "qemu-char.h"
+#include "monitor.h"
+#include "hw/ccid.h"
+#include "libcacard/vscard_common.h"
+
+#define DPRINTF(card, lvl, fmt, ...)\
+do {\
+if (lvl <= card->debug) { \
+printf("ccid-card-passthru: " fmt , ## __VA_ARGS__); \
+} \
+} while (0)
+
+#define D_WARN 1
+#define D_INFO 2
+#define D_MORE_INFO 3
+#define D_VERBOSE 4
+
+/* TODO: do we still need this? */
+uint8_t DEFAULT_ATR[] = {
+/*
+ * From some example somewhere
+ * 0x3B, 0xB0, 0x18, 0x00, 0xD1, 0x81, 0x05, 0xB1, 0x40, 0x38, 0x1F, 0x03, 0x28
+ */
+
+/* From an Athena smart card */
+ 0x3B, 0xD5, 0x18, 0xFF, 0x80, 0x91, 0xFE, 0x1F, 0xC3, 0x80, 0x73, 0xC8, 0x21,
+ 0x13, 0x08
+};
+
+
+#define PASSTHRU_DEV_NAME "ccid-card-passthru"
+#define VSCARD_IN_SIZE 65536
+
+/* maximum size of ATR - from 7816-3 */
+#define MAX_ATR_SIZE40
+
+typedef struct PassthruState PassthruState;
+
+struct PassthruState {
+CCIDCardState base;
+CharDriverState *cs;
+uint8_t vscard_in_data[VSCARD_IN_SIZE];
+uint32_t vscard_in_pos;
+uint32_t vscard_in_hdr;
+uint8_t atr[MAX_ATR_SIZE];
+uint8_t atr_length;
+uint8_t debug;
+};
+
+/*
+ * VSCard protocol over chardev
+ * This code should not depend on the card type.
+ */
+
+static void ccid_card_vscard_send_msg(PassthruState *s,
+VSCMsgType type, uint32_t reader_id,
+const uint8_t *payload, uint32_t length)
+{
+VSCMsgHeader scr_msg_header;
+
+scr_msg_header.type = htonl(type);
+scr_msg_header.reader_id = htonl(reader_id);
+scr_msg_header.length = htonl(length);
+qemu_chr_write(s->cs, (uint8_t *)&scr_msg_header, sizeof(