[qemu/f19] Support windows 7 smartcard using guests and clients - (bz #917860 rhel 6.5)

Alon Levy alon at fedoraproject.org
Sun Aug 18 13:34:32 UTC 2013


commit 4d1515ab5b518c39414923d65c5e6520841c7105
Author: Alon Levy <alevy at redhat.com>
Date:   Sun Aug 18 13:25:16 2013 +0300

    Support windows 7 smartcard using guests and clients - (bz #917860 rhel 6.5)

 0211-qemu-socket-Make-socket_optslist-public.patch |  113 ++++
 ...ibcacard-correct-T0-historical-bytes-size.patch |   38 ++
 ...mul-do-not-crash-if-backend-is-not-provid.patch |   40 ++
 ...ackend_enum_table-static-const-and-adjust.patch |   50 ++
 ...lare-DEFAULT_ATR-table-to-be-static-const.patch |   32 ++
 ...se-system-config-directory-for-nss-db-on-.patch |   51 ++
 0217-util-move-socket_init-to-osdep.c.patch        |   97 ++++
 ...build-sys-must-link-with-fstack-protector.patch |   73 +++
 0219-libcacard-fix-mingw64-cross-compilation.patch |   57 ++
 ...-split-vscclient-main-from-socket-reading.patch |  377 ++++++++++++++
 ...scclient-to-use-QemuThread-for-portabilit.patch |   46 ++
 ...each-vscclient-to-use-GMainLoop-for-porta.patch |  548 ++++++++++++++++++++
 0223-libcacard-remove-sql-prefix.patch             |   47 ++
 ...bcacard-remove-default-libcoolkey-loading.patch |   64 +++
 0225-dev-smartcard-reader-white-space-fixes.patch  |   54 ++
 ...dev-smartcard-reader-nicer-debug-messages.patch |  144 +++++
 ...rd-reader-remove-aborts-never-triggered-b.patch |   71 +++
 ...ev-smartcard-reader-support-windows-guest.patch |   38 ++
 ...-smartcard-reader-reuse-usb.h-definitions.patch |   65 +++
 0230-libcacard-change-default-ATR.patch            |   42 ++
 0231-ccid-card-passthru-add-atr-check.patch        |   95 ++++
 ...assthru-dev-smartcard-reader-add-debug-en.patch |  110 ++++
 ...rd-reader-define-structs-for-CCID_Paramet.patch |  161 ++++++
 ...ard-reader-change-default-protocol-to-T-0.patch |   50 ++
 ...rd-reader-copy-atr-protocol-to-ccid-param.patch |   85 +++
 ...d-vreader-add-debugging-messages-for-apdu.patch |  169 ++++++
 ...d-move-atr-setting-from-macro-to-function.patch |  161 ++++++
 ...rd-reader-empty-implementation-for-Mechan.patch |   34 ++
 ...ac-change-big-switch-functions-to-single-.patch |  209 ++++++++
 ...scclient-fix-leakage-of-socket-on-error-p.patch |   55 ++
 ...ix-cppcheck-warning-and-remove-unneeded-c.patch |   89 ++++
 qemu.spec                                          |   71 +++-
 32 files changed, 3335 insertions(+), 1 deletions(-)
---
diff --git a/0211-qemu-socket-Make-socket_optslist-public.patch b/0211-qemu-socket-Make-socket_optslist-public.patch
new file mode 100644
index 0000000..4fc8d97
--- /dev/null
+++ b/0211-qemu-socket-Make-socket_optslist-public.patch
@@ -0,0 +1,113 @@
+From 4190f44bbdde97adb467c9c0c625bdc2f89f4af7 Mon Sep 17 00:00:00 2001
+From: Kevin Wolf <kwolf at redhat.com>
+Date: Fri, 15 Mar 2013 17:14:24 +0100
+Subject: [PATCH 211/241] qemu-socket: Make socket_optslist public
+
+Allow other users to create the QemuOpts needed for inet_connect_opts().
+
+Signed-off-by: Kevin Wolf <kwolf at redhat.com>
+Reviewed-by: Eric Blake <eblake at redhat.com>
+(cherry picked from commit e62be8888a83aa0ab7f50eeb954deb2ec4e7201d)
+---
+ include/qemu/sockets.h |  2 ++
+ util/qemu-sockets.c    | 22 +++++++++++-----------
+ 2 files changed, 13 insertions(+), 11 deletions(-)
+
+diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
+index 42ca690..6eed34e 100644
+--- a/include/qemu/sockets.h
++++ b/include/qemu/sockets.h
+@@ -31,6 +31,8 @@ int inet_aton(const char *cp, struct in_addr *ia);
+ #include "qapi/qmp/qerror.h"
+ #include "char/char.h"
+ 
++extern QemuOptsList socket_optslist;
++
+ /* misc helpers */
+ int qemu_socket(int domain, int type, int protocol);
+ int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
+diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
+index cd54fb4..b32510a 100644
+--- a/util/qemu-sockets.c
++++ b/util/qemu-sockets.c
+@@ -33,10 +33,10 @@
+ 
+ static const int on=1, off=0;
+ 
+-/* used temporarely until all users are converted to QemuOpts */
+-static QemuOptsList dummy_opts = {
+-    .name = "dummy",
+-    .head = QTAILQ_HEAD_INITIALIZER(dummy_opts.head),
++/* used temporarily until all users are converted to QemuOpts */
++QemuOptsList socket_optslist = {
++    .name = "socket",
++    .head = QTAILQ_HEAD_INITIALIZER(socket_optslist.head),
+     .desc = {
+         {
+             .name = "path",
+@@ -579,7 +579,7 @@ int inet_listen(const char *str, char *ostr, int olen,
+ 
+     addr = inet_parse(str, errp);
+     if (addr != NULL) {
+-        opts = qemu_opts_create_nofail(&dummy_opts);
++        opts = qemu_opts_create_nofail(&socket_optslist);
+         inet_addr_to_opts(opts, addr);
+         qapi_free_InetSocketAddress(addr);
+         sock = inet_listen_opts(opts, port_offset, errp);
+@@ -652,7 +652,7 @@ int inet_nonblocking_connect(const char *str,
+ 
+     addr = inet_parse(str, errp);
+     if (addr != NULL) {
+-        opts = qemu_opts_create_nofail(&dummy_opts);
++        opts = qemu_opts_create_nofail(&socket_optslist);
+         inet_addr_to_opts(opts, addr);
+         qapi_free_InetSocketAddress(addr);
+         sock = inet_connect_opts(opts, errp, callback, opaque);
+@@ -795,7 +795,7 @@ int unix_listen(const char *str, char *ostr, int olen, Error **errp)
+     char *path, *optstr;
+     int sock, len;
+ 
+-    opts = qemu_opts_create_nofail(&dummy_opts);
++    opts = qemu_opts_create_nofail(&socket_optslist);
+ 
+     optstr = strchr(str, ',');
+     if (optstr) {
+@@ -823,7 +823,7 @@ int unix_connect(const char *path, Error **errp)
+     QemuOpts *opts;
+     int sock;
+ 
+-    opts = qemu_opts_create_nofail(&dummy_opts);
++    opts = qemu_opts_create_nofail(&socket_optslist);
+     qemu_opt_set(opts, "path", path);
+     sock = unix_connect_opts(opts, errp, NULL, NULL);
+     qemu_opts_del(opts);
+@@ -840,7 +840,7 @@ int unix_nonblocking_connect(const char *path,
+ 
+     g_assert(callback != NULL);
+ 
+-    opts = qemu_opts_create_nofail(&dummy_opts);
++    opts = qemu_opts_create_nofail(&socket_optslist);
+     qemu_opt_set(opts, "path", path);
+     sock = unix_connect_opts(opts, errp, callback, opaque);
+     qemu_opts_del(opts);
+@@ -891,7 +891,7 @@ int socket_connect(SocketAddress *addr, Error **errp,
+     QemuOpts *opts;
+     int fd;
+ 
+-    opts = qemu_opts_create_nofail(&dummy_opts);
++    opts = qemu_opts_create_nofail(&socket_optslist);
+     switch (addr->kind) {
+     case SOCKET_ADDRESS_KIND_INET:
+         inet_addr_to_opts(opts, addr->inet);
+@@ -923,7 +923,7 @@ int socket_listen(SocketAddress *addr, Error **errp)
+     QemuOpts *opts;
+     int fd;
+ 
+-    opts = qemu_opts_create_nofail(&dummy_opts);
++    opts = qemu_opts_create_nofail(&socket_optslist);
+     switch (addr->kind) {
+     case SOCKET_ADDRESS_KIND_INET:
+         inet_addr_to_opts(opts, addr->inet);
+-- 
+1.8.3.1
+
diff --git a/0212-libcacard-correct-T0-historical-bytes-size.patch b/0212-libcacard-correct-T0-historical-bytes-size.patch
new file mode 100644
index 0000000..f2d3507
--- /dev/null
+++ b/0212-libcacard-correct-T0-historical-bytes-size.patch
@@ -0,0 +1,38 @@
+From ec22a81dc76492a729695a54e32a837ab6384e65 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <mlureau at redhat.com>
+Date: Sun, 2 Dec 2012 22:00:55 +0100
+Subject: [PATCH 212/241] libcacard: correct T0 historical bytes size
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The VCARD_ATR_PREFIX macro adds a prefix of 6 characters only.
+
+pcsc_scan was complaining before the patch:
+
++ Historical bytes: 56 43 41 52 44 5F 4E 53 53
+ ERROR! ATR is truncated: 2 byte(s) is/are missing
+
+Signed-off-by: Marc-André Lureau <mlureau at redhat.com>
+Reviewed-by: Alon Levy <alevy at redhat.com>
+(cherry picked from commit e2fd2115ce26049335d66ae0ae5e5c0ad06fb498)
+---
+ libcacard/vcardt.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/libcacard/vcardt.h b/libcacard/vcardt.h
+index d3e9522..538bdde 100644
+--- a/libcacard/vcardt.h
++++ b/libcacard/vcardt.h
+@@ -26,7 +26,7 @@ typedef struct VCardEmulStruct VCardEmul;
+ #define MAX_CHANNEL 4
+ 
+ /* create an ATR with appropriate historical bytes */
+-#define VCARD_ATR_PREFIX(size) 0x3b, 0x68+(size), 0x00, 0xff, \
++#define VCARD_ATR_PREFIX(size) 0x3b, 0x66+(size), 0x00, 0xff, \
+                                'V', 'C', 'A', 'R', 'D', '_'
+ 
+ 
+-- 
+1.8.3.1
+
diff --git a/0213-ccid-card-emul-do-not-crash-if-backend-is-not-provid.patch b/0213-ccid-card-emul-do-not-crash-if-backend-is-not-provid.patch
new file mode 100644
index 0000000..0caa307
--- /dev/null
+++ b/0213-ccid-card-emul-do-not-crash-if-backend-is-not-provid.patch
@@ -0,0 +1,40 @@
+From 142383e938fddcf7ed4f81aa30a1e7c1a968cef8 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <mlureau at redhat.com>
+Date: Wed, 21 Nov 2012 14:16:08 +0100
+Subject: [PATCH 213/241] ccid-card-emul: do not crash if backend is not
+ provided
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Program received signal SIGSEGV, Segmentation fault.
+__strcmp_sse42 () at ../sysdeps/x86_64/multiarch/strcmp-sse42.S:164
+164               movdqu        (%rsi), %xmm2
+(gdb) bt
+    at /home/elmarco/320g/src/qemu/hw/ccid-card-emulated.c:477
+    at /home/elmarco/320g/src/qemu/hw/ccid-card-emulated.c:503
+
+Signed-off-by: Marc-André Lureau <mlureau at redhat.com>
+Reviewed-by: Alon Levy <alevy at redhat.com>
+(cherry picked from commit d0ebd78890fba2ab458ec34763dae8566ccb1b72)
+---
+ hw/ccid-card-emulated.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/hw/ccid-card-emulated.c b/hw/ccid-card-emulated.c
+index c8f8ba3..210433e 100644
+--- a/hw/ccid-card-emulated.c
++++ b/hw/ccid-card-emulated.c
+@@ -473,6 +473,9 @@ static uint32_t parse_enumeration(char *str,
+ {
+     uint32_t ret = not_found_value;
+ 
++    if (str == NULL)
++        return 0;
++
+     while (table->name != NULL) {
+         if (strcmp(table->name, str) == 0) {
+             ret = table->value;
+-- 
+1.8.3.1
+
diff --git a/0214-ccid-make-backend_enum_table-static-const-and-adjust.patch b/0214-ccid-make-backend_enum_table-static-const-and-adjust.patch
new file mode 100644
index 0000000..8ecc5a7
--- /dev/null
+++ b/0214-ccid-make-backend_enum_table-static-const-and-adjust.patch
@@ -0,0 +1,50 @@
+From e72e97097d1c619774cb07326496e38c0de46ef0 Mon Sep 17 00:00:00 2001
+From: Jim Meyering <meyering at redhat.com>
+Date: Mon, 21 May 2012 21:56:20 +0200
+Subject: [PATCH 214/241] ccid: make backend_enum_table "static const" and
+ adjust users
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Jim Meyering <meyering at redhat.com>
+Reviewed-by: Alon Levy <alevy at redhat.com>
+Reviewed-by: Marc-André Lureau <mlureau at redhat.com>
+(cherry picked from commit d18c7117467aa5fae95a7c6eaffcf50618197e79)
+---
+ hw/ccid-card-emulated.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/hw/ccid-card-emulated.c b/hw/ccid-card-emulated.c
+index 210433e..cb9ef10 100644
+--- a/hw/ccid-card-emulated.c
++++ b/hw/ccid-card-emulated.c
+@@ -462,14 +462,14 @@ typedef struct EnumTable {
+     uint32_t value;
+ } EnumTable;
+ 
+-EnumTable backend_enum_table[] = {
++static const EnumTable backend_enum_table[] = {
+     {BACKEND_NSS_EMULATED_NAME, BACKEND_NSS_EMULATED},
+     {BACKEND_CERTIFICATES_NAME, BACKEND_CERTIFICATES},
+     {NULL, 0},
+ };
+ 
+ static uint32_t parse_enumeration(char *str,
+-    EnumTable *table, uint32_t not_found_value)
++    const EnumTable *table, uint32_t not_found_value)
+ {
+     uint32_t ret = not_found_value;
+ 
+@@ -490,7 +490,7 @@ static int emulated_initfn(CCIDCardState *base)
+ {
+     EmulatedState *card = DO_UPCAST(EmulatedState, base, base);
+     VCardEmulError ret;
+-    EnumTable *ptable;
++    const EnumTable *ptable;
+ 
+     QSIMPLEQ_INIT(&card->event_list);
+     QSIMPLEQ_INIT(&card->guest_apdu_list);
+-- 
+1.8.3.1
+
diff --git a/0215-ccid-declare-DEFAULT_ATR-table-to-be-static-const.patch b/0215-ccid-declare-DEFAULT_ATR-table-to-be-static-const.patch
new file mode 100644
index 0000000..a93cafd
--- /dev/null
+++ b/0215-ccid-declare-DEFAULT_ATR-table-to-be-static-const.patch
@@ -0,0 +1,32 @@
+From 0a8bbcf1c62e0cf12188eaad871b23633a336f73 Mon Sep 17 00:00:00 2001
+From: Jim Meyering <meyering at redhat.com>
+Date: Mon, 21 May 2012 21:51:33 +0200
+Subject: [PATCH 215/241] ccid: declare DEFAULT_ATR table to be "static const"
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Jim Meyering <meyering at redhat.com>
+Reviewed-by: Alon Levy <alevy at redhat.com>
+Reviewed-by: Marc-André Lureau <mlureau at redhat.com>
+(cherry picked from commit da000a4867749434e03896a5072321771736352a)
+---
+ hw/ccid-card-passthru.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c
+index 0dde761..62070db 100644
+--- a/hw/ccid-card-passthru.c
++++ b/hw/ccid-card-passthru.c
+@@ -27,7 +27,7 @@ do {                                                    \
+ #define D_VERBOSE 4
+ 
+ /* TODO: do we still need this? */
+-uint8_t DEFAULT_ATR[] = {
++static const uint8_t DEFAULT_ATR[] = {
+ /*
+  * From some example somewhere
+  * 0x3B, 0xB0, 0x18, 0x00, 0xD1, 0x81, 0x05, 0xB1, 0x40, 0x38, 0x1F, 0x03, 0x28
+-- 
+1.8.3.1
+
diff --git a/0216-libcacard-use-system-config-directory-for-nss-db-on-.patch b/0216-libcacard-use-system-config-directory-for-nss-db-on-.patch
new file mode 100644
index 0000000..dc6ce62
--- /dev/null
+++ b/0216-libcacard-use-system-config-directory-for-nss-db-on-.patch
@@ -0,0 +1,51 @@
+From 2b60d2a60e98747e46e6addb89bf9a7f923ae499 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <mlureau at redhat.com>
+Date: Wed, 27 Feb 2013 21:08:06 +0100
+Subject: [PATCH 216/241] libcacard: use system config directory for nss db on
+ win32
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+It's a bit nicer to look for default database under
+CSIDL_COMMON_APPDATA\pki\nss rather that /etc/pki/nss.
+
+Signed-off-by: Marc-André Lureau <mlureau at redhat.com>
+Reviewed-by: Alon Levy <alevy at redhat.com>
+(cherry picked from commit e2d9c5e769d59f2bca649b8286892d49bdcfc2b1)
+---
+ libcacard/vcard_emul_nss.c | 18 +++++++++++++++++-
+ 1 file changed, 17 insertions(+), 1 deletion(-)
+
+diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
+index df79476..21d4689 100644
+--- a/libcacard/vcard_emul_nss.c
++++ b/libcacard/vcard_emul_nss.c
+@@ -893,7 +893,23 @@ vcard_emul_init(const VCardEmulOptions *options)
+     if (options->nss_db) {
+         rv = NSS_Init(options->nss_db);
+     } else {
+-        rv = NSS_Init("sql:/etc/pki/nssdb");
++        gchar *path, *db;
++#ifndef _WIN32
++        path = g_strdup("/etc/pki/nssdb");
++#else
++        if (g_get_system_config_dirs() == NULL ||
++            g_get_system_config_dirs()[0] == NULL) {
++            return VCARD_EMUL_FAIL;
++        }
++
++        path = g_build_filename(
++            g_get_system_config_dirs()[0], "pki", "nssdb", NULL);
++#endif
++        db = g_strdup_printf("sql:%s", path);
++
++        rv = NSS_Init(db);
++        g_free(db);
++        g_free(path);
+     }
+     if (rv != SECSuccess) {
+         return VCARD_EMUL_FAIL;
+-- 
+1.8.3.1
+
diff --git a/0217-util-move-socket_init-to-osdep.c.patch b/0217-util-move-socket_init-to-osdep.c.patch
new file mode 100644
index 0000000..83de188
--- /dev/null
+++ b/0217-util-move-socket_init-to-osdep.c.patch
@@ -0,0 +1,97 @@
+From 2f2068568e87fc1f20bc891cce18b4e65965b091 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau at redhat.com>
+Date: Mon, 25 Feb 2013 23:31:11 +0100
+Subject: [PATCH 217/241] util: move socket_init() to osdep.c
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+vscclient needs to call socket_init() for portability.
+Moving to osdep.c since it has no internal dependency.
+
+Signed-off-by: Marc-André Lureau <marcandre.lureau at redhat.com>
+Reviewed-by: Alon Levy <alevy at redhat.com>
+(cherry picked from commit d3bf825e59125bc6a0accec0dca119ea0155cb82)
+
+Conflicts:
+	util/qemu-sockets.c
+---
+ util/osdep.c        | 23 +++++++++++++++++++++++
+ util/qemu-sockets.c | 26 +-------------------------
+ 2 files changed, 24 insertions(+), 25 deletions(-)
+
+diff --git a/util/osdep.c b/util/osdep.c
+index 5b51a03..3c1a0a3 100644
+--- a/util/osdep.c
++++ b/util/osdep.c
+@@ -400,3 +400,26 @@ bool fips_get_state(void)
+     return fips_enabled;
+ }
+ 
++#ifdef _WIN32
++static void socket_cleanup(void)
++{
++    WSACleanup();
++}
++#endif
++
++int socket_init(void)
++{
++#ifdef _WIN32
++    WSADATA Data;
++    int ret, err;
++
++    ret = WSAStartup(MAKEWORD(2, 2), &Data);
++    if (ret != 0) {
++        err = WSAGetLastError();
++        fprintf(stderr, "WSAStartup: %d\n", err);
++        return -1;
++    }
++    atexit(socket_cleanup);
++#endif
++    return 0;
++}
+diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
+index b32510a..7909381 100644
+--- a/util/qemu-sockets.c
++++ b/util/qemu-sockets.c
+@@ -618,7 +618,7 @@ int inet_connect(const char *str, Error **errp)
+ 
+     addr = inet_parse(str, errp);
+     if (addr != NULL) {
+-        opts = qemu_opts_create_nofail(&dummy_opts);
++        opts = qemu_opts_create_nofail(&socket_optslist);
+         inet_addr_to_opts(opts, addr);
+         qapi_free_InetSocketAddress(addr);
+         sock = inet_connect_opts(opts, errp, NULL, NULL);
+@@ -945,27 +945,3 @@ int socket_listen(SocketAddress *addr, Error **errp)
+     qemu_opts_del(opts);
+     return fd;
+ }
+-
+-#ifdef _WIN32
+-static void socket_cleanup(void)
+-{
+-    WSACleanup();
+-}
+-#endif
+-
+-int socket_init(void)
+-{
+-#ifdef _WIN32
+-    WSADATA Data;
+-    int ret, err;
+-
+-    ret = WSAStartup(MAKEWORD(2,2), &Data);
+-    if (ret != 0) {
+-        err = WSAGetLastError();
+-        fprintf(stderr, "WSAStartup: %d\n", err);
+-        return -1;
+-    }
+-    atexit(socket_cleanup);
+-#endif
+-    return 0;
+-}
+-- 
+1.8.3.1
+
diff --git a/0218-build-sys-must-link-with-fstack-protector.patch b/0218-build-sys-must-link-with-fstack-protector.patch
new file mode 100644
index 0000000..95a1dfe
--- /dev/null
+++ b/0218-build-sys-must-link-with-fstack-protector.patch
@@ -0,0 +1,73 @@
+From 989623664fb428748a5efedbab162d75e1eb0432 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <mlureau at redhat.com>
+Date: Mon, 25 Feb 2013 23:31:12 +0100
+Subject: [PATCH 218/241] build-sys: must link with -fstack-protector
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+It is needed to give that flag to the linker as well, but latest
+libtool 2.4.2 still swallows that argument, so let's pass it with
+libtool -Wc argument.
+
+qemu-1.4.0/stubs/arch-query-cpu-def.c:6: undefined reference to `__stack_chk_guard'
+
+Signed-off-by: Marc-André Lureau <mlureau at redhat.com>
+Reviewed-by: Alon Levy <alevy at redhat.com>
+(cherry picked from commit 37746c5eacf309fa019ea0fa45f776c36c561457)
+
+Conflicts:
+	configure
+---
+ configure | 8 +++++++-
+ rules.mak | 1 +
+ 2 files changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/configure b/configure
+index 2996e1d..e8633c5 100755
+--- a/configure
++++ b/configure
+@@ -1197,7 +1197,7 @@ fi
+ gcc_flags="-Wold-style-declaration -Wold-style-definition -Wtype-limits"
+ gcc_flags="-Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers $gcc_flags"
+ gcc_flags="-Wmissing-include-dirs -Wempty-body -Wnested-externs $gcc_flags"
+-gcc_flags="-fstack-protector-all -Wendif-labels $gcc_flags"
++gcc_flags="-Wendif-labels $gcc_flags"
+ gcc_flags="-Wno-initializer-overrides $gcc_flags"
+ # Note that we do not add -Werror to gcc_flags here, because that would
+ # enable it for all configure tests. If a configure test failed due
+@@ -1216,6 +1216,11 @@ for flag in $gcc_flags; do
+     fi
+ done
+ 
++if compile_prog "-Werror -fstack-protector-all" "" ; then
++    QEMU_CFLAGS="$QEMU_CFLAGS -fstack-protector-all"
++    LIBTOOLFLAGS="$LIBTOOLFLAGS -Wc,-fstack-protector-all"
++fi
++
+ # Workaround for http://gcc.gnu.org/PR55489.  Happens with -fPIE/-fPIC and
+ # large functions that use global variables.  The bug is in all releases of
+ # GCC, but it became particularly acute in 4.6.x and 4.7.x.  It is fixed in
+@@ -3832,6 +3837,7 @@ fi
+ echo "LDFLAGS=$LDFLAGS" >> $config_host_mak
+ echo "ARLIBS_BEGIN=$arlibs_begin" >> $config_host_mak
+ echo "ARLIBS_END=$arlibs_end" >> $config_host_mak
++echo "LIBTOOLFLAGS=$LIBTOOLFLAGS" >> $config_host_mak
+ echo "LIBS+=$LIBS" >> $config_host_mak
+ echo "LIBS_TOOLS+=$libs_tools" >> $config_host_mak
+ echo "EXESUF=$EXESUF" >> $config_host_mak
+diff --git a/rules.mak b/rules.mak
+index edc2552..36aba2d 100644
+--- a/rules.mak
++++ b/rules.mak
+@@ -36,6 +36,7 @@ LINK = $(call quiet-command,\
+        $(if $(filter %.lo %.la,$^),$(LIBTOOL) --mode=link --tag=CC \
+        )$(CC) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ \
+        $(sort $(filter %.o, $1)) $(filter-out %.o, $1) $(version-obj-y) \
++       $(if $(filter %.lo %.la,$^),$(LIBTOOLFLAGS)) \
+        $(LIBS),$(if $(filter %.lo %.la,$^),"lt LINK ", "  LINK  ")"$(TARGET_DIR)$@")
+ endif
+ 
+-- 
+1.8.3.1
+
diff --git a/0219-libcacard-fix-mingw64-cross-compilation.patch b/0219-libcacard-fix-mingw64-cross-compilation.patch
new file mode 100644
index 0000000..106a709
--- /dev/null
+++ b/0219-libcacard-fix-mingw64-cross-compilation.patch
@@ -0,0 +1,57 @@
+From cc5a2202bc5484aba302a684fb75106da506b1f0 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <mlureau at redhat.com>
+Date: Mon, 25 Feb 2013 23:31:13 +0100
+Subject: [PATCH 219/241] libcacard: fix mingw64 cross-compilation
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Compile and link with version.lo
+
+Signed-off-by: Marc-André Lureau <mlureau at redhat.com>
+Reviewed-by: Alon Levy <alevy at redhat.com>
+(cherry picked from commit 5354e4d242175e067bb70732f694ae9322a81351)
+---
+ Makefile  | 8 ++++++--
+ rules.mak | 3 ++-
+ 2 files changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/Makefile b/Makefile
+index 0d9099a..751cf1d 100644
+--- a/Makefile
++++ b/Makefile
+@@ -148,11 +148,15 @@ recurse-all: $(SUBDIR_RULES) $(ROMSUBDIR_RULES)
+ 
+ bt-host.o: QEMU_CFLAGS += $(BLUEZ_CFLAGS)
+ 
+-version.o: $(SRC_PATH)/version.rc config-host.h
++version.o: $(SRC_PATH)/version.rc config-host.h | version.lo
+ 	$(call quiet-command,$(WINDRES) -I. -o $@ $<,"  RC    $(TARGET_DIR)$@")
++version.lo: $(SRC_PATH)/version.rc config-host.h
++	$(call quiet-command,$(LIBTOOL) --mode=compile --tag=RC $(WINDRES) -I. -o $@ $<,"lt RC   $(TARGET_DIR)$@")
+ 
+ version-obj-$(CONFIG_WIN32) += version.o
+-Makefile: $(version-obj-y)
++version-lobj-$(CONFIG_WIN32) += $(if $(LIBTOOL),version.lo)
++Makefile: $(version-obj-y) $(version-lobj-y)
++
+ 
+ ######################################################################
+ # Build libraries
+diff --git a/rules.mak b/rules.mak
+index 36aba2d..292a422 100644
+--- a/rules.mak
++++ b/rules.mak
+@@ -35,7 +35,8 @@ LIBTOOL += $(if $(V),,--quiet)
+ LINK = $(call quiet-command,\
+        $(if $(filter %.lo %.la,$^),$(LIBTOOL) --mode=link --tag=CC \
+        )$(CC) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ \
+-       $(sort $(filter %.o, $1)) $(filter-out %.o, $1) $(version-obj-y) \
++       $(sort $(filter %.o, $1)) $(filter-out %.o, $1) \
++       $(if $(filter %.lo %.la,$^),$(version-lobj-y),$(version-obj-y)) \
+        $(if $(filter %.lo %.la,$^),$(LIBTOOLFLAGS)) \
+        $(LIBS),$(if $(filter %.lo %.la,$^),"lt LINK ", "  LINK  ")"$(TARGET_DIR)$@")
+ endif
+-- 
+1.8.3.1
+
diff --git a/0220-libcacard-split-vscclient-main-from-socket-reading.patch b/0220-libcacard-split-vscclient-main-from-socket-reading.patch
new file mode 100644
index 0000000..37fe0e7
--- /dev/null
+++ b/0220-libcacard-split-vscclient-main-from-socket-reading.patch
@@ -0,0 +1,377 @@
+From 2898705c820b4b0c6bbd196bccce55dd3d64f62c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau at redhat.com>
+Date: Mon, 25 Feb 2013 23:31:14 +0100
+Subject: [PATCH 220/241] libcacard: split vscclient main() from socket reading
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Marc-André Lureau <marcandre.lureau at redhat.com>
+Reviewed-by: Alon Levy <alevy at redhat.com>
+(cherry picked from commit a50b831ae1fe039b7c22793f307e0b8afdf50589)
+---
+ libcacard/vscclient.c | 314 ++++++++++++++++++++++++++------------------------
+ 1 file changed, 162 insertions(+), 152 deletions(-)
+
+diff --git a/libcacard/vscclient.c b/libcacard/vscclient.c
+index 9b744f2..5e00db3 100644
+--- a/libcacard/vscclient.c
++++ b/libcacard/vscclient.c
+@@ -211,6 +211,166 @@ get_id_from_string(char *string, unsigned int default_id)
+     return id;
+ }
+ 
++static int
++on_host_init(VSCMsgHeader *mhHeader, VSCMsgInit *incoming)
++{
++    uint32_t *capabilities = (incoming->capabilities);
++    int num_capabilities =
++        1 + ((mhHeader->length - sizeof(VSCMsgInit)) / sizeof(uint32_t));
++    int i;
++    int rv;
++    pthread_t thread_id;
++
++    incoming->version = ntohl(incoming->version);
++    if (incoming->version != VSCARD_VERSION) {
++        if (verbose > 0) {
++            printf("warning: host has version %d, we have %d\n",
++                verbose, VSCARD_VERSION);
++        }
++    }
++    if (incoming->magic != VSCARD_MAGIC) {
++        printf("unexpected magic: got %d, expected %d\n",
++            incoming->magic, VSCARD_MAGIC);
++        return -1;
++    }
++    for (i = 0 ; i < num_capabilities; ++i) {
++        capabilities[i] = ntohl(capabilities[i]);
++    }
++    /* Future: check capabilities */
++    /* remove whatever reader might be left in qemu,
++     * in case of an unclean previous exit. */
++    send_msg(VSC_ReaderRemove, VSCARD_MINIMAL_READER_ID, NULL, 0);
++    /* launch the event_thread. This will trigger reader adds for all the
++     * existing readers */
++    rv = pthread_create(&thread_id, NULL, event_thread, NULL);
++    if (rv < 0) {
++        perror("pthread_create");
++        return rv;
++    }
++    return 0;
++}
++
++#define APDUBufSize 270
++
++static int
++do_socket_read(void)
++{
++    int rv;
++    int dwSendLength;
++    int dwRecvLength;
++    uint8_t pbRecvBuffer[APDUBufSize];
++    uint8_t pbSendBuffer[APDUBufSize];
++    VReaderStatus reader_status;
++    VReader *reader = NULL;
++    VSCMsgHeader mhHeader;
++    VSCMsgError *error_msg;
++
++    rv = read(sock, &mhHeader, sizeof(mhHeader));
++    if (rv < sizeof(mhHeader)) {
++        /* Error */
++        if (rv < 0) {
++            perror("header read error\n");
++        } else {
++            fprintf(stderr, "header short read %d\n", rv);
++        }
++        return -1;
++    }
++    mhHeader.type = ntohl(mhHeader.type);
++    mhHeader.reader_id = ntohl(mhHeader.reader_id);
++    mhHeader.length = ntohl(mhHeader.length);
++    if (verbose) {
++        printf("Header: type=%d, reader_id=%u length=%d (0x%x)\n",
++               mhHeader.type, mhHeader.reader_id, mhHeader.length,
++               mhHeader.length);
++    }
++    switch (mhHeader.type) {
++    case VSC_APDU:
++    case VSC_Flush:
++    case VSC_Error:
++    case VSC_Init:
++        rv = read(sock, pbSendBuffer, mhHeader.length);
++        break;
++    default:
++        fprintf(stderr, "Unexpected message of type 0x%X\n", mhHeader.type);
++        return -1;
++    }
++    switch (mhHeader.type) {
++    case VSC_APDU:
++        if (rv < 0) {
++            /* Error */
++            fprintf(stderr, "read error\n");
++            close(sock);
++            return -1;
++        }
++        if (verbose) {
++            printf(" recv APDU: ");
++            print_byte_array(pbSendBuffer, mhHeader.length);
++        }
++        /* Transmit received APDU */
++        dwSendLength = mhHeader.length;
++        dwRecvLength = sizeof(pbRecvBuffer);
++        reader = vreader_get_reader_by_id(mhHeader.reader_id);
++        reader_status = vreader_xfr_bytes(reader,
++                                          pbSendBuffer, dwSendLength,
++                                          pbRecvBuffer, &dwRecvLength);
++        if (reader_status == VREADER_OK) {
++            mhHeader.length = dwRecvLength;
++            if (verbose) {
++                printf(" send response: ");
++                print_byte_array(pbRecvBuffer, mhHeader.length);
++            }
++            send_msg(VSC_APDU, mhHeader.reader_id,
++                     pbRecvBuffer, dwRecvLength);
++        } else {
++            rv = reader_status; /* warning: not meaningful */
++            send_msg(VSC_Error, mhHeader.reader_id, &rv, sizeof(uint32_t));
++        }
++        vreader_free(reader);
++        reader = NULL; /* we've freed it, don't use it by accident
++                          again */
++        break;
++    case VSC_Flush:
++        /* TODO: actually flush */
++        send_msg(VSC_FlushComplete, mhHeader.reader_id, NULL, 0);
++        break;
++    case VSC_Error:
++        error_msg = (VSCMsgError *) pbSendBuffer;
++        if (error_msg->code == VSC_SUCCESS) {
++            qemu_mutex_lock(&pending_reader_lock);
++            if (pending_reader) {
++                vreader_set_id(pending_reader, mhHeader.reader_id);
++                vreader_free(pending_reader);
++                pending_reader = NULL;
++                qemu_cond_signal(&pending_reader_condition);
++            }
++            qemu_mutex_unlock(&pending_reader_lock);
++            break;
++        }
++        printf("warning: qemu refused to add reader\n");
++        if (error_msg->code == VSC_CANNOT_ADD_MORE_READERS) {
++            /* clear pending reader, qemu can't handle any more */
++            qemu_mutex_lock(&pending_reader_lock);
++            if (pending_reader) {
++                pending_reader = NULL;
++                /* make sure the event loop doesn't hang */
++                qemu_cond_signal(&pending_reader_condition);
++            }
++            qemu_mutex_unlock(&pending_reader_lock);
++        }
++        break;
++    case VSC_Init:
++        if (on_host_init(&mhHeader, (VSCMsgInit *)pbSendBuffer) < 0) {
++            return -1;
++        }
++        break;
++    default:
++        printf("Default\n");
++        return -1;
++    }
++
++    return 0;
++}
++
+ static void
+ do_command(void)
+ {
+@@ -339,8 +499,6 @@ do_command(void)
+ }
+ 
+ 
+-#define APDUBufSize 270
+-
+ /* just for ease of parsing command line arguments. */
+ #define MAX_CERTS 100
+ 
+@@ -385,44 +543,6 @@ connect_to_qemu(
+     return sock;
+ }
+ 
+-static int on_host_init(VSCMsgHeader *mhHeader, VSCMsgInit *incoming)
+-{
+-    uint32_t *capabilities = (incoming->capabilities);
+-    int num_capabilities =
+-        1 + ((mhHeader->length - sizeof(VSCMsgInit)) / sizeof(uint32_t));
+-    int i;
+-    int rv;
+-    pthread_t thread_id;
+-
+-    incoming->version = ntohl(incoming->version);
+-    if (incoming->version != VSCARD_VERSION) {
+-        if (verbose > 0) {
+-            printf("warning: host has version %d, we have %d\n",
+-                verbose, VSCARD_VERSION);
+-        }
+-    }
+-    if (incoming->magic != VSCARD_MAGIC) {
+-        printf("unexpected magic: got %d, expected %d\n",
+-            incoming->magic, VSCARD_MAGIC);
+-        return -1;
+-    }
+-    for (i = 0 ; i < num_capabilities; ++i) {
+-        capabilities[i] = ntohl(capabilities[i]);
+-    }
+-    /* Future: check capabilities */
+-    /* remove whatever reader might be left in qemu,
+-     * in case of an unclean previous exit. */
+-    send_msg(VSC_ReaderRemove, VSCARD_MINIMAL_READER_ID, NULL, 0);
+-    /* launch the event_thread. This will trigger reader adds for all the
+-     * existing readers */
+-    rv = pthread_create(&thread_id, NULL, event_thread, NULL);
+-    if (rv < 0) {
+-        perror("pthread_create");
+-        return rv;
+-    }
+-    return 0;
+-}
+-
+ int
+ main(
+     int argc,
+@@ -431,21 +551,13 @@ main(
+     char *qemu_host;
+     char *qemu_port;
+     VSCMsgHeader mhHeader;
+-    VSCMsgError *error_msg;
+ 
+-    int rv;
+-    int dwSendLength;
+-    int dwRecvLength;
+-    uint8_t pbRecvBuffer[APDUBufSize];
+-    uint8_t pbSendBuffer[APDUBufSize];
+-     VReaderStatus reader_status;
+-    VReader *reader = NULL;
+     VCardEmulOptions *command_line_options = NULL;
+ 
+     char *cert_names[MAX_CERTS];
+     char *emul_args = NULL;
+     int cert_count = 0;
+-    int c;
++    int c, rv;
+ 
+     while ((c = getopt(argc, argv, "c:e:pd:")) != -1) {
+         switch (c) {
+@@ -548,109 +660,7 @@ main(
+         if (!FD_ISSET(sock, &fds)) {
+             continue;
+         }
+-
+-        rv = read(sock, &mhHeader, sizeof(mhHeader));
+-        if (rv < sizeof(mhHeader)) {
+-            /* Error */
+-            if (rv < 0) {
+-                perror("header read error\n");
+-            } else {
+-                fprintf(stderr, "header short read %d\n", rv);
+-            }
+-            return 8;
+-        }
+-        mhHeader.type = ntohl(mhHeader.type);
+-        mhHeader.reader_id = ntohl(mhHeader.reader_id);
+-        mhHeader.length = ntohl(mhHeader.length);
+-        if (verbose) {
+-            printf("Header: type=%d, reader_id=%u length=%d (0x%x)\n",
+-                    mhHeader.type, mhHeader.reader_id, mhHeader.length,
+-                                               mhHeader.length);
+-        }
+-        switch (mhHeader.type) {
+-        case VSC_APDU:
+-        case VSC_Flush:
+-        case VSC_Error:
+-        case VSC_Init:
+-            rv = read(sock, pbSendBuffer, mhHeader.length);
+-            break;
+-        default:
+-            fprintf(stderr, "Unexpected message of type 0x%X\n", mhHeader.type);
+-            return 0;
+-        }
+-        switch (mhHeader.type) {
+-        case VSC_APDU:
+-            if (rv < 0) {
+-                /* Error */
+-                fprintf(stderr, "read error\n");
+-                close(sock);
+-                return 8;
+-            }
+-            if (verbose) {
+-                printf(" recv APDU: ");
+-                print_byte_array(pbSendBuffer, mhHeader.length);
+-            }
+-            /* Transmit received APDU */
+-            dwSendLength = mhHeader.length;
+-            dwRecvLength = sizeof(pbRecvBuffer);
+-            reader = vreader_get_reader_by_id(mhHeader.reader_id);
+-            reader_status = vreader_xfr_bytes(reader,
+-                pbSendBuffer, dwSendLength,
+-                pbRecvBuffer, &dwRecvLength);
+-            if (reader_status == VREADER_OK) {
+-                mhHeader.length = dwRecvLength;
+-                if (verbose) {
+-                    printf(" send response: ");
+-                    print_byte_array(pbRecvBuffer, mhHeader.length);
+-                }
+-                send_msg(VSC_APDU, mhHeader.reader_id,
+-                         pbRecvBuffer, dwRecvLength);
+-            } else {
+-                rv = reader_status; /* warning: not meaningful */
+-                send_msg(VSC_Error, mhHeader.reader_id, &rv, sizeof(uint32_t));
+-            }
+-            vreader_free(reader);
+-            reader = NULL; /* we've freed it, don't use it by accident
+-                              again */
+-            break;
+-        case VSC_Flush:
+-            /* TODO: actually flush */
+-            send_msg(VSC_FlushComplete, mhHeader.reader_id, NULL, 0);
+-            break;
+-        case VSC_Error:
+-            error_msg = (VSCMsgError *) pbSendBuffer;
+-            if (error_msg->code == VSC_SUCCESS) {
+-                qemu_mutex_lock(&pending_reader_lock);
+-                if (pending_reader) {
+-                    vreader_set_id(pending_reader, mhHeader.reader_id);
+-                    vreader_free(pending_reader);
+-                    pending_reader = NULL;
+-                    qemu_cond_signal(&pending_reader_condition);
+-                }
+-                qemu_mutex_unlock(&pending_reader_lock);
+-                break;
+-            }
+-            printf("warning: qemu refused to add reader\n");
+-            if (error_msg->code == VSC_CANNOT_ADD_MORE_READERS) {
+-                /* clear pending reader, qemu can't handle any more */
+-                qemu_mutex_lock(&pending_reader_lock);
+-                if (pending_reader) {
+-                    pending_reader = NULL;
+-                    /* make sure the event loop doesn't hang */
+-                    qemu_cond_signal(&pending_reader_condition);
+-                }
+-                qemu_mutex_unlock(&pending_reader_lock);
+-            }
+-            break;
+-        case VSC_Init:
+-            if (on_host_init(&mhHeader, (VSCMsgInit *)pbSendBuffer) < 0) {
+-                return -1;
+-            }
+-            break;
+-        default:
+-            printf("Default\n");
+-            return 0;
+-        }
++        rv = do_socket_read();
+     } while (rv >= 0);
+ 
+     return 0;
+-- 
+1.8.3.1
+
diff --git a/0221-libcacard-vscclient-to-use-QemuThread-for-portabilit.patch b/0221-libcacard-vscclient-to-use-QemuThread-for-portabilit.patch
new file mode 100644
index 0000000..6d75edf
--- /dev/null
+++ b/0221-libcacard-vscclient-to-use-QemuThread-for-portabilit.patch
@@ -0,0 +1,46 @@
+From dc54f4b260b2fe57af5ad57326f0a67a82f977d3 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau at redhat.com>
+Date: Mon, 25 Feb 2013 23:31:15 +0100
+Subject: [PATCH 221/241] libcacard: vscclient to use QemuThread for
+ portability
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Marc-André Lureau <marcandre.lureau at redhat.com>
+Reviewed-by: Alon Levy <alevy at redhat.com>
+(cherry picked from commit 930c8ad472ec00d40cfbf1e9b1395946bf0dd392)
+---
+ libcacard/vscclient.c | 9 ++-------
+ 1 file changed, 2 insertions(+), 7 deletions(-)
+
+diff --git a/libcacard/vscclient.c b/libcacard/vscclient.c
+index 5e00db3..5f47634 100644
+--- a/libcacard/vscclient.c
++++ b/libcacard/vscclient.c
+@@ -218,8 +218,7 @@ on_host_init(VSCMsgHeader *mhHeader, VSCMsgInit *incoming)
+     int num_capabilities =
+         1 + ((mhHeader->length - sizeof(VSCMsgInit)) / sizeof(uint32_t));
+     int i;
+-    int rv;
+-    pthread_t thread_id;
++    QemuThread thread_id;
+ 
+     incoming->version = ntohl(incoming->version);
+     if (incoming->version != VSCARD_VERSION) {
+@@ -242,11 +241,7 @@ on_host_init(VSCMsgHeader *mhHeader, VSCMsgInit *incoming)
+     send_msg(VSC_ReaderRemove, VSCARD_MINIMAL_READER_ID, NULL, 0);
+     /* launch the event_thread. This will trigger reader adds for all the
+      * existing readers */
+-    rv = pthread_create(&thread_id, NULL, event_thread, NULL);
+-    if (rv < 0) {
+-        perror("pthread_create");
+-        return rv;
+-    }
++    qemu_thread_create(&thread_id, event_thread, NULL, 0);
+     return 0;
+ }
+ 
+-- 
+1.8.3.1
+
diff --git a/0222-libcacard-teach-vscclient-to-use-GMainLoop-for-porta.patch b/0222-libcacard-teach-vscclient-to-use-GMainLoop-for-porta.patch
new file mode 100644
index 0000000..4b9d39f
--- /dev/null
+++ b/0222-libcacard-teach-vscclient-to-use-GMainLoop-for-porta.patch
@@ -0,0 +1,548 @@
+From d5830145bc9af4b8df2eddd5a6ece27c4010b3d6 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <mlureau at redhat.com>
+Date: Mon, 25 Feb 2013 23:31:16 +0100
+Subject: [PATCH 222/241] libcacard: teach vscclient to use GMainLoop for
+ portability
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This version handles non-blocking sending and receiving from the
+socket.
+
+Signed-off-by: Marc-André Lureau <mlureau at redhat.com>
+Reviewed-by: Alon Levy <alevy at redhat.com>
+(cherry picked from commit c9495ee9eb57786f5a60d4591bb186b23f6b6bef)
+---
+ libcacard/vscclient.c | 391 +++++++++++++++++++++++++++++++-------------------
+ 1 file changed, 246 insertions(+), 145 deletions(-)
+
+diff --git a/libcacard/vscclient.c b/libcacard/vscclient.c
+index 5f47634..ac23647 100644
+--- a/libcacard/vscclient.c
++++ b/libcacard/vscclient.c
+@@ -10,7 +10,10 @@
+  * See the COPYING.LIB file in the top-level directory.
+  */
+ 
++#ifndef _WIN32
+ #include <netdb.h>
++#endif
++#include <glib.h>
+ 
+ #include "qemu-common.h"
+ #include "qemu/thread.h"
+@@ -22,9 +25,7 @@
+ #include "vcard_emul.h"
+ #include "vevent.h"
+ 
+-int verbose;
+-
+-int sock;
++static int verbose;
+ 
+ static void
+ print_byte_array(
+@@ -51,7 +52,47 @@ print_usage(void) {
+     vcard_emul_usage();
+ }
+ 
+-static QemuMutex write_lock;
++static GIOChannel *channel_socket;
++static GByteArray *socket_to_send;
++static QemuMutex socket_to_send_lock;
++static guint socket_tag;
++
++static void
++update_socket_watch(gboolean out);
++
++static gboolean
++do_socket_send(GIOChannel *source,
++               GIOCondition condition,
++               gpointer data)
++{
++    gsize bw;
++    GError *err = NULL;
++
++    g_return_val_if_fail(socket_to_send->len != 0, FALSE);
++    g_return_val_if_fail(condition & G_IO_OUT, FALSE);
++
++    g_io_channel_write_chars(channel_socket,
++        (gchar *)socket_to_send->data, socket_to_send->len, &bw, &err);
++    if (err != NULL) {
++        g_error("Error while sending socket %s", err->message);
++        return FALSE;
++    }
++    g_byte_array_remove_range(socket_to_send, 0, bw);
++
++    if (socket_to_send->len == 0) {
++        update_socket_watch(FALSE);
++        return FALSE;
++    }
++    return TRUE;
++}
++
++static gboolean
++socket_prepare_sending(gpointer user_data)
++{
++    update_socket_watch(TRUE);
++
++    return FALSE;
++}
+ 
+ static int
+ send_msg(
+@@ -60,10 +101,9 @@ send_msg(
+     const void *msg,
+     unsigned int length
+ ) {
+-    int rv;
+     VSCMsgHeader mhHeader;
+ 
+-    qemu_mutex_lock(&write_lock);
++    qemu_mutex_lock(&socket_to_send_lock);
+ 
+     if (verbose > 10) {
+         printf("sending type=%d id=%u, len =%u (0x%x)\n",
+@@ -73,23 +113,11 @@ send_msg(
+     mhHeader.type = htonl(type);
+     mhHeader.reader_id = 0;
+     mhHeader.length = htonl(length);
+-    rv = write(sock, &mhHeader, sizeof(mhHeader));
+-    if (rv < 0) {
+-        /* Error */
+-        fprintf(stderr, "write header error\n");
+-        close(sock);
+-        qemu_mutex_unlock(&write_lock);
+-        return 16;
+-    }
+-    rv = write(sock, msg, length);
+-    if (rv < 0) {
+-        /* Error */
+-        fprintf(stderr, "write error\n");
+-        close(sock);
+-        qemu_mutex_unlock(&write_lock);
+-        return 16;
+-    }
+-    qemu_mutex_unlock(&write_lock);
++    g_byte_array_append(socket_to_send, (guint8 *)&mhHeader, sizeof(mhHeader));
++    g_byte_array_append(socket_to_send, (guint8 *)msg, length);
++    g_idle_add(socket_prepare_sending, NULL);
++
++    qemu_mutex_unlock(&socket_to_send_lock);
+ 
+     return 0;
+ }
+@@ -245,139 +273,203 @@ on_host_init(VSCMsgHeader *mhHeader, VSCMsgInit *incoming)
+     return 0;
+ }
+ 
++
++enum {
++    STATE_HEADER,
++    STATE_MESSAGE,
++};
++
+ #define APDUBufSize 270
+ 
+-static int
+-do_socket_read(void)
++static gboolean
++do_socket_read(GIOChannel *source,
++               GIOCondition condition,
++               gpointer data)
+ {
+     int rv;
+     int dwSendLength;
+     int dwRecvLength;
+     uint8_t pbRecvBuffer[APDUBufSize];
+-    uint8_t pbSendBuffer[APDUBufSize];
++    static uint8_t pbSendBuffer[APDUBufSize];
+     VReaderStatus reader_status;
+     VReader *reader = NULL;
+-    VSCMsgHeader mhHeader;
++    static VSCMsgHeader mhHeader;
+     VSCMsgError *error_msg;
++    GError *err = NULL;
+ 
+-    rv = read(sock, &mhHeader, sizeof(mhHeader));
+-    if (rv < sizeof(mhHeader)) {
+-        /* Error */
+-        if (rv < 0) {
+-            perror("header read error\n");
+-        } else {
+-            fprintf(stderr, "header short read %d\n", rv);
+-        }
+-        return -1;
+-    }
+-    mhHeader.type = ntohl(mhHeader.type);
+-    mhHeader.reader_id = ntohl(mhHeader.reader_id);
+-    mhHeader.length = ntohl(mhHeader.length);
+-    if (verbose) {
+-        printf("Header: type=%d, reader_id=%u length=%d (0x%x)\n",
+-               mhHeader.type, mhHeader.reader_id, mhHeader.length,
+-               mhHeader.length);
+-    }
+-    switch (mhHeader.type) {
+-    case VSC_APDU:
+-    case VSC_Flush:
+-    case VSC_Error:
+-    case VSC_Init:
+-        rv = read(sock, pbSendBuffer, mhHeader.length);
+-        break;
+-    default:
+-        fprintf(stderr, "Unexpected message of type 0x%X\n", mhHeader.type);
+-        return -1;
++    static gchar *buf;
++    static gsize br, to_read;
++    static int state = STATE_HEADER;
++
++    if (state == STATE_HEADER && to_read == 0) {
++        buf = (gchar *)&mhHeader;
++        to_read = sizeof(mhHeader);
+     }
+-    switch (mhHeader.type) {
+-    case VSC_APDU:
+-        if (rv < 0) {
+-            /* Error */
+-            fprintf(stderr, "read error\n");
+-            close(sock);
+-            return -1;
++
++    if (to_read > 0) {
++        g_io_channel_read_chars(source, (gchar *)buf, to_read, &br, &err);
++        if (err != NULL) {
++            g_error("error while reading: %s", err->message);
+         }
++        buf += br;
++        to_read -= br;
++        if (to_read != 0) {
++            return TRUE;
++        }
++    }
++
++    if (state == STATE_HEADER) {
++        mhHeader.type = ntohl(mhHeader.type);
++        mhHeader.reader_id = ntohl(mhHeader.reader_id);
++        mhHeader.length = ntohl(mhHeader.length);
+         if (verbose) {
+-            printf(" recv APDU: ");
+-            print_byte_array(pbSendBuffer, mhHeader.length);
++            printf("Header: type=%d, reader_id=%u length=%d (0x%x)\n",
++                   mhHeader.type, mhHeader.reader_id, mhHeader.length,
++                   mhHeader.length);
+         }
+-        /* Transmit received APDU */
+-        dwSendLength = mhHeader.length;
+-        dwRecvLength = sizeof(pbRecvBuffer);
+-        reader = vreader_get_reader_by_id(mhHeader.reader_id);
+-        reader_status = vreader_xfr_bytes(reader,
+-                                          pbSendBuffer, dwSendLength,
+-                                          pbRecvBuffer, &dwRecvLength);
+-        if (reader_status == VREADER_OK) {
+-            mhHeader.length = dwRecvLength;
++        switch (mhHeader.type) {
++        case VSC_APDU:
++        case VSC_Flush:
++        case VSC_Error:
++        case VSC_Init:
++            buf = (gchar *)pbSendBuffer;
++            to_read = mhHeader.length;
++            state = STATE_MESSAGE;
++            return TRUE;
++        default:
++            fprintf(stderr, "Unexpected message of type 0x%X\n", mhHeader.type);
++            return FALSE;
++        }
++    }
++
++    if (state == STATE_MESSAGE) {
++        switch (mhHeader.type) {
++        case VSC_APDU:
+             if (verbose) {
+-                printf(" send response: ");
+-                print_byte_array(pbRecvBuffer, mhHeader.length);
++                printf(" recv APDU: ");
++                print_byte_array(pbSendBuffer, mhHeader.length);
+             }
+-            send_msg(VSC_APDU, mhHeader.reader_id,
+-                     pbRecvBuffer, dwRecvLength);
+-        } else {
+-            rv = reader_status; /* warning: not meaningful */
+-            send_msg(VSC_Error, mhHeader.reader_id, &rv, sizeof(uint32_t));
+-        }
+-        vreader_free(reader);
+-        reader = NULL; /* we've freed it, don't use it by accident
+-                          again */
+-        break;
+-    case VSC_Flush:
+-        /* TODO: actually flush */
+-        send_msg(VSC_FlushComplete, mhHeader.reader_id, NULL, 0);
+-        break;
+-    case VSC_Error:
+-        error_msg = (VSCMsgError *) pbSendBuffer;
+-        if (error_msg->code == VSC_SUCCESS) {
+-            qemu_mutex_lock(&pending_reader_lock);
+-            if (pending_reader) {
+-                vreader_set_id(pending_reader, mhHeader.reader_id);
+-                vreader_free(pending_reader);
+-                pending_reader = NULL;
+-                qemu_cond_signal(&pending_reader_condition);
++            /* Transmit received APDU */
++            dwSendLength = mhHeader.length;
++            dwRecvLength = sizeof(pbRecvBuffer);
++            reader = vreader_get_reader_by_id(mhHeader.reader_id);
++            reader_status = vreader_xfr_bytes(reader,
++                                              pbSendBuffer, dwSendLength,
++                                              pbRecvBuffer, &dwRecvLength);
++            if (reader_status == VREADER_OK) {
++                mhHeader.length = dwRecvLength;
++                if (verbose) {
++                    printf(" send response: ");
++                    print_byte_array(pbRecvBuffer, mhHeader.length);
++                }
++                send_msg(VSC_APDU, mhHeader.reader_id,
++                         pbRecvBuffer, dwRecvLength);
++            } else {
++                rv = reader_status; /* warning: not meaningful */
++                send_msg(VSC_Error, mhHeader.reader_id, &rv, sizeof(uint32_t));
+             }
+-            qemu_mutex_unlock(&pending_reader_lock);
++            vreader_free(reader);
++            reader = NULL; /* we've freed it, don't use it by accident
++                              again */
+             break;
+-        }
+-        printf("warning: qemu refused to add reader\n");
+-        if (error_msg->code == VSC_CANNOT_ADD_MORE_READERS) {
+-            /* clear pending reader, qemu can't handle any more */
+-            qemu_mutex_lock(&pending_reader_lock);
+-            if (pending_reader) {
+-                pending_reader = NULL;
+-                /* make sure the event loop doesn't hang */
+-                qemu_cond_signal(&pending_reader_condition);
++        case VSC_Flush:
++            /* TODO: actually flush */
++            send_msg(VSC_FlushComplete, mhHeader.reader_id, NULL, 0);
++            break;
++        case VSC_Error:
++            error_msg = (VSCMsgError *) pbSendBuffer;
++            if (error_msg->code == VSC_SUCCESS) {
++                qemu_mutex_lock(&pending_reader_lock);
++                if (pending_reader) {
++                    vreader_set_id(pending_reader, mhHeader.reader_id);
++                    vreader_free(pending_reader);
++                    pending_reader = NULL;
++                    qemu_cond_signal(&pending_reader_condition);
++                }
++                qemu_mutex_unlock(&pending_reader_lock);
++                break;
+             }
+-            qemu_mutex_unlock(&pending_reader_lock);
++            printf("warning: qemu refused to add reader\n");
++            if (error_msg->code == VSC_CANNOT_ADD_MORE_READERS) {
++                /* clear pending reader, qemu can't handle any more */
++                qemu_mutex_lock(&pending_reader_lock);
++                if (pending_reader) {
++                    pending_reader = NULL;
++                    /* make sure the event loop doesn't hang */
++                    qemu_cond_signal(&pending_reader_condition);
++                }
++                qemu_mutex_unlock(&pending_reader_lock);
++            }
++            break;
++        case VSC_Init:
++            if (on_host_init(&mhHeader, (VSCMsgInit *)pbSendBuffer) < 0) {
++                return FALSE;
++            }
++            break;
++        default:
++            g_warn_if_reached();
++            return FALSE;
+         }
+-        break;
+-    case VSC_Init:
+-        if (on_host_init(&mhHeader, (VSCMsgInit *)pbSendBuffer) < 0) {
+-            return -1;
++
++        state = STATE_HEADER;
++    }
++
++
++    return TRUE;
++}
++
++static gboolean
++do_socket(GIOChannel *source,
++          GIOCondition condition,
++          gpointer data)
++{
++    /* not sure if two watches work well with a single win32 sources */
++    if (condition & G_IO_OUT) {
++        if (!do_socket_send(source, condition, data)) {
++            return FALSE;
+         }
+-        break;
+-    default:
+-        printf("Default\n");
+-        return -1;
+     }
+ 
+-    return 0;
++    if (condition & G_IO_IN) {
++        if (!do_socket_read(source, condition, data)) {
++            return FALSE;
++        }
++    }
++
++    return TRUE;
+ }
+ 
+ static void
+-do_command(void)
++update_socket_watch(gboolean out)
++{
++    if (socket_tag != 0) {
++        g_source_remove(socket_tag);
++    }
++
++    socket_tag = g_io_add_watch(channel_socket,
++        G_IO_IN | (out ? G_IO_OUT : 0), do_socket, NULL);
++}
++
++static gboolean
++do_command(GIOChannel *source,
++           GIOCondition condition,
++           gpointer data)
+ {
+-    char inbuf[255];
+     char *string;
+     VCardEmulError error;
+     static unsigned int default_reader_id;
+     unsigned int reader_id;
+     VReader *reader = NULL;
++    GError *err = NULL;
++
++    g_assert(condition & G_IO_IN);
+ 
+     reader_id = default_reader_id;
+-    string = fgets(inbuf, sizeof(inbuf), stdin);
++    g_io_channel_read_line(source, &string, NULL, NULL, &err);
++    if (err != NULL) {
++        g_error("Error while reading command: %s", err->message);
++    }
++
+     if (string != NULL) {
+         if (strncmp(string, "exit", 4) == 0) {
+             /* remove all the readers */
+@@ -491,6 +583,8 @@ do_command(void)
+     vreader_free(reader);
+     printf("> ");
+     fflush(stdout);
++
++    return TRUE;
+ }
+ 
+ 
+@@ -504,7 +598,7 @@ connect_to_qemu(
+ ) {
+     struct addrinfo hints;
+     struct addrinfo *server;
+-    int ret;
++    int ret, sock;
+ 
+     sock = qemu_socket(AF_INET, SOCK_STREAM, 0);
+     if (sock < 0) {
+@@ -543,6 +637,8 @@ main(
+     int argc,
+     char *argv[]
+ ) {
++    GMainLoop *loop;
++    GIOChannel *channel_stdin;
+     char *qemu_host;
+     char *qemu_port;
+     VSCMsgHeader mhHeader;
+@@ -552,7 +648,10 @@ main(
+     char *cert_names[MAX_CERTS];
+     char *emul_args = NULL;
+     int cert_count = 0;
+-    int c, rv;
++    int c, sock;
++
++    if (socket_init() != 0)
++        return 1;
+ 
+     while ((c = getopt(argc, argv, "c:e:pd:")) != -1) {
+         switch (c) {
+@@ -618,15 +717,33 @@ main(
+         exit(5);
+     }
+ 
+-    qemu_mutex_init(&write_lock);
++    socket_to_send = g_byte_array_new();
++    qemu_mutex_init(&socket_to_send_lock);
+     qemu_mutex_init(&pending_reader_lock);
+     qemu_cond_init(&pending_reader_condition);
+ 
+     vcard_emul_init(command_line_options);
+ 
++    loop = g_main_loop_new(NULL, true);
++
+     printf("> ");
+     fflush(stdout);
+ 
++#ifdef _WIN32
++    channel_stdin = g_io_channel_win32_new_fd(STDIN_FILENO);
++#else
++    channel_stdin = g_io_channel_unix_new(STDIN_FILENO);
++#endif
++    g_io_add_watch(channel_stdin, G_IO_IN, do_command, NULL);
++#ifdef _WIN32
++    channel_socket = g_io_channel_win32_new_socket(sock);
++#else
++    channel_socket = g_io_channel_unix_new(sock);
++#endif
++    g_io_channel_set_encoding(channel_socket, NULL, NULL);
++    /* we buffer ourself for thread safety reasons */
++    g_io_channel_set_buffered(channel_socket, FALSE);
++
+     /* Send init message, Host responds (and then we send reader attachments) */
+     VSCMsgInit init = {
+         .version = htonl(VSCARD_VERSION),
+@@ -635,28 +752,12 @@ main(
+     };
+     send_msg(VSC_Init, mhHeader.reader_id, &init, sizeof(init));
+ 
+-    do {
+-        fd_set fds;
+-
+-        FD_ZERO(&fds);
+-        FD_SET(1, &fds);
+-        FD_SET(sock, &fds);
++    g_main_loop_run(loop);
++    g_main_loop_unref(loop);
+ 
+-        /* waiting on input from the socket */
+-        rv = select(sock+1, &fds, NULL, NULL, NULL);
+-        if (rv < 0) {
+-            /* handle error */
+-            perror("select");
+-            return 7;
+-        }
+-        if (FD_ISSET(1, &fds)) {
+-            do_command();
+-        }
+-        if (!FD_ISSET(sock, &fds)) {
+-            continue;
+-        }
+-        rv = do_socket_read();
+-    } while (rv >= 0);
++    g_io_channel_unref(channel_stdin);
++    g_io_channel_unref(channel_socket);
++    g_byte_array_unref(socket_to_send);
+ 
+     return 0;
+ }
+-- 
+1.8.3.1
+
diff --git a/0223-libcacard-remove-sql-prefix.patch b/0223-libcacard-remove-sql-prefix.patch
new file mode 100644
index 0000000..ee58836
--- /dev/null
+++ b/0223-libcacard-remove-sql-prefix.patch
@@ -0,0 +1,47 @@
+From 1975b2acbff807d88d494153db64882d19410724 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <mlureau at redhat.com>
+Date: Wed, 20 Mar 2013 14:07:48 +0100
+Subject: [PATCH 223/241] libcacard: remove sql: prefix
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+For some reason, with sql:/ prefix, the PKCS11 modules are not loaded.
+
+This patch goes on top of Alon smartcard series.
+
+Signed-off-by: Marc-André Lureau <mlureau at redhat.com>
+Reviewed-by: Alon Levy <alevy at redhat.com>
+(cherry picked from commit 667e0b4b6806d53e0b46e29a15d24427ef958c78)
+---
+ libcacard/vcard_emul_nss.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
+index 21d4689..6b1ca8a 100644
+--- a/libcacard/vcard_emul_nss.c
++++ b/libcacard/vcard_emul_nss.c
+@@ -893,7 +893,7 @@ vcard_emul_init(const VCardEmulOptions *options)
+     if (options->nss_db) {
+         rv = NSS_Init(options->nss_db);
+     } else {
+-        gchar *path, *db;
++        gchar *path;
+ #ifndef _WIN32
+         path = g_strdup("/etc/pki/nssdb");
+ #else
+@@ -905,10 +905,8 @@ vcard_emul_init(const VCardEmulOptions *options)
+         path = g_build_filename(
+             g_get_system_config_dirs()[0], "pki", "nssdb", NULL);
+ #endif
+-        db = g_strdup_printf("sql:%s", path);
+ 
+-        rv = NSS_Init(db);
+-        g_free(db);
++        rv = NSS_Init(path);
+         g_free(path);
+     }
+     if (rv != SECSuccess) {
+-- 
+1.8.3.1
+
diff --git a/0224-libcacard-remove-default-libcoolkey-loading.patch b/0224-libcacard-remove-default-libcoolkey-loading.patch
new file mode 100644
index 0000000..77cb055
--- /dev/null
+++ b/0224-libcacard-remove-default-libcoolkey-loading.patch
@@ -0,0 +1,64 @@
+From 26acaa4bf064f7608dec08cff4d23769b167dced Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <mlureau at redhat.com>
+Date: Wed, 20 Mar 2013 14:07:49 +0100
+Subject: [PATCH 224/241] libcacard: remove default libcoolkey loading
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Use only the modules defined in the NSS database.
+
+Signed-off-by: Marc-André Lureau <mlureau at redhat.com>
+Reviewed-by: Alon Levy <alevy at redhat.com>
+(cherry picked from commit ad2181f2b612cd8bf0a790faa2a1b51559f7234b)
+---
+ libcacard/vcard_emul_nss.c | 17 +----------------
+ 1 file changed, 1 insertion(+), 16 deletions(-)
+
+diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
+index 6b1ca8a..9ba80fb 100644
+--- a/libcacard/vcard_emul_nss.c
++++ b/libcacard/vcard_emul_nss.c
+@@ -870,7 +870,7 @@ VCardEmulError
+ vcard_emul_init(const VCardEmulOptions *options)
+ {
+     SECStatus rv;
+-    PRBool ret, has_readers = PR_FALSE, need_coolkey_module;
++    PRBool ret, has_readers = PR_FALSE;
+     VReader *vreader;
+     VReaderEmul *vreader_emul;
+     SECMODListLock *module_lock;
+@@ -983,30 +983,15 @@ vcard_emul_init(const VCardEmulOptions *options)
+     /* make sure we have some PKCS #11 module loaded */
+     module_lock = SECMOD_GetDefaultModuleListLock();
+     module_list = SECMOD_GetDefaultModuleList();
+-    need_coolkey_module = !has_readers;
+     SECMOD_GetReadLock(module_lock);
+     for (mlp = module_list; mlp; mlp = mlp->next) {
+         SECMODModule *module = mlp->module;
+         if (module_has_removable_hw_slots(module)) {
+-            need_coolkey_module = PR_FALSE;
+             break;
+         }
+     }
+     SECMOD_ReleaseReadLock(module_lock);
+ 
+-    if (need_coolkey_module) {
+-        SECMODModule *module;
+-        module = SECMOD_LoadUserModule(
+-                    (char *)"library=libcoolkeypk11.so name=Coolkey",
+-                    NULL, PR_FALSE);
+-        if (module == NULL) {
+-            return VCARD_EMUL_FAIL;
+-        }
+-        SECMOD_DestroyModule(module); /* free our reference, Module will still
+-                                       * be on the list.
+-                                       * until we destroy it */
+-    }
+-
+     /* now examine all the slots, finding which should be readers */
+     /* We should control this with options. For now we mirror out any
+      * removable hardware slot */
+-- 
+1.8.3.1
+
diff --git a/0225-dev-smartcard-reader-white-space-fixes.patch b/0225-dev-smartcard-reader-white-space-fixes.patch
new file mode 100644
index 0000000..c00da7d
--- /dev/null
+++ b/0225-dev-smartcard-reader-white-space-fixes.patch
@@ -0,0 +1,54 @@
+From c1a01e889c7562c5e61cbd2da7844697c56940bd Mon Sep 17 00:00:00 2001
+From: Alon Levy <alevy at redhat.com>
+Date: Mon, 4 Mar 2013 18:45:49 +0200
+Subject: [PATCH 225/241] dev-smartcard-reader: white space fixes
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Alon Levy <alevy at redhat.com>
+Reviewed-by: Marc-André Lureau <mlureau at redhat.com>
+(cherry picked from commit 4543d43c6181d90f86fb528430f250810dde03d5)
+---
+ hw/usb/dev-smartcard-reader.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
+index 979a473..24c84ce 100644
+--- a/hw/usb/dev-smartcard-reader.c
++++ b/hw/usb/dev-smartcard-reader.c
+@@ -471,6 +471,7 @@ static const USBDesc desc_ccid = {
+ 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);
+     }
+@@ -482,6 +483,7 @@ static void ccid_card_apdu_from_guest(CCIDCardState *card,
+                                       uint32_t len)
+ {
+     CCIDCardClass *cc = CCID_CARD_GET_CLASS(card);
++
+     if (cc->apdu_from_guest) {
+         cc->apdu_from_guest(card, apdu, len);
+     }
+@@ -490,6 +492,7 @@ static void ccid_card_apdu_from_guest(CCIDCardState *card,
+ static int ccid_card_exitfn(CCIDCardState *card)
+ {
+     CCIDCardClass *cc = CCID_CARD_GET_CLASS(card);
++
+     if (cc->exitfn) {
+         return cc->exitfn(card);
+     }
+@@ -499,6 +502,7 @@ static int ccid_card_exitfn(CCIDCardState *card)
+ static int ccid_card_initfn(CCIDCardState *card)
+ {
+     CCIDCardClass *cc = CCID_CARD_GET_CLASS(card);
++
+     if (cc->initfn) {
+         return cc->initfn(card);
+     }
+-- 
+1.8.3.1
+
diff --git a/0226-dev-smartcard-reader-nicer-debug-messages.patch b/0226-dev-smartcard-reader-nicer-debug-messages.patch
new file mode 100644
index 0000000..660c460
--- /dev/null
+++ b/0226-dev-smartcard-reader-nicer-debug-messages.patch
@@ -0,0 +1,144 @@
+From bd39de640ffd3f552775bfb1a084657872acd114 Mon Sep 17 00:00:00 2001
+From: Alon Levy <alevy at redhat.com>
+Date: Mon, 4 Mar 2013 18:50:33 +0200
+Subject: [PATCH 226/241] dev-smartcard-reader: nicer debug messages
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Alon Levy <alevy at redhat.com>
+Reviewed-by: Marc-André Lureau <mlureau at redhat.com>
+(cherry picked from commit 7e1ac5abe3fbbfee4ddfc2d9971a644bd787e055)
+---
+ hw/usb/dev-smartcard-reader.c | 69 +++++++++++++++++++++++++++++++++++++++----
+ 1 file changed, 63 insertions(+), 6 deletions(-)
+
+diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
+index 24c84ce..173dcc9 100644
+--- a/hw/usb/dev-smartcard-reader.c
++++ b/hw/usb/dev-smartcard-reader.c
+@@ -639,13 +639,47 @@ static void ccid_handle_reset(USBDevice *dev)
+     ccid_reset(s);
+ }
+ 
++static const char *ccid_control_to_str(USBCCIDState *s, int request)
++{
++    switch (request) {
++        /* generic - should be factored out if there are other debugees */
++    case DeviceOutRequest | USB_REQ_SET_ADDRESS:
++        return "(generic) set address";
++    case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
++        return "(generic) get descriptor";
++    case DeviceRequest | USB_REQ_GET_CONFIGURATION:
++        return "(generic) get configuration";
++    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
++        return "(generic) set configuration";
++    case DeviceRequest | USB_REQ_GET_STATUS:
++        return "(generic) get status";
++    case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
++        return "(generic) clear feature";
++    case DeviceOutRequest | USB_REQ_SET_FEATURE:
++        return "(generic) set_feature";
++    case InterfaceRequest | USB_REQ_GET_INTERFACE:
++        return "(generic) get interface";
++    case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
++        return "(generic) set interface";
++        /* class requests */
++    case ClassInterfaceOutRequest | CCID_CONTROL_ABORT:
++        return "ABORT";
++    case ClassInterfaceRequest | CCID_CONTROL_GET_CLOCK_FREQUENCIES:
++        return "GET_CLOCK_FREQUENCIES";
++    case ClassInterfaceRequest | CCID_CONTROL_GET_DATA_RATES:
++        return "GET_DATA_RATES";
++    }
++    return "unknown";
++}
++
+ static void ccid_handle_control(USBDevice *dev, USBPacket *p, int request,
+                                int value, int index, int length, uint8_t *data)
+ {
+     USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
+     int ret;
+ 
+-    DPRINTF(s, 1, "got control %x, value %x\n", request, value);
++    DPRINTF(s, 1, "%s: got control %s (%x), value %x\n", __func__,
++            ccid_control_to_str(s, request), request, value);
+     ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
+     if (ret >= 0) {
+         return;
+@@ -695,7 +729,7 @@ static uint8_t ccid_calc_status(USBCCIDState *s)
+      * bmCommandStatus
+      */
+     uint8_t ret = ccid_card_status(s) | (s->bmCommandStatus << 6);
+-    DPRINTF(s, D_VERBOSE, "status = %d\n", ret);
++    DPRINTF(s, D_VERBOSE, "%s: status = %d\n", __func__, ret);
+     return ret;
+ }
+ 
+@@ -756,7 +790,7 @@ static void ccid_write_data_block(USBCCIDState *s, uint8_t slot, uint8_t seq,
+     p->b.bStatus = ccid_calc_status(s);
+     p->b.bError = s->bError;
+     if (p->b.bError) {
+-        DPRINTF(s, D_VERBOSE, "error %d", p->b.bError);
++        DPRINTF(s, D_VERBOSE, "error %d\n", p->b.bError);
+     }
+     memcpy(p->abData, data, len);
+     ccid_reset_error_status(s);
+@@ -873,6 +907,28 @@ static void ccid_on_apdu_from_guest(USBCCIDState *s, CCID_XferBlock *recv)
+     }
+ }
+ 
++static const char *ccid_message_type_to_str(uint8_t type)
++{
++    switch (type) {
++    case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOn: return "IccPowerOn";
++    case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOff: return "IccPowerOff";
++    case CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus: return "GetSlotStatus";
++    case CCID_MESSAGE_TYPE_PC_to_RDR_XfrBlock: return "XfrBlock";
++    case CCID_MESSAGE_TYPE_PC_to_RDR_GetParameters: return "GetParameters";
++    case CCID_MESSAGE_TYPE_PC_to_RDR_ResetParameters: return "ResetParameters";
++    case CCID_MESSAGE_TYPE_PC_to_RDR_SetParameters: return "SetParameters";
++    case CCID_MESSAGE_TYPE_PC_to_RDR_Escape: return "Escape";
++    case CCID_MESSAGE_TYPE_PC_to_RDR_IccClock: return "IccClock";
++    case CCID_MESSAGE_TYPE_PC_to_RDR_T0APDU: return "T0APDU";
++    case CCID_MESSAGE_TYPE_PC_to_RDR_Secure: return "Secure";
++    case CCID_MESSAGE_TYPE_PC_to_RDR_Mechanical: return "Mechanical";
++    case CCID_MESSAGE_TYPE_PC_to_RDR_Abort: return "Abort";
++    case CCID_MESSAGE_TYPE_PC_to_RDR_SetDataRateAndClockFrequency:
++        return "SetDataRateAndClockFrequency";
++    }
++    return "unknown";
++}
++
+ static void ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
+ {
+     CCID_Header *ccid_header;
+@@ -895,13 +951,15 @@ static void ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
+                 "%s: bad USB_TOKEN_OUT length, should be at least 10 bytes\n",
+                 __func__);
+     } else {
+-        DPRINTF(s, D_MORE_INFO, "%s %x\n", __func__, ccid_header->bMessageType);
++        DPRINTF(s, D_MORE_INFO, "%s %x %s\n", __func__,
++                ccid_header->bMessageType,
++                ccid_message_type_to_str(ccid_header->bMessageType));
+         switch (ccid_header->bMessageType) {
+         case CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus:
+             ccid_write_slot_status(s, ccid_header);
+             break;
+         case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOn:
+-            DPRINTF(s, 1, "PowerOn: %d\n",
++            DPRINTF(s, 1, "%s: PowerOn: %d\n", __func__,
+                 ((CCID_IccPowerOn *)(ccid_header))->bPowerSelect);
+             s->powered = true;
+             if (!ccid_card_inserted(s)) {
+@@ -911,7 +969,6 @@ static void ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
+             ccid_write_data_block_atr(s, ccid_header);
+             break;
+         case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOff:
+-            DPRINTF(s, 1, "PowerOff\n");
+             ccid_reset_error_status(s);
+             s->powered = false;
+             ccid_write_slot_status(s, ccid_header);
+-- 
+1.8.3.1
+
diff --git a/0227-dev-smartcard-reader-remove-aborts-never-triggered-b.patch b/0227-dev-smartcard-reader-remove-aborts-never-triggered-b.patch
new file mode 100644
index 0000000..6306c72
--- /dev/null
+++ b/0227-dev-smartcard-reader-remove-aborts-never-triggered-b.patch
@@ -0,0 +1,71 @@
+From 006440535dd1d581f0e5b7b15295fe511589c3e2 Mon Sep 17 00:00:00 2001
+From: Alon Levy <alevy at redhat.com>
+Date: Mon, 4 Mar 2013 18:55:07 +0200
+Subject: [PATCH 227/241] dev-smartcard-reader: remove aborts (never triggered,
+ but just in case)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Alon Levy <alevy at redhat.com>
+Reviewed-by: Marc-André Lureau <mlureau at redhat.com>
+(cherry picked from commit 47bf53af7507986fc473cb308324340448fd85e7)
+---
+ hw/usb/dev-smartcard-reader.c | 20 ++++++++++++--------
+ 1 file changed, 12 insertions(+), 8 deletions(-)
+
+diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
+index 173dcc9..54ea536 100644
+--- a/hw/usb/dev-smartcard-reader.c
++++ b/hw/usb/dev-smartcard-reader.c
+@@ -796,6 +796,12 @@ static void ccid_write_data_block(USBCCIDState *s, uint8_t slot, uint8_t seq,
+     ccid_reset_error_status(s);
+ }
+ 
++static void ccid_report_error_failed(USBCCIDState *s, uint8_t error)
++{
++    s->bmCommandStatus = COMMAND_STATUS_FAILED;
++    s->bError = error;
++}
++
+ static void ccid_write_data_block_answer(USBCCIDState *s,
+     const uint8_t *data, uint32_t len)
+ {
+@@ -803,7 +809,9 @@ static void ccid_write_data_block_answer(USBCCIDState *s,
+     uint8_t slot;
+ 
+     if (!ccid_has_pending_answers(s)) {
+-        abort();
++        DPRINTF(s, D_WARN, "error: no pending answer to return to guest\n");
++        ccid_report_error_failed(s, ERROR_ICC_MUTE);
++        return;
+     }
+     ccid_remove_pending_answer(s, &slot, &seq);
+     ccid_write_data_block(s, slot, seq, data, len);
+@@ -857,12 +865,6 @@ static void ccid_reset_parameters(USBCCIDState *s)
+    memcpy(s->abProtocolDataStructure, abDefaultProtocolDataStructure, len);
+ }
+ 
+-static void ccid_report_error_failed(USBCCIDState *s, uint8_t error)
+-{
+-    s->bmCommandStatus = COMMAND_STATUS_FAILED;
+-    s->bError = error;
+-}
+-
+ /* NOTE: only a single slot is supported (SLOT_0) */
+ static void ccid_on_slot_change(USBCCIDState *s, bool full)
+ {
+@@ -1129,7 +1131,9 @@ void ccid_card_send_apdu_to_guest(CCIDCardState *card,
+     s->bmCommandStatus = COMMAND_STATUS_NO_ERROR;
+     answer = ccid_peek_next_answer(s);
+     if (answer == NULL) {
+-        abort();
++        DPRINTF(s, D_WARN, "%s: error: unexpected lack of answer\n", __func__);
++        ccid_report_error_failed(s, ERROR_HW_ERROR);
++        return;
+     }
+     DPRINTF(s, 1, "APDU returned to guest %d (answer seq %d, slot %d)\n",
+         len, answer->seq, answer->slot);
+-- 
+1.8.3.1
+
diff --git a/0228-dev-smartcard-reader-support-windows-guest.patch b/0228-dev-smartcard-reader-support-windows-guest.patch
new file mode 100644
index 0000000..6fd2e09
--- /dev/null
+++ b/0228-dev-smartcard-reader-support-windows-guest.patch
@@ -0,0 +1,38 @@
+From 6339bbf28651cbcb5cf24bd1d53cd7b52028ff1b Mon Sep 17 00:00:00 2001
+From: Alon Levy <alevy at redhat.com>
+Date: Mon, 4 Mar 2013 21:40:53 +0200
+Subject: [PATCH 228/241] dev-smartcard-reader: support windows guest
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+By not advertising USB wakeup support (which we don't).
+
+Signed-off-by: Alon Levy <alevy at redhat.com>
+Reviewed-by: Marc-André Lureau <mlureau at redhat.com>
+(cherry picked from commit c5cd7c875608911ec74817d24cd12b825014ba19)
+---
+ hw/usb/dev-smartcard-reader.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
+index 54ea536..db5dd6d 100644
+--- a/hw/usb/dev-smartcard-reader.c
++++ b/hw/usb/dev-smartcard-reader.c
+@@ -359,11 +359,11 @@ static const uint8_t qemu_ccid_descriptor[] = {
+                      * 20000 Short APDU level exchange with CCID
+                      * 40000 Short and Extended APDU level exchange with CCID
+                      *
+-                     * + 100000 USB Wake up signaling supported on card
++                     * 100000 USB Wake up signaling supported on card
+                      * insertion and removal. Must set bit 5 in bmAttributes
+                      * in Configuration descriptor if 100000 is set.
+                      */
+-        0xfe, 0x04, 0x11, 0x00,
++        0xfe, 0x04, 0x01, 0x00,
+                     /*
+                      * u32 dwMaxCCIDMessageLength; For extended APDU in
+                      * [261 + 10 , 65544 + 10]. Otherwise the minimum is
+-- 
+1.8.3.1
+
diff --git a/0229-dev-smartcard-reader-reuse-usb.h-definitions.patch b/0229-dev-smartcard-reader-reuse-usb.h-definitions.patch
new file mode 100644
index 0000000..1616e7a
--- /dev/null
+++ b/0229-dev-smartcard-reader-reuse-usb.h-definitions.patch
@@ -0,0 +1,65 @@
+From b7fd4cdb21c93be3a3e4b2d309f07e56d47eb2a4 Mon Sep 17 00:00:00 2001
+From: Alon Levy <alevy at redhat.com>
+Date: Tue, 5 Mar 2013 15:31:26 +0200
+Subject: [PATCH 229/241] dev-smartcard-reader: reuse usb.h definitions
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Alon Levy <alevy at redhat.com>
+Reviewed-by: Marc-André Lureau <mlureau at redhat.com>
+(cherry picked from commit 693e47738d05463b2743b0a652412d33cf254977)
+---
+ hw/usb/dev-smartcard-reader.c | 16 +++++-----------
+ 1 file changed, 5 insertions(+), 11 deletions(-)
+
+diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
+index db5dd6d..75f813c 100644
+--- a/hw/usb/dev-smartcard-reader.c
++++ b/hw/usb/dev-smartcard-reader.c
+@@ -68,12 +68,6 @@ do { \
+ #define BULK_IN_BUF_SIZE 384
+ #define BULK_IN_PENDING_NUM 8
+ 
+-#define InterfaceOutClass \
+-    ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)<<8)
+-
+-#define InterfaceInClass  \
+-    ((USB_DIR_IN  | USB_TYPE_CLASS | USB_RECIP_INTERFACE)<<8)
+-
+ #define CCID_MAX_PACKET_SIZE                64
+ 
+ #define CCID_CONTROL_ABORT                  0x1
+@@ -410,8 +404,8 @@ static const USBDescStrings desc_strings = {
+ static const USBDescIface desc_iface0 = {
+     .bInterfaceNumber              = 0,
+     .bNumEndpoints                 = 3,
+-    .bInterfaceClass               = 0x0b,
+-    .bInterfaceSubClass            = 0x00,
++    .bInterfaceClass               = USB_CLASS_CSCID,
++    .bInterfaceSubClass            = USB_SUBCLASS_UNDEFINED,
+     .bInterfaceProtocol            = 0x00,
+     .iInterface                    = STR_INTERFACE,
+     .ndesc                         = 1,
+@@ -687,15 +681,15 @@ static void ccid_handle_control(USBDevice *dev, USBPacket *p, int request,
+ 
+     switch (request) {
+         /* Class specific requests.  */
+-    case InterfaceOutClass | CCID_CONTROL_ABORT:
++    case ClassInterfaceOutRequest | CCID_CONTROL_ABORT:
+         DPRINTF(s, 1, "ccid_control abort UNIMPLEMENTED\n");
+         p->status = USB_RET_STALL;
+         break;
+-    case InterfaceInClass | CCID_CONTROL_GET_CLOCK_FREQUENCIES:
++    case ClassInterfaceRequest | CCID_CONTROL_GET_CLOCK_FREQUENCIES:
+         DPRINTF(s, 1, "ccid_control get clock frequencies UNIMPLEMENTED\n");
+         p->status = USB_RET_STALL;
+         break;
+-    case InterfaceInClass | CCID_CONTROL_GET_DATA_RATES:
++    case ClassInterfaceRequest | CCID_CONTROL_GET_DATA_RATES:
+         DPRINTF(s, 1, "ccid_control get data rates UNIMPLEMENTED\n");
+         p->status = USB_RET_STALL;
+         break;
+-- 
+1.8.3.1
+
diff --git a/0230-libcacard-change-default-ATR.patch b/0230-libcacard-change-default-ATR.patch
new file mode 100644
index 0000000..3cfee43
--- /dev/null
+++ b/0230-libcacard-change-default-ATR.patch
@@ -0,0 +1,42 @@
+From b3d57573e23a456b2c21f045b153e2c0a621f886 Mon Sep 17 00:00:00 2001
+From: Alon Levy <alevy at redhat.com>
+Date: Tue, 5 Mar 2013 15:35:24 +0200
+Subject: [PATCH 230/241] libcacard: change default ATR
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Alon Levy <alevy at redhat.com>
+Reviewed-by: Marc-André Lureau <mlureau at redhat.com>
+(cherry picked from commit a26dfd95d33d650f9f9f93b6ee6f03be925db1a8)
+---
+ libcacard/vcardt.h | 12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/libcacard/vcardt.h b/libcacard/vcardt.h
+index 538bdde..3b9a619 100644
+--- a/libcacard/vcardt.h
++++ b/libcacard/vcardt.h
+@@ -26,9 +26,17 @@ typedef struct VCardEmulStruct VCardEmul;
+ #define MAX_CHANNEL 4
+ 
+ /* create an ATR with appropriate historical bytes */
+-#define VCARD_ATR_PREFIX(size) 0x3b, 0x66+(size), 0x00, 0xff, \
+-                               'V', 'C', 'A', 'R', 'D', '_'
++#define TS_DIRECT_CONVENTION 0x3b
++#define TA_PRESENT 0x10
++#define TB_PRESENT 0x20
++#define TC_PRESENT 0x40
++#define TD_PRESENT 0x80
+ 
++#define VCARD_ATR_PREFIX(size) \
++    TS_DIRECT_CONVENTION, \
++    TD_PRESENT + (6 + size), \
++    0x00, \
++    'V', 'C', 'A', 'R', 'D', '_'
+ 
+ typedef enum {
+     VCARD_DONE,
+-- 
+1.8.3.1
+
diff --git a/0231-ccid-card-passthru-add-atr-check.patch b/0231-ccid-card-passthru-add-atr-check.patch
new file mode 100644
index 0000000..abae187
--- /dev/null
+++ b/0231-ccid-card-passthru-add-atr-check.patch
@@ -0,0 +1,95 @@
+From 1c4d96f6622f00c4d4b84b5e17f8e42dcb5b7501 Mon Sep 17 00:00:00 2001
+From: Alon Levy <alevy at redhat.com>
+Date: Mon, 4 Mar 2013 18:39:09 +0200
+Subject: [PATCH 231/241] ccid-card-passthru: add atr check
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Alon Levy <alevy at redhat.com>
+Reviewed-by: Marc-André Lureau <mlureau at redhat.com>
+(cherry picked from commit 0e61400c1941aabc9f45d5ff961b57337c7caac6)
+---
+ hw/ccid-card-passthru.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 59 insertions(+)
+
+diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c
+index 62070db..7fecd10 100644
+--- a/hw/ccid-card-passthru.c
++++ b/hw/ccid-card-passthru.c
+@@ -138,6 +138,59 @@ static void ccid_card_vscard_handle_init(
+     ccid_card_vscard_send_init(card);
+ }
+ 
++static int check_atr(PassthruState *card, uint8_t *data, int len)
++{
++    int historical_length, opt_bytes;
++    int td_count = 0;
++    int td;
++
++    if (len < 2) {
++        return 0;
++    }
++    historical_length = data[1] & 0xf;
++    opt_bytes = 0;
++    if (data[0] != 0x3b && data[0] != 0x3f) {
++        DPRINTF(card, D_WARN, "atr's T0 is 0x%X, not in {0x3b, 0x3f}\n",
++                data[0]);
++        return 0;
++    }
++    td_count = 0;
++    td = data[1] >> 4;
++    while (td && td_count < 2 && opt_bytes + historical_length + 2 < len) {
++        td_count++;
++        if (td & 0x1) {
++            opt_bytes++;
++        }
++        if (td & 0x2) {
++            opt_bytes++;
++        }
++        if (td & 0x4) {
++            opt_bytes++;
++        }
++        if (td & 0x8) {
++            opt_bytes++;
++            td = data[opt_bytes + 2] >> 4;
++        }
++    }
++    if (len < 2 + historical_length + opt_bytes) {
++        DPRINTF(card, D_WARN,
++            "atr too short: len %d, but historical_len %d, T1 0x%X\n",
++            len, historical_length, data[1]);
++        return 0;
++    }
++    if (len > 2 + historical_length + opt_bytes) {
++        DPRINTF(card, D_WARN,
++            "atr too long: len %d, but hist/opt %d/%d, T1 0x%X\n",
++            len, historical_length, opt_bytes, data[1]);
++        /* let it through */
++    }
++    DPRINTF(card, D_VERBOSE,
++            "atr passes check: %d total length, %d historical, %d optional\n",
++            len, historical_length, opt_bytes);
++
++    return 1;
++}
++
+ static void ccid_card_vscard_handle_message(PassthruState *card,
+     VSCMsgHeader *scr_msg_header)
+ {
+@@ -152,6 +205,12 @@ static void ccid_card_vscard_handle_message(PassthruState *card,
+                                         VSC_GENERAL_ERROR);
+             break;
+         }
++        if (!check_atr(card, data, scr_msg_header->length)) {
++            error_report("ATR is inconsistent, ignoring");
++            ccid_card_vscard_send_error(card, scr_msg_header->reader_id,
++                                        VSC_GENERAL_ERROR);
++            break;
++        }
+         memcpy(card->atr, data, scr_msg_header->length);
+         card->atr_length = scr_msg_header->length;
+         ccid_card_card_inserted(&card->base);
+-- 
+1.8.3.1
+
diff --git a/0232-ccid-card-passthru-dev-smartcard-reader-add-debug-en.patch b/0232-ccid-card-passthru-dev-smartcard-reader-add-debug-en.patch
new file mode 100644
index 0000000..39cb23e
--- /dev/null
+++ b/0232-ccid-card-passthru-dev-smartcard-reader-add-debug-en.patch
@@ -0,0 +1,110 @@
+From f462152289d55ae01456d1d9122e26ff63407520 Mon Sep 17 00:00:00 2001
+From: Alon Levy <alevy at redhat.com>
+Date: Mon, 4 Mar 2013 18:41:28 +0200
+Subject: [PATCH 232/241] ccid-card-passthru, dev-smartcard-reader: add debug
+ environment variables
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Introduces a new utility function: parse_debug_env to avoid code
+duplication.
+
+This overrides whatever debug value is set on the corresponding devices
+from the command line, and is meant to ease the usage with any
+management stack. For libvirt you can set environment variables by
+extending the dom namespace, i.e:
+
+<domain type='kvm' id='3' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
+  <qemu:commandline>
+    <qemu:env name='QEMU_CCID_PASSTHRU_DEBUG' value='4'/>
+    <qemu:env name='QEMU_CCID_DEBUG' value='4'/>
+  </qemu:commandline>
+</domain>
+
+Signed-off-by: Alon Levy <alevy at redhat.com>
+Reviewed-by: Marc-André Lureau <mlureau at redhat.com>
+(cherry picked from commit b16352acf3105000e14f194b556e159d5d06cff9)
+
+Conflicts:
+	include/qemu-common.h
+---
+ hw/ccid-card-passthru.c       |  2 ++
+ hw/usb/dev-smartcard-reader.c |  1 +
+ include/qemu-common.h         |  5 +++++
+ util/cutils.c                 | 23 +++++++++++++++++++++++
+ 4 files changed, 31 insertions(+)
+
+diff --git a/hw/ccid-card-passthru.c b/hw/ccid-card-passthru.c
+index 7fecd10..4026ccd 100644
+--- a/hw/ccid-card-passthru.c
++++ b/hw/ccid-card-passthru.c
+@@ -353,6 +353,8 @@ static int passthru_initfn(CCIDCardState *base)
+         error_report("missing chardev");
+         return -1;
+     }
++    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);
+diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
+index 75f813c..09c2403 100644
+--- a/hw/usb/dev-smartcard-reader.c
++++ b/hw/usb/dev-smartcard-reader.c
+@@ -1260,6 +1260,7 @@ static int ccid_initfn(USBDevice *dev)
+     s->bulk_out_pos = 0;
+     ccid_reset_parameters(s);
+     ccid_reset(s);
++    s->debug = parse_debug_env("QEMU_CCID_DEBUG", D_VERBOSE, s->debug);
+     return 0;
+ }
+ 
+diff --git a/include/qemu-common.h b/include/qemu-common.h
+index 80016ad..77d0980 100644
+--- a/include/qemu-common.h
++++ b/include/qemu-common.h
+@@ -430,4 +430,9 @@ int64_t pow2floor(int64_t value);
+ int uleb128_encode_small(uint8_t *out, uint32_t n);
+ int uleb128_decode_small(const uint8_t *in, uint32_t *n);
+ 
++/*
++ * helper to parse debug environment variables
++ */
++int parse_debug_env(const char *name, int max, int initial);
++
+ #endif
+diff --git a/util/cutils.c b/util/cutils.c
+index 1439da4..32e1f5b 100644
+--- a/util/cutils.c
++++ b/util/cutils.c
+@@ -422,3 +422,26 @@ int uleb128_decode_small(const uint8_t *in, uint32_t *n)
+         return 2;
+     }
+ }
++
++/*
++ * helper to parse debug environment variables
++ */
++int parse_debug_env(const char *name, int max, int initial)
++{
++    char *debug_env = getenv(name);
++    char *inv = NULL;
++    int debug;
++
++    if (!debug_env) {
++        return initial;
++    }
++    debug = strtol(debug_env, &inv, 10);
++    if (inv == debug_env) {
++        return initial;
++    }
++    if (debug < 0 || debug > max) {
++        fprintf(stderr, "warning: %s not in [0, %d]", name, max);
++        return initial;
++    }
++    return debug;
++}
+-- 
+1.8.3.1
+
diff --git a/0233-dev-smartcard-reader-define-structs-for-CCID_Paramet.patch b/0233-dev-smartcard-reader-define-structs-for-CCID_Paramet.patch
new file mode 100644
index 0000000..89f2fb5
--- /dev/null
+++ b/0233-dev-smartcard-reader-define-structs-for-CCID_Paramet.patch
@@ -0,0 +1,161 @@
+From 4d36e75eb55c7ee557bebabd6fe33c5a65d52228 Mon Sep 17 00:00:00 2001
+From: Alon Levy <alevy at redhat.com>
+Date: Mon, 4 Mar 2013 18:57:45 +0200
+Subject: [PATCH 233/241] dev-smartcard-reader: define structs for
+ CCID_Parameter internals
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Alon Levy <alevy at redhat.com>
+Reviewed-by: Marc-André Lureau <mlureau at redhat.com>
+(cherry picked from commit 4942d6c39477f441a106430ab11f85806b4532f5)
+---
+ hw/usb/dev-smartcard-reader.c | 74 +++++++++++++++++++++++++++----------------
+ 1 file changed, 47 insertions(+), 27 deletions(-)
+
+diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
+index 09c2403..f2cab09 100644
+--- a/hw/usb/dev-smartcard-reader.c
++++ b/hw/usb/dev-smartcard-reader.c
+@@ -189,10 +189,34 @@ typedef struct QEMU_PACKED CCID_SlotStatus {
+     uint8_t     bClockStatus;
+ } CCID_SlotStatus;
+ 
++typedef struct QEMU_PACKED CCID_T0ProtocolDataStructure {
++    uint8_t     bmFindexDindex;
++    uint8_t     bmTCCKST0;
++    uint8_t     bGuardTimeT0;
++    uint8_t     bWaitingIntegerT0;
++    uint8_t     bClockStop;
++} CCID_T0ProtocolDataStructure;
++
++typedef struct QEMU_PACKED CCID_T1ProtocolDataStructure {
++    uint8_t     bmFindexDindex;
++    uint8_t     bmTCCKST1;
++    uint8_t     bGuardTimeT1;
++    uint8_t     bWaitingIntegerT1;
++    uint8_t     bClockStop;
++    uint8_t     bIFSC;
++    uint8_t     bNadValue;
++} CCID_T1ProtocolDataStructure;
++
++typedef union CCID_ProtocolDataStructure {
++    CCID_T0ProtocolDataStructure t0;
++    CCID_T1ProtocolDataStructure t1;
++    uint8_t data[7]; /* must be = max(sizeof(t0), sizeof(t1)) */
++} CCID_ProtocolDataStructure;
++
+ typedef struct QEMU_PACKED CCID_Parameter {
+     CCID_BULK_IN b;
+     uint8_t     bProtocolNum;
+-    uint8_t     abProtocolDataStructure[0];
++    CCID_ProtocolDataStructure abProtocolDataStructure;
+ } CCID_Parameter;
+ 
+ typedef struct QEMU_PACKED CCID_DataBlock {
+@@ -224,7 +248,7 @@ typedef struct QEMU_PACKED CCID_SetParameters {
+     CCID_Header hdr;
+     uint8_t     bProtocolNum;
+     uint16_t   abRFU;
+-    uint8_t    abProtocolDataStructure[0];
++    CCID_ProtocolDataStructure abProtocolDataStructure;
+ } CCID_SetParameters;
+ 
+ typedef struct CCID_Notify_Slot_Change {
+@@ -254,8 +278,6 @@ typedef struct CCIDBus {
+     BusState qbus;
+ } CCIDBus;
+ 
+-#define MAX_PROTOCOL_SIZE   7
+-
+ /*
+  * powered - defaults to true, changed by PowerOn/PowerOff messages
+  */
+@@ -279,7 +301,7 @@ typedef struct USBCCIDState {
+     uint8_t  bError;
+     uint8_t  bmCommandStatus;
+     uint8_t  bProtocolNum;
+-    uint8_t  abProtocolDataStructure[MAX_PROTOCOL_SIZE];
++    CCID_ProtocolDataStructure abProtocolDataStructure;
+     uint32_t ulProtocolDataStructureSize;
+     uint32_t state_vmstate;
+     uint32_t migration_target_ip;
+@@ -765,7 +787,7 @@ static void ccid_write_parameters(USBCCIDState *s, CCID_Header *recv)
+     h->b.bStatus = ccid_calc_status(s);
+     h->b.bError = s->bError;
+     h->bProtocolNum = s->bProtocolNum;
+-    memcpy(h->abProtocolDataStructure, s->abProtocolDataStructure, len);
++    h->abProtocolDataStructure = s->abProtocolDataStructure;
+     ccid_reset_error_status(s);
+ }
+ 
+@@ -825,38 +847,36 @@ static void ccid_write_data_block_atr(USBCCIDState *s, CCID_Header *recv)
+ static void ccid_set_parameters(USBCCIDState *s, CCID_Header *recv)
+ {
+     CCID_SetParameters *ph = (CCID_SetParameters *) recv;
+-    uint32_t len = 0;
+-    if ((ph->bProtocolNum & 3) == 0) {
+-        len = 5;
+-    }
+-    if ((ph->bProtocolNum & 3) == 1) {
+-        len = 7;
+-    }
+-    if (len == 0) {
+-        s->bmCommandStatus = COMMAND_STATUS_FAILED;
+-        s->bError = 7; /* Protocol invalid or not supported */
++    uint32_t protocol_num = ph->bProtocolNum & 3;
++
++    if (protocol_num != 0 && protocol_num != 1) {
++        ccid_report_error_failed(s, ERROR_CMD_NOT_SUPPORTED);
+         return;
+     }
+-    s->bProtocolNum = ph->bProtocolNum;
+-    memcpy(s->abProtocolDataStructure, ph->abProtocolDataStructure, len);
+-    s->ulProtocolDataStructureSize = len;
+-    DPRINTF(s, 1, "%s: using len %d\n", __func__, len);
++    s->bProtocolNum = protocol_num;
++    s->abProtocolDataStructure = ph->abProtocolDataStructure;
+ }
+ 
+ /*
+  * must be 5 bytes for T=0, 7 bytes for T=1
+  * See page 52
+  */
+-static const uint8_t abDefaultProtocolDataStructure[7] = {
+-    0x77, 0x00, 0x00, 0x00, 0x00, 0xfe /*IFSC*/, 0x00 /*NAD*/ };
++static const CCID_ProtocolDataStructure defaultProtocolDataStructure = {
++    .t1 = {
++        .bmFindexDindex = 0x77,
++        .bmTCCKST1 = 0x00,
++        .bGuardTimeT1 = 0x00,
++        .bWaitingIntegerT1 = 0x00,
++        .bClockStop = 0x00,
++        .bIFSC = 0xfe,
++        .bNadValue = 0x00,
++    }
++};
+ 
+ static void ccid_reset_parameters(USBCCIDState *s)
+ {
+-   uint32_t len = sizeof(abDefaultProtocolDataStructure);
+-
+    s->bProtocolNum = 1; /* T=1 */
+-   s->ulProtocolDataStructureSize = len;
+-   memcpy(s->abProtocolDataStructure, abDefaultProtocolDataStructure, len);
++   s->abProtocolDataStructure = defaultProtocolDataStructure;
+ }
+ 
+ /* NOTE: only a single slot is supported (SLOT_0) */
+@@ -1345,7 +1365,7 @@ static VMStateDescription ccid_vmstate = {
+         VMSTATE_UINT8(bError, USBCCIDState),
+         VMSTATE_UINT8(bmCommandStatus, USBCCIDState),
+         VMSTATE_UINT8(bProtocolNum, USBCCIDState),
+-        VMSTATE_BUFFER(abProtocolDataStructure, USBCCIDState),
++        VMSTATE_BUFFER(abProtocolDataStructure.data, USBCCIDState),
+         VMSTATE_UINT32(ulProtocolDataStructureSize, USBCCIDState),
+         VMSTATE_STRUCT_ARRAY(bulk_in_pending, USBCCIDState,
+                        BULK_IN_PENDING_NUM, 1, bulk_in_vmstate, BulkIn),
+-- 
+1.8.3.1
+
diff --git a/0234-dev-smartcard-reader-change-default-protocol-to-T-0.patch b/0234-dev-smartcard-reader-change-default-protocol-to-T-0.patch
new file mode 100644
index 0000000..05e11ea
--- /dev/null
+++ b/0234-dev-smartcard-reader-change-default-protocol-to-T-0.patch
@@ -0,0 +1,50 @@
+From f7019fa4fc6d883f1922bb0e3b18ceb3a628b340 Mon Sep 17 00:00:00 2001
+From: Alon Levy <alevy at redhat.com>
+Date: Wed, 27 Mar 2013 10:14:15 +0200
+Subject: [PATCH 234/241] dev-smartcard-reader: change default protocol to T=0
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+We don't support T=1 so we shouldn't advertise it by default.
+
+Two independent changes:
+* Default ATR
+ sets T=0. This gets overwritten by the client provided ATR later.
+* Class descriptor
+ changes dwAdvertise dwProtocols.PPPP to 0x1 and dwProtocols.RRRR=0 per spec.
+
+Signed-off-by: Alon Levy <alevy at redhat.com>
+Reviewed-by: Marc-André Lureau <mlureau at redhat.com>
+(cherry picked from commit d7d218ef02d87c637d20d64da8f575d434ff6f78)
+---
+ hw/usb/dev-smartcard-reader.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
+index f2cab09..e97dfcb 100644
+--- a/hw/usb/dev-smartcard-reader.c
++++ b/hw/usb/dev-smartcard-reader.c
+@@ -335,8 +335,8 @@ static const uint8_t qemu_ccid_descriptor[] = {
+                      */
+         0x07,       /* u8  bVoltageSupport; 01h - 5.0v, 02h - 3.0, 03 - 1.8 */
+ 
+-        0x03, 0x00, /* u32 dwProtocols; RRRR PPPP. RRRR = 0000h.*/
+-        0x00, 0x00, /* PPPP: 0001h = Protocol T=0, 0002h = Protocol T=1 */
++        0x00, 0x00, /* u32 dwProtocols; RRRR PPPP. RRRR = 0000h.*/
++        0x01, 0x00, /* PPPP: 0001h = Protocol T=0, 0002h = Protocol T=1 */
+                     /* u32 dwDefaultClock; in kHZ (0x0fa0 is 4 MHz) */
+         0xa0, 0x0f, 0x00, 0x00,
+                     /* u32 dwMaximumClock; */
+@@ -875,7 +875,7 @@ static const CCID_ProtocolDataStructure defaultProtocolDataStructure = {
+ 
+ static void ccid_reset_parameters(USBCCIDState *s)
+ {
+-   s->bProtocolNum = 1; /* T=1 */
++   s->bProtocolNum = 0; /* T=0 */
+    s->abProtocolDataStructure = defaultProtocolDataStructure;
+ }
+ 
+-- 
+1.8.3.1
+
diff --git a/0235-dev-smartcard-reader-copy-atr-protocol-to-ccid-param.patch b/0235-dev-smartcard-reader-copy-atr-protocol-to-ccid-param.patch
new file mode 100644
index 0000000..e0be516
--- /dev/null
+++ b/0235-dev-smartcard-reader-copy-atr-protocol-to-ccid-param.patch
@@ -0,0 +1,85 @@
+From 2e26deacddb52bb3f7eb100ac5fe9709d6089cf3 Mon Sep 17 00:00:00 2001
+From: Alon Levy <alevy at redhat.com>
+Date: Mon, 4 Mar 2013 18:58:29 +0200
+Subject: [PATCH 235/241] dev-smartcard-reader: copy atr protocol to ccid
+ parameters
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Adds todos.
+
+Signed-off-by: Alon Levy <alevy at redhat.com>
+Reviewed-by: Marc-André Lureau <mlureau at redhat.com>
+(cherry picked from commit 2f8f916b6d4482976bb5cf179f65aa2cfcd1aec9)
+---
+ hw/usb/dev-smartcard-reader.c | 45 +++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 45 insertions(+)
+
+diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
+index e97dfcb..4e08f9b 100644
+--- a/hw/usb/dev-smartcard-reader.c
++++ b/hw/usb/dev-smartcard-reader.c
+@@ -833,14 +833,59 @@ static void ccid_write_data_block_answer(USBCCIDState *s,
+     ccid_write_data_block(s, slot, seq, data, len);
+ }
+ 
++static uint8_t atr_get_protocol_num(const uint8_t *atr, uint32_t len)
++{
++    int i;
++
++    if (len < 2 || !(atr[1] & 0x80)) {
++        /* too short or TD1 not included */
++        return 0; /* T=0, default */
++    }
++    i = 1 + !!(atr[1] & 0x10) + !!(atr[1] & 0x20) + !!(atr[1] & 0x40);
++    i += !!(atr[1] & 0x80);
++    return atr[i] & 0x0f;
++}
++
+ static void ccid_write_data_block_atr(USBCCIDState *s, CCID_Header *recv)
+ {
+     const uint8_t *atr = NULL;
+     uint32_t len = 0;
++    uint8_t atr_protocol_num;
++    CCID_T0ProtocolDataStructure *t0 = &s->abProtocolDataStructure.t0;
++    CCID_T1ProtocolDataStructure *t1 = &s->abProtocolDataStructure.t1;
+ 
+     if (s->card) {
+         atr = ccid_card_get_atr(s->card, &len);
+     }
++    atr_protocol_num = atr_get_protocol_num(atr, len);
++    DPRINTF(s, D_VERBOSE, "%s: atr contains protocol=%d\n", __func__,
++            atr_protocol_num);
++    /* set parameters from ATR - see spec page 109 */
++    s->bProtocolNum = (atr_protocol_num <= 1 ? atr_protocol_num
++                                             : s->bProtocolNum);
++    switch (atr_protocol_num) {
++    case 0:
++        /* TODO: unimplemented ATR T0 parameters */
++        t0->bmFindexDindex = 0;
++        t0->bmTCCKST0 = 0;
++        t0->bGuardTimeT0 = 0;
++        t0->bWaitingIntegerT0 = 0;
++        t0->bClockStop = 0;
++        break;
++    case 1:
++        /* TODO: unimplemented ATR T1 parameters */
++        t1->bmFindexDindex = 0;
++        t1->bmTCCKST1 = 0;
++        t1->bGuardTimeT1 = 0;
++        t1->bWaitingIntegerT1 = 0;
++        t1->bClockStop = 0;
++        t1->bIFSC = 0;
++        t1->bNadValue = 0;
++        break;
++    default:
++        DPRINTF(s, D_WARN, "%s: error: unsupported ATR protocol %d\n",
++                __func__, atr_protocol_num);
++    }
+     ccid_write_data_block(s, recv->bSlot, recv->bSeq, atr, len);
+ }
+ 
+-- 
+1.8.3.1
+
diff --git a/0236-libcacard-vreader-add-debugging-messages-for-apdu.patch b/0236-libcacard-vreader-add-debugging-messages-for-apdu.patch
new file mode 100644
index 0000000..20dffe4
--- /dev/null
+++ b/0236-libcacard-vreader-add-debugging-messages-for-apdu.patch
@@ -0,0 +1,169 @@
+From 71560a321c2c7678191f0f7da42f25917ed40974 Mon Sep 17 00:00:00 2001
+From: Alon Levy <alevy at redhat.com>
+Date: Tue, 5 Mar 2013 15:32:19 +0200
+Subject: [PATCH 236/241] libcacard/vreader: add debugging messages for apdu
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Using g_debug with log domain libcacard
+
+Signed-off-by: Alon Levy <alevy at redhat.com>
+Reviewed-by: Marc-André Lureau <mlureau at redhat.com>
+(cherry picked from commit 7a6858962457c54be44715d6562504c765d9ea76)
+---
+ libcacard/cac.c     |  7 -----
+ libcacard/cac.h     |  8 ++++++
+ libcacard/vreader.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 85 insertions(+), 7 deletions(-)
+
+diff --git a/libcacard/cac.c b/libcacard/cac.c
+index 927a4ca..5864539 100644
+--- a/libcacard/cac.c
++++ b/libcacard/cac.c
+@@ -12,13 +12,6 @@
+ #include "vcard_emul.h"
+ #include "card_7816.h"
+ 
+-#define CAC_GET_PROPERTIES  0x56
+-#define CAC_GET_ACR         0x4c
+-#define CAC_READ_BUFFER     0x52
+-#define CAC_UPDATE_BUFFER   0x58
+-#define CAC_SIGN_DECRYPT    0x42
+-#define CAC_GET_CERTIFICATE 0x36
+-
+ /* private data for PKI applets */
+ typedef struct CACPKIAppletDataStruct {
+     unsigned char *cert;
+diff --git a/libcacard/cac.h b/libcacard/cac.h
+index 15a61be..d24a2a8 100644
+--- a/libcacard/cac.h
++++ b/libcacard/cac.h
+@@ -9,6 +9,14 @@
+ #define CAC_H 1
+ #include "vcard.h"
+ #include "vreader.h"
++
++#define CAC_GET_PROPERTIES  0x56
++#define CAC_GET_ACR         0x4c
++#define CAC_READ_BUFFER     0x52
++#define CAC_UPDATE_BUFFER   0x58
++#define CAC_SIGN_DECRYPT    0x42
++#define CAC_GET_CERTIFICATE 0x36
++
+ /*
+  * Initialize the cac card. This is the only public function in this file. All
+  * the rest are connected through function pointers.
+diff --git a/libcacard/vreader.c b/libcacard/vreader.c
+index f3efc27..5793d73 100644
+--- a/libcacard/vreader.c
++++ b/libcacard/vreader.c
+@@ -5,6 +5,12 @@
+  * See the COPYING.LIB file in the top-level directory.
+  */
+ 
++#ifdef G_LOG_DOMAIN
++#undef G_LOG_DOMAIN
++#endif
++#define G_LOG_DOMAIN "libcacard"
++#include <glib.h>
++
+ #include "qemu-common.h"
+ #include "qemu/thread.h"
+ 
+@@ -13,6 +19,9 @@
+ #include "card_7816.h"
+ #include "vreader.h"
+ #include "vevent.h"
++#include "cac.h" /* just for debugging defines */
++
++#define LIBCACARD_LOG_DOMAIN "libcacard"
+ 
+ struct VReaderStruct {
+     int    reference_count;
+@@ -24,6 +33,66 @@ struct VReaderStruct {
+     VReaderEmulFree reader_private_free;
+ };
+ 
++/*
++ * Debug helpers
++ */
++
++static const char *
++apdu_ins_to_string(int ins)
++{
++    switch (ins) {
++    case VCARD7816_INS_MANAGE_CHANNEL:
++        return "manage channel";
++    case VCARD7816_INS_EXTERNAL_AUTHENTICATE:
++        return "external authenticate";
++    case VCARD7816_INS_GET_CHALLENGE:
++        return "get challenge";
++    case VCARD7816_INS_INTERNAL_AUTHENTICATE:
++        return "internal authenticate";
++    case VCARD7816_INS_ERASE_BINARY:
++        return "erase binary";
++    case VCARD7816_INS_READ_BINARY:
++        return "read binary";
++    case VCARD7816_INS_WRITE_BINARY:
++        return "write binary";
++    case VCARD7816_INS_UPDATE_BINARY:
++        return "update binary";
++    case VCARD7816_INS_READ_RECORD:
++        return "read record";
++    case VCARD7816_INS_WRITE_RECORD:
++        return "write record";
++    case VCARD7816_INS_UPDATE_RECORD:
++        return "update record";
++    case VCARD7816_INS_APPEND_RECORD:
++        return "append record";
++    case VCARD7816_INS_ENVELOPE:
++        return "envelope";
++    case VCARD7816_INS_PUT_DATA:
++        return "put data";
++    case VCARD7816_INS_GET_DATA:
++        return "get data";
++    case VCARD7816_INS_SELECT_FILE:
++        return "select file";
++    case VCARD7816_INS_VERIFY:
++        return "verify";
++    case VCARD7816_INS_GET_RESPONSE:
++        return "get response";
++    case CAC_GET_PROPERTIES:
++        return "get properties";
++    case CAC_GET_ACR:
++        return "get acr";
++    case CAC_READ_BUFFER:
++        return "read buffer";
++    case CAC_UPDATE_BUFFER:
++        return "update buffer";
++    case CAC_SIGN_DECRYPT:
++        return "sign decrypt";
++    case CAC_GET_CERTIFICATE:
++        return "get certificate";
++    }
++    return "unknown";
++}
++
+ /* manage locking */
+ static inline void
+ vreader_lock(VReader *reader)
+@@ -204,7 +273,15 @@ vreader_xfr_bytes(VReader *reader,
+         response = vcard_make_response(status);
+         card_status = VCARD_DONE;
+     } else {
++        g_debug("%s: CLS=0x%x,INS=0x%x,P1=0x%x,P2=0x%x,Lc=%d,Le=%d %s\n",
++              __func__, apdu->a_cla, apdu->a_ins, apdu->a_p1, apdu->a_p2,
++              apdu->a_Lc, apdu->a_Le, apdu_ins_to_string(apdu->a_ins));
+         card_status = vcard_process_apdu(card, apdu, &response);
++        if (response) {
++            g_debug("%s: status=%d sw1=0x%x sw2=0x%x len=%d (total=%d)\n",
++                  __func__, response->b_status, response->b_sw1,
++                  response->b_sw2, response->b_len, response->b_total_len);
++        }
+     }
+     assert(card_status == VCARD_DONE);
+     if (card_status == VCARD_DONE) {
+-- 
+1.8.3.1
+
diff --git a/0237-libcacard-move-atr-setting-from-macro-to-function.patch b/0237-libcacard-move-atr-setting-from-macro-to-function.patch
new file mode 100644
index 0000000..d622ae2
--- /dev/null
+++ b/0237-libcacard-move-atr-setting-from-macro-to-function.patch
@@ -0,0 +1,161 @@
+From 703a72f26668f26f2bb98851f1a2edd9a8681f86 Mon Sep 17 00:00:00 2001
+From: Alon Levy <alevy at redhat.com>
+Date: Tue, 5 Mar 2013 16:27:43 +0200
+Subject: [PATCH 237/241] libcacard: move atr setting from macro to function
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Only because qemu's checkpatch complains about it.
+
+Signed-off-by: Alon Levy <alevy at redhat.com>
+Reviewed-by: Marc-André Lureau <mlureau at redhat.com>
+(cherry picked from commit 0b6a16c1a47b622b1a692ab179013d9e30e9cf3b)
+---
+ Makefile.objs               |  1 +
+ libcacard/vcard_emul_nss.c  | 14 +++++++++++---
+ libcacard/vcardt.c          | 40 ++++++++++++++++++++++++++++++++++++++++
+ libcacard/vcardt.h          | 13 -------------
+ libcacard/vcardt_internal.h |  6 ++++++
+ 5 files changed, 58 insertions(+), 16 deletions(-)
+ create mode 100644 libcacard/vcardt.c
+ create mode 100644 libcacard/vcardt_internal.h
+
+diff --git a/Makefile.objs b/Makefile.objs
+index 3884790..729be2b 100644
+--- a/Makefile.objs
++++ b/Makefile.objs
+@@ -32,6 +32,7 @@ libcacard-y += libcacard/vcard.o libcacard/vreader.o
+ libcacard-y += libcacard/vcard_emul_nss.o
+ libcacard-y += libcacard/vcard_emul_type.o
+ libcacard-y += libcacard/card_7816.o
++libcacard-y += libcacard/vcardt.o
+ 
+ ######################################################################
+ # Target independent part of system emulation. The long term path is to
+diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
+index 9ba80fb..1a3e568 100644
+--- a/libcacard/vcard_emul_nss.c
++++ b/libcacard/vcard_emul_nss.c
+@@ -33,6 +33,9 @@
+ #include "vreader.h"
+ #include "vevent.h"
+ 
++#include "libcacard/vcardt_internal.h"
++
++
+ typedef enum {
+     VCardEmulUnknown = -1,
+     VCardEmulFalse = 0,
+@@ -519,18 +522,23 @@ vcard_emul_reader_get_slot(VReader *vreader)
+ }
+ 
+ /*
+- *  Card ATR's map to physical cards. VCARD_ATR_PREFIX will set appropriate
++ *  Card ATR's map to physical cards. vcard_alloc_atr will set appropriate
+  *  historical bytes for any software emulated card. The remaining bytes can be
+  *  used to indicate the actual emulator
+  */
+-static const unsigned char nss_atr[] = { VCARD_ATR_PREFIX(3), 'N', 'S', 'S' };
++static unsigned char *nss_atr;
++static int nss_atr_len;
+ 
+ void
+ vcard_emul_get_atr(VCard *card, unsigned char *atr, int *atr_len)
+ {
+-    int len = MIN(sizeof(nss_atr), *atr_len);
++    int len;
+     assert(atr != NULL);
+ 
++    if (nss_atr == NULL) {
++        nss_atr = vcard_alloc_atr("NSS", &nss_atr_len);
++    }
++    len = MIN(nss_atr_len, *atr_len);
+     memcpy(atr, nss_atr, len);
+     *atr_len = len;
+ }
+diff --git a/libcacard/vcardt.c b/libcacard/vcardt.c
+new file mode 100644
+index 0000000..9ce4648
+--- /dev/null
++++ b/libcacard/vcardt.c
+@@ -0,0 +1,40 @@
++#include <stdlib.h>
++#include <string.h>
++#include <glib.h>
++
++#include "libcacard/vcardt.h"
++
++#include "libcacard/vcardt_internal.h"
++
++/* create an ATR with appropriate historical bytes */
++#define ATR_TS_DIRECT_CONVENTION 0x3b
++#define ATR_TA_PRESENT 0x10
++#define ATR_TB_PRESENT 0x20
++#define ATR_TC_PRESENT 0x40
++#define ATR_TD_PRESENT 0x80
++
++unsigned char *vcard_alloc_atr(const char *postfix, int *atr_len)
++{
++    int postfix_len;
++    const char prefix[] = "VCARD_";
++    const char default_postfix[] = "DEFAULT";
++    const int prefix_len = sizeof(prefix) - 1;
++    int total_len;
++    unsigned char *atr;
++
++    if (postfix == NULL) {
++        postfix = default_postfix;
++    }
++    postfix_len = strlen(postfix);
++    total_len = 3 + prefix_len + postfix_len;
++    atr = g_malloc(total_len);
++    atr[0] = ATR_TS_DIRECT_CONVENTION;
++    atr[1] = ATR_TD_PRESENT + prefix_len + postfix_len;
++    atr[2] = 0x00;
++    memcpy(&atr[3], prefix, prefix_len);
++    memcpy(&atr[3 + prefix_len], postfix, postfix_len);
++    if (atr_len) {
++        *atr_len = total_len;
++    }
++    return atr;
++}
+diff --git a/libcacard/vcardt.h b/libcacard/vcardt.h
+index 3b9a619..795e265 100644
+--- a/libcacard/vcardt.h
++++ b/libcacard/vcardt.h
+@@ -25,19 +25,6 @@ typedef struct VCardEmulStruct VCardEmul;
+ 
+ #define MAX_CHANNEL 4
+ 
+-/* create an ATR with appropriate historical bytes */
+-#define TS_DIRECT_CONVENTION 0x3b
+-#define TA_PRESENT 0x10
+-#define TB_PRESENT 0x20
+-#define TC_PRESENT 0x40
+-#define TD_PRESENT 0x80
+-
+-#define VCARD_ATR_PREFIX(size) \
+-    TS_DIRECT_CONVENTION, \
+-    TD_PRESENT + (6 + size), \
+-    0x00, \
+-    'V', 'C', 'A', 'R', 'D', '_'
+-
+ typedef enum {
+     VCARD_DONE,
+     VCARD_NEXT,
+diff --git a/libcacard/vcardt_internal.h b/libcacard/vcardt_internal.h
+new file mode 100644
+index 0000000..e5c8d2d
+--- /dev/null
++++ b/libcacard/vcardt_internal.h
+@@ -0,0 +1,6 @@
++#ifndef VCARDT_INTERNAL_H
++#define VCARDT_INTERNAL_H
++
++unsigned char *vcard_alloc_atr(const char *postfix, int *atr_len);
++
++#endif
+-- 
+1.8.3.1
+
diff --git a/0238-dev-smartcard-reader-empty-implementation-for-Mechan.patch b/0238-dev-smartcard-reader-empty-implementation-for-Mechan.patch
new file mode 100644
index 0000000..340a550
--- /dev/null
+++ b/0238-dev-smartcard-reader-empty-implementation-for-Mechan.patch
@@ -0,0 +1,34 @@
+From 002714edb70b00c20de7d54980a528ac7232bb33 Mon Sep 17 00:00:00 2001
+From: Alon Levy <alevy at redhat.com>
+Date: Tue, 5 Mar 2013 17:31:10 +0200
+Subject: [PATCH 238/241] dev-smartcard-reader: empty implementation for
+ Mechanical (fail correctly)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Alon Levy <alevy at redhat.com>
+Reviewed-by: Marc-André Lureau <mlureau at redhat.com>
+(cherry picked from commit 58aeda15abb963196faaa4a0f23c5af45840f1b0)
+---
+ hw/usb/dev-smartcard-reader.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
+index 4e08f9b..a473b87 100644
+--- a/hw/usb/dev-smartcard-reader.c
++++ b/hw/usb/dev-smartcard-reader.c
+@@ -1051,6 +1051,10 @@ static void ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
+             ccid_reset_error_status(s);
+             ccid_write_parameters(s, ccid_header);
+             break;
++        case CCID_MESSAGE_TYPE_PC_to_RDR_Mechanical:
++            ccid_report_error_failed(s, 0);
++            ccid_write_slot_status(s, ccid_header);
++            break;
+         default:
+             DPRINTF(s, 1,
+                 "handle_data: ERROR: unhandled message type %Xh\n",
+-- 
+1.8.3.1
+
diff --git a/0239-libcacard-cac-change-big-switch-functions-to-single-.patch b/0239-libcacard-cac-change-big-switch-functions-to-single-.patch
new file mode 100644
index 0000000..1d77761
--- /dev/null
+++ b/0239-libcacard-cac-change-big-switch-functions-to-single-.patch
@@ -0,0 +1,209 @@
+From 8527c47117c0ec6d12929b6c19206eed6ee90528 Mon Sep 17 00:00:00 2001
+From: Alon Levy <alevy at redhat.com>
+Date: Mon, 4 Mar 2013 21:43:36 +0200
+Subject: [PATCH 239/241] libcacard/cac: change big switch functions to single
+ return point
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Alon Levy <alevy at redhat.com>
+Reviewed-by: Marc-André Lureau <mlureau at redhat.com>
+(cherry picked from commit 57f97834efe0c208ffadc9d2959f3d3d55580e52)
+---
+ libcacard/cac.c | 73 ++++++++++++++++++++++++++++++++++++++++-----------------
+ 1 file changed, 52 insertions(+), 21 deletions(-)
+
+diff --git a/libcacard/cac.c b/libcacard/cac.c
+index 5864539..7a06b5a 100644
+--- a/libcacard/cac.c
++++ b/libcacard/cac.c
+@@ -40,41 +40,51 @@ static VCardStatus
+ cac_common_process_apdu(VCard *card, VCardAPDU *apdu, VCardResponse **response)
+ {
+     int ef;
++    VCardStatus ret = VCARD_FAIL;
+ 
+     switch (apdu->a_ins) {
+     case VCARD7816_INS_SELECT_FILE:
+         if (apdu->a_p1 != 0x02) {
+             /* let the 7816 code handle applet switches */
+-            return VCARD_NEXT;
++            ret = VCARD_NEXT;
++            break;
+         }
+         /* handle file id setting */
+         if (apdu->a_Lc != 2) {
+             *response = vcard_make_response(
+                 VCARD7816_STATUS_ERROR_DATA_INVALID);
+-            return VCARD_DONE;
++            ret = VCARD_DONE;
++            break;
+         }
+         /* CAC 1.0 only supports ef = 0 */
+         ef = apdu->a_body[0] | (apdu->a_body[1] << 8);
+         if (ef != 0) {
+             *response = vcard_make_response(
+                 VCARD7816_STATUS_ERROR_FILE_NOT_FOUND);
+-            return VCARD_DONE;
++            ret = VCARD_DONE;
++            break;
+         }
+         *response = vcard_make_response(VCARD7816_STATUS_SUCCESS);
+-        return VCARD_DONE;
++        ret = VCARD_DONE;
++        break;
+     case VCARD7816_INS_GET_RESPONSE:
+     case VCARD7816_INS_VERIFY:
+         /* let the 7816 code handle these */
+-        return VCARD_NEXT;
++        ret = VCARD_NEXT;
++        break;
+     case CAC_GET_PROPERTIES:
+     case CAC_GET_ACR:
+         /* skip these for now, this will probably be needed */
+         *response = vcard_make_response(VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
+-        return VCARD_DONE;
++        ret = VCARD_DONE;
++        break;
++    default:
++        *response = vcard_make_response(
++            VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
++        ret = VCARD_DONE;
++        break;
+     }
+-    *response = vcard_make_response(
+-        VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
+-    return VCARD_DONE;
++    return ret;
+ }
+ 
+ /*
+@@ -108,6 +118,7 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu,
+     int size, next;
+     unsigned char *sign_buffer;
+     vcard_7816_status_t status;
++    VCardStatus ret = VCARD_FAIL;
+ 
+     applet_private = vcard_get_current_applet_private(card, apdu->a_channel);
+     assert(applet_private);
+@@ -117,7 +128,8 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu,
+     case CAC_UPDATE_BUFFER:
+         *response = vcard_make_response(
+             VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED);
+-        return VCARD_DONE;
++        ret = VCARD_DONE;
++        break;
+     case CAC_GET_CERTIFICATE:
+         if ((apdu->a_p2 != 0) || (apdu->a_p1 != 0)) {
+             *response = vcard_make_response(
+@@ -147,7 +159,8 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu,
+             *response = vcard_make_response(
+                             VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
+         }
+-        return VCARD_DONE;
++        ret = VCARD_DONE;
++        break;
+     case CAC_SIGN_DECRYPT:
+         if (apdu->a_p2 != 0) {
+             *response = vcard_make_response(
+@@ -164,7 +177,8 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu,
+             pki_applet->sign_buffer_len = 0;
+             *response = vcard_make_response(
+                             VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
+-            return VCARD_DONE;
++            ret = VCARD_DONE;
++            break;
+         }
+         memcpy(sign_buffer+pki_applet->sign_buffer_len, apdu->a_body, size);
+         size += pki_applet->sign_buffer_len;
+@@ -175,7 +189,8 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu,
+             pki_applet->sign_buffer = sign_buffer;
+             pki_applet->sign_buffer_len = size;
+             *response = vcard_make_response(VCARD7816_STATUS_SUCCESS);
+-            return VCARD_DONE;
++            ret = VCARD_DONE;
++            break;
+         case 0x00:
+             /* we now have the whole buffer, do the operation, result will be
+              * in the sign_buffer */
+@@ -200,15 +215,20 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu,
+         g_free(sign_buffer);
+         pki_applet->sign_buffer = NULL;
+         pki_applet->sign_buffer_len = 0;
+-        return VCARD_DONE;
++        ret = VCARD_DONE;
++        break;
+     case CAC_READ_BUFFER:
+         /* new CAC call, go ahead and use the old version for now */
+         /* TODO: implement */
+         *response = vcard_make_response(
+                                 VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
+-        return VCARD_DONE;
++        ret = VCARD_DONE;
++        break;
++    default:
++        ret = cac_common_process_apdu(card, apdu, response);
++        break;
+     }
+-    return cac_common_process_apdu(card, apdu, response);
++    return ret;
+ }
+ 
+ 
+@@ -216,19 +236,26 @@ static VCardStatus
+ cac_applet_id_process_apdu(VCard *card, VCardAPDU *apdu,
+                            VCardResponse **response)
+ {
++    VCardStatus ret = VCARD_FAIL;
++
+     switch (apdu->a_ins) {
+     case CAC_UPDATE_BUFFER:
+         *response = vcard_make_response(
+                         VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED);
+-        return VCARD_DONE;
++        ret = VCARD_DONE;
++        break;
+     case CAC_READ_BUFFER:
+         /* new CAC call, go ahead and use the old version for now */
+         /* TODO: implement */
+         *response = vcard_make_response(
+                         VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
+-        return VCARD_DONE;
++        ret = VCARD_DONE;
++        break;
++    default:
++        ret = cac_common_process_apdu(card, apdu, response);
++        break;
+     }
+-    return cac_common_process_apdu(card, apdu, response);
++    return ret;
+ }
+ 
+ 
+@@ -240,16 +267,20 @@ static VCardStatus
+ cac_applet_container_process_apdu(VCard *card, VCardAPDU *apdu,
+                                   VCardResponse **response)
+ {
++    VCardStatus ret = VCARD_FAIL;
++
+     switch (apdu->a_ins) {
+     case CAC_READ_BUFFER:
+     case CAC_UPDATE_BUFFER:
+         *response = vcard_make_response(
+                         VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
+-        return VCARD_DONE;
++        ret = VCARD_DONE;
++        break;
+     default:
++        ret = cac_common_process_apdu(card, apdu, response);
+         break;
+     }
+-    return cac_common_process_apdu(card, apdu, response);
++    return ret;
+ }
+ 
+ /*
+-- 
+1.8.3.1
+
diff --git a/0240-libcacard-vscclient-fix-leakage-of-socket-on-error-p.patch b/0240-libcacard-vscclient-fix-leakage-of-socket-on-error-p.patch
new file mode 100644
index 0000000..b23df89
--- /dev/null
+++ b/0240-libcacard-vscclient-fix-leakage-of-socket-on-error-p.patch
@@ -0,0 +1,55 @@
+From aae98aa5aa23dbddf3a6e8c8c0399948f0d43480 Mon Sep 17 00:00:00 2001
+From: Alon Levy <alevy at redhat.com>
+Date: Tue, 4 Jun 2013 16:23:37 -0400
+Subject: [PATCH 240/241] libcacard/vscclient: fix leakage of socket on error
+ paths
+
+Spotted by Coverity.
+
+Signed-off-by: Alon Levy <alevy at redhat.com>
+Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
+Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>
+(cherry picked from commit 581fe784c3adf85dc167a47a4a60fd1245a98217)
+---
+ libcacard/vscclient.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/libcacard/vscclient.c b/libcacard/vscclient.c
+index ac23647..5180d29 100644
+--- a/libcacard/vscclient.c
++++ b/libcacard/vscclient.c
+@@ -618,18 +618,22 @@ connect_to_qemu(
+     if (ret != 0) {
+         /* Error */
+         fprintf(stderr, "getaddrinfo failed\n");
+-        return -1;
++        goto cleanup_socket;
+     }
+ 
+     if (connect(sock, server->ai_addr, server->ai_addrlen) < 0) {
+         /* Error */
+         fprintf(stderr, "Could not connect\n");
+-        return -1;
++        goto cleanup_socket;
+     }
+     if (verbose) {
+         printf("Connected (sizeof Header=%zd)!\n", sizeof(VSCMsgHeader));
+     }
+     return sock;
++
++cleanup_socket:
++    closesocket(sock);
++    return -1;
+ }
+ 
+ int
+@@ -759,5 +763,6 @@ main(
+     g_io_channel_unref(channel_socket);
+     g_byte_array_unref(socket_to_send);
+ 
++    closesocket(sock);
+     return 0;
+ }
+-- 
+1.8.3.1
+
diff --git a/0241-libcacard-Fix-cppcheck-warning-and-remove-unneeded-c.patch b/0241-libcacard-Fix-cppcheck-warning-and-remove-unneeded-c.patch
new file mode 100644
index 0000000..06965b0
--- /dev/null
+++ b/0241-libcacard-Fix-cppcheck-warning-and-remove-unneeded-c.patch
@@ -0,0 +1,89 @@
+From 742e78d849a701e49f3c7d3c13eb9c4013f2cec3 Mon Sep 17 00:00:00 2001
+From: Stefan Weil <sw at weilnetz.de>
+Date: Sun, 16 Jun 2013 11:08:52 +0200
+Subject: [PATCH 241/241] libcacard: Fix cppcheck warning and remove unneeded
+ code
+
+The local function vcard_emul_alloc_arrays always returned PR_TRUE.
+Therefore cppcheck complained about code which handled the
+non-existent PR_FALSE case.
+
+Remove the function's return value and the dead code.
+
+Signed-off-by: Stefan Weil <sw at weilnetz.de>
+Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>
+(cherry picked from commit 48f0475f813dfa5ceb0e1f10c2ac3f28a8af583b)
+---
+ libcacard/vcard_emul_nss.c | 22 ++++++----------------
+ 1 file changed, 6 insertions(+), 16 deletions(-)
+
+diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
+index 1a3e568..fb429b1 100644
+--- a/libcacard/vcard_emul_nss.c
++++ b/libcacard/vcard_emul_nss.c
+@@ -90,17 +90,13 @@ static int nss_emul_init;
+ /*
+  * allocate the set of arrays for certs, cert_len, key
+  */
+-static PRBool
++static void
+ vcard_emul_alloc_arrays(unsigned char ***certsp, int **cert_lenp,
+                         VCardKey ***keysp, int cert_count)
+ {
+-    *certsp = NULL;
+-    *cert_lenp = NULL;
+-    *keysp = NULL;
+     *certsp = (unsigned char **)g_malloc(sizeof(unsigned char *)*cert_count);
+     *cert_lenp = (int *)g_malloc(sizeof(int)*cert_count);
+     *keysp = (VCardKey **)g_malloc(sizeof(VCardKey *)*cert_count);
+-    return PR_TRUE;
+ }
+ 
+ /*
+@@ -601,7 +597,6 @@ vcard_emul_mirror_card(VReader *vreader)
+     int *cert_len;
+     VCardKey **keys;
+     PK11SlotInfo *slot;
+-    PRBool ret;
+     VCard *card;
+ 
+     slot = vcard_emul_reader_get_slot(vreader);
+@@ -627,10 +622,7 @@ vcard_emul_mirror_card(VReader *vreader)
+     }
+ 
+     /* allocate the arrays */
+-    ret = vcard_emul_alloc_arrays(&certs, &cert_len, &keys, cert_count);
+-    if (ret == PR_FALSE) {
+-        return NULL;
+-    }
++    vcard_emul_alloc_arrays(&certs, &cert_len, &keys, cert_count);
+ 
+     /* fill in the arrays */
+     cert_count = 0;
+@@ -878,7 +870,7 @@ VCardEmulError
+ vcard_emul_init(const VCardEmulOptions *options)
+ {
+     SECStatus rv;
+-    PRBool ret, has_readers = PR_FALSE;
++    PRBool has_readers = PR_FALSE;
+     VReader *vreader;
+     VReaderEmul *vreader_emul;
+     SECMODListLock *module_lock;
+@@ -944,11 +936,9 @@ vcard_emul_init(const VCardEmulOptions *options)
+         vreader_add_reader(vreader);
+         cert_count = options->vreader[i].cert_count;
+ 
+-        ret = vcard_emul_alloc_arrays(&certs, &cert_len, &keys,
+-                                      options->vreader[i].cert_count);
+-        if (ret == PR_FALSE) {
+-            continue;
+-        }
++        vcard_emul_alloc_arrays(&certs, &cert_len, &keys,
++                                options->vreader[i].cert_count);
++
+         cert_count = 0;
+         for (j = 0; j < options->vreader[i].cert_count; j++) {
+             /* we should have a better way of identifying certs than by
+-- 
+1.8.3.1
+
diff --git a/qemu.spec b/qemu.spec
index e3d4256..6d9caed 100644
--- a/qemu.spec
+++ b/qemu.spec
@@ -131,7 +131,7 @@
 Summary: QEMU is a FAST! processor emulator
 Name: qemu
 Version: 1.4.2
-Release: 6%{?dist}
+Release: 7%{?dist}
 # Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped
 Epoch: 2
 License: GPLv2+ and LGPLv2+ and BSD
@@ -254,6 +254,39 @@ Patch0209: 0209-Fix-usage-of-USB_DEV_FLAG_IS_HOST-flag.patch
 # Fix crash when adding spice vdagent channel in the guest (bz #969084)
 Patch0210: 0210-qxl-Fix-QXLRam-initialisation.patch
 
+# 917860 related libcacard and qemu/hw/ccid windows 7 smartcard support.
+Patch0211: 0211-qemu-socket-Make-socket_optslist-public.patch
+Patch0212: 0212-libcacard-correct-T0-historical-bytes-size.patch
+Patch0213: 0213-ccid-card-emul-do-not-crash-if-backend-is-not-provid.patch
+Patch0214: 0214-ccid-make-backend_enum_table-static-const-and-adjust.patch
+Patch0215: 0215-ccid-declare-DEFAULT_ATR-table-to-be-static-const.patch
+Patch0216: 0216-libcacard-use-system-config-directory-for-nss-db-on-.patch
+Patch0217: 0217-util-move-socket_init-to-osdep.c.patch
+Patch0218: 0218-build-sys-must-link-with-fstack-protector.patch
+Patch0219: 0219-libcacard-fix-mingw64-cross-compilation.patch
+Patch0220: 0220-libcacard-split-vscclient-main-from-socket-reading.patch
+Patch0221: 0221-libcacard-vscclient-to-use-QemuThread-for-portabilit.patch
+Patch0222: 0222-libcacard-teach-vscclient-to-use-GMainLoop-for-porta.patch
+Patch0223: 0223-libcacard-remove-sql-prefix.patch
+Patch0224: 0224-libcacard-remove-default-libcoolkey-loading.patch
+Patch0225: 0225-dev-smartcard-reader-white-space-fixes.patch
+Patch0226: 0226-dev-smartcard-reader-nicer-debug-messages.patch
+Patch0227: 0227-dev-smartcard-reader-remove-aborts-never-triggered-b.patch
+Patch0228: 0228-dev-smartcard-reader-support-windows-guest.patch
+Patch0229: 0229-dev-smartcard-reader-reuse-usb.h-definitions.patch
+Patch0230: 0230-libcacard-change-default-ATR.patch
+Patch0231: 0231-ccid-card-passthru-add-atr-check.patch
+Patch0232: 0232-ccid-card-passthru-dev-smartcard-reader-add-debug-en.patch
+Patch0233: 0233-dev-smartcard-reader-define-structs-for-CCID_Paramet.patch
+Patch0234: 0234-dev-smartcard-reader-change-default-protocol-to-T-0.patch
+Patch0235: 0235-dev-smartcard-reader-copy-atr-protocol-to-ccid-param.patch
+Patch0236: 0236-libcacard-vreader-add-debugging-messages-for-apdu.patch
+Patch0237: 0237-libcacard-move-atr-setting-from-macro-to-function.patch
+Patch0238: 0238-dev-smartcard-reader-empty-implementation-for-Mechan.patch
+Patch0239: 0239-libcacard-cac-change-big-switch-functions-to-single-.patch
+Patch0240: 0240-libcacard-vscclient-fix-leakage-of-socket-on-error-p.patch
+Patch0241: 0241-libcacard-Fix-cppcheck-warning-and-remove-unneeded-c.patch
+
 BuildRequires: SDL-devel
 BuildRequires: zlib-devel
 BuildRequires: which
@@ -796,6 +829,39 @@ CAC emulation development files.
 # Fix crash when adding spice vdagent channel in the guest (bz #969084)
 %patch0210 -p1
 
+# 917860 libcacard and qemu/hw/ccid windows 7 smartcard support.
+%patch0211 -p1
+%patch0212 -p1
+%patch0213 -p1
+%patch0214 -p1
+%patch0215 -p1
+%patch0216 -p1
+%patch0217 -p1
+%patch0218 -p1
+%patch0219 -p1
+%patch0220 -p1
+%patch0221 -p1
+%patch0222 -p1
+%patch0223 -p1
+%patch0224 -p1
+%patch0225 -p1
+%patch0226 -p1
+%patch0227 -p1
+%patch0228 -p1
+%patch0229 -p1
+%patch0230 -p1
+%patch0231 -p1
+%patch0232 -p1
+%patch0233 -p1
+%patch0234 -p1
+%patch0235 -p1
+%patch0236 -p1
+%patch0237 -p1
+%patch0238 -p1
+%patch0239 -p1
+%patch0240 -p1
+%patch0241 -p1
+
 %build
 %if %{with kvmonly}
     buildarch="%{kvm_target}-softmmu"
@@ -1441,6 +1507,9 @@ getent passwd qemu >/dev/null || \
 %endif
 
 %changelog
+* Sun Aug 18 2013 Alon Levy <alevy at redhat.com> - 2:1.4.2-7
+- Support windows 7 smartcard using guests and clients - (bz #917860 rhel 6.5)
+
 * Thu Aug 01 2013 Cole Robinson <crobinso at redhat.com> - 2:1.4.2-6
 - Fix crash when adding spice vdagent channel in the guest (bz #969084)
 


More information about the scm-commits mailing list