qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

ccid-card-emulated.c (19739B)


      1 /*
      2  * CCID Card Device. Emulated card.
      3  *
      4  * Copyright (c) 2011 Red Hat.
      5  * Written by Alon Levy.
      6  *
      7  * This code is licensed under the GNU LGPL, version 2 or later.
      8  */
      9 
     10 /*
     11  * It can be used to provide access to the local hardware in a non exclusive
     12  * way, or it can use certificates. It requires the usb-ccid bus.
     13  *
     14  * Usage 1: standard, mirror hardware reader+card:
     15  * qemu .. -usb -device usb-ccid -device ccid-card-emulated
     16  *
     17  * Usage 2: use certificates, no hardware required
     18  * one time: create the certificates:
     19  *  for i in 1 2 3; do
     20  *      certutil -d /etc/pki/nssdb -x -t "CT,CT,CT" -S -s "CN=user$i" -n user$i
     21  *  done
     22  * qemu .. -usb -device usb-ccid \
     23  *  -device ccid-card-emulated,cert1=user1,cert2=user2,cert3=user3
     24  *
     25  * If you use a non default db for the certificates you can specify it using
     26  * the db parameter.
     27  */
     28 
     29 #include "qemu/osdep.h"
     30 #include <libcacard.h>
     31 
     32 #include "qemu/thread.h"
     33 #include "qemu/lockable.h"
     34 #include "qemu/main-loop.h"
     35 #include "qemu/module.h"
     36 #include "ccid.h"
     37 #include "hw/qdev-properties.h"
     38 #include "qapi/error.h"
     39 #include "qom/object.h"
     40 
     41 #define DPRINTF(card, lvl, fmt, ...) \
     42 do {\
     43     if (lvl <= card->debug) {\
     44         printf("ccid-card-emul: %s: " fmt , __func__, ## __VA_ARGS__);\
     45     } \
     46 } while (0)
     47 
     48 
     49 #define TYPE_EMULATED_CCID "ccid-card-emulated"
     50 typedef struct EmulatedState EmulatedState;
     51 DECLARE_INSTANCE_CHECKER(EmulatedState, EMULATED_CCID_CARD,
     52                          TYPE_EMULATED_CCID)
     53 
     54 #define BACKEND_NSS_EMULATED_NAME "nss-emulated"
     55 #define BACKEND_CERTIFICATES_NAME "certificates"
     56 
     57 enum {
     58     BACKEND_NSS_EMULATED = 1,
     59     BACKEND_CERTIFICATES
     60 };
     61 
     62 #define DEFAULT_BACKEND BACKEND_NSS_EMULATED
     63 
     64 
     65 enum {
     66     EMUL_READER_INSERT = 0,
     67     EMUL_READER_REMOVE,
     68     EMUL_CARD_INSERT,
     69     EMUL_CARD_REMOVE,
     70     EMUL_GUEST_APDU,
     71     EMUL_RESPONSE_APDU,
     72     EMUL_ERROR,
     73 };
     74 
     75 static const char *emul_event_to_string(uint32_t emul_event)
     76 {
     77     switch (emul_event) {
     78     case EMUL_READER_INSERT:
     79         return "EMUL_READER_INSERT";
     80     case EMUL_READER_REMOVE:
     81         return "EMUL_READER_REMOVE";
     82     case EMUL_CARD_INSERT:
     83         return "EMUL_CARD_INSERT";
     84     case EMUL_CARD_REMOVE:
     85         return "EMUL_CARD_REMOVE";
     86     case EMUL_GUEST_APDU:
     87         return "EMUL_GUEST_APDU";
     88     case EMUL_RESPONSE_APDU:
     89         return "EMUL_RESPONSE_APDU";
     90     case EMUL_ERROR:
     91         return "EMUL_ERROR";
     92     }
     93     return "UNKNOWN";
     94 }
     95 
     96 typedef struct EmulEvent {
     97     QSIMPLEQ_ENTRY(EmulEvent) entry;
     98     union {
     99         struct {
    100             uint32_t type;
    101         } gen;
    102         struct {
    103             uint32_t type;
    104             uint64_t code;
    105         } error;
    106         struct {
    107             uint32_t type;
    108             uint32_t len;
    109             uint8_t data[];
    110         } data;
    111     } p;
    112 } EmulEvent;
    113 
    114 #define MAX_ATR_SIZE 40
    115 struct EmulatedState {
    116     CCIDCardState base;
    117     uint8_t  debug;
    118     char    *backend_str;
    119     uint32_t backend;
    120     char    *cert1;
    121     char    *cert2;
    122     char    *cert3;
    123     char    *db;
    124     uint8_t  atr[MAX_ATR_SIZE];
    125     uint8_t  atr_length;
    126     QSIMPLEQ_HEAD(, EmulEvent) event_list;
    127     QemuMutex event_list_mutex;
    128     QemuThread event_thread_id;
    129     VReader *reader;
    130     QSIMPLEQ_HEAD(, EmulEvent) guest_apdu_list;
    131     QemuMutex vreader_mutex; /* and guest_apdu_list mutex */
    132     QemuMutex handle_apdu_mutex;
    133     QemuCond handle_apdu_cond;
    134     EventNotifier notifier;
    135     int      quit_apdu_thread;
    136     QemuThread apdu_thread_id;
    137 };
    138 
    139 static void emulated_apdu_from_guest(CCIDCardState *base,
    140     const uint8_t *apdu, uint32_t len)
    141 {
    142     EmulatedState *card = EMULATED_CCID_CARD(base);
    143     EmulEvent *event = g_malloc(sizeof(EmulEvent) + len);
    144 
    145     assert(event);
    146     event->p.data.type = EMUL_GUEST_APDU;
    147     event->p.data.len = len;
    148     memcpy(event->p.data.data, apdu, len);
    149     qemu_mutex_lock(&card->vreader_mutex);
    150     QSIMPLEQ_INSERT_TAIL(&card->guest_apdu_list, event, entry);
    151     qemu_mutex_unlock(&card->vreader_mutex);
    152     qemu_mutex_lock(&card->handle_apdu_mutex);
    153     qemu_cond_signal(&card->handle_apdu_cond);
    154     qemu_mutex_unlock(&card->handle_apdu_mutex);
    155 }
    156 
    157 static const uint8_t *emulated_get_atr(CCIDCardState *base, uint32_t *len)
    158 {
    159     EmulatedState *card = EMULATED_CCID_CARD(base);
    160 
    161     *len = card->atr_length;
    162     return card->atr;
    163 }
    164 
    165 static void emulated_push_event(EmulatedState *card, EmulEvent *event)
    166 {
    167     qemu_mutex_lock(&card->event_list_mutex);
    168     QSIMPLEQ_INSERT_TAIL(&(card->event_list), event, entry);
    169     qemu_mutex_unlock(&card->event_list_mutex);
    170     event_notifier_set(&card->notifier);
    171 }
    172 
    173 static void emulated_push_type(EmulatedState *card, uint32_t type)
    174 {
    175     EmulEvent *event = g_new(EmulEvent, 1);
    176 
    177     assert(event);
    178     event->p.gen.type = type;
    179     emulated_push_event(card, event);
    180 }
    181 
    182 static void emulated_push_error(EmulatedState *card, uint64_t code)
    183 {
    184     EmulEvent *event = g_new(EmulEvent, 1);
    185 
    186     assert(event);
    187     event->p.error.type = EMUL_ERROR;
    188     event->p.error.code = code;
    189     emulated_push_event(card, event);
    190 }
    191 
    192 static void emulated_push_data_type(EmulatedState *card, uint32_t type,
    193     const uint8_t *data, uint32_t len)
    194 {
    195     EmulEvent *event = (EmulEvent *)g_malloc(sizeof(EmulEvent) + len);
    196 
    197     assert(event);
    198     event->p.data.type = type;
    199     event->p.data.len = len;
    200     memcpy(event->p.data.data, data, len);
    201     emulated_push_event(card, event);
    202 }
    203 
    204 static void emulated_push_reader_insert(EmulatedState *card)
    205 {
    206     emulated_push_type(card, EMUL_READER_INSERT);
    207 }
    208 
    209 static void emulated_push_reader_remove(EmulatedState *card)
    210 {
    211     emulated_push_type(card, EMUL_READER_REMOVE);
    212 }
    213 
    214 static void emulated_push_card_insert(EmulatedState *card,
    215     const uint8_t *atr, uint32_t len)
    216 {
    217     emulated_push_data_type(card, EMUL_CARD_INSERT, atr, len);
    218 }
    219 
    220 static void emulated_push_card_remove(EmulatedState *card)
    221 {
    222     emulated_push_type(card, EMUL_CARD_REMOVE);
    223 }
    224 
    225 static void emulated_push_response_apdu(EmulatedState *card,
    226     const uint8_t *apdu, uint32_t len)
    227 {
    228     emulated_push_data_type(card, EMUL_RESPONSE_APDU, apdu, len);
    229 }
    230 
    231 #define APDU_BUF_SIZE 270
    232 static void *handle_apdu_thread(void* arg)
    233 {
    234     EmulatedState *card = arg;
    235     uint8_t recv_data[APDU_BUF_SIZE];
    236     int recv_len;
    237     VReaderStatus reader_status;
    238     EmulEvent *event;
    239 
    240     while (1) {
    241         qemu_mutex_lock(&card->handle_apdu_mutex);
    242         qemu_cond_wait(&card->handle_apdu_cond, &card->handle_apdu_mutex);
    243         qemu_mutex_unlock(&card->handle_apdu_mutex);
    244         if (card->quit_apdu_thread) {
    245             card->quit_apdu_thread = 0; /* debugging */
    246             break;
    247         }
    248         WITH_QEMU_LOCK_GUARD(&card->vreader_mutex) {
    249             while (!QSIMPLEQ_EMPTY(&card->guest_apdu_list)) {
    250                 event = QSIMPLEQ_FIRST(&card->guest_apdu_list);
    251                 assert((unsigned long)event > 1000);
    252                 QSIMPLEQ_REMOVE_HEAD(&card->guest_apdu_list, entry);
    253                 if (event->p.data.type != EMUL_GUEST_APDU) {
    254                     DPRINTF(card, 1, "unexpected message in handle_apdu_thread\n");
    255                     g_free(event);
    256                     continue;
    257                 }
    258                 if (card->reader == NULL) {
    259                     DPRINTF(card, 1, "reader is NULL\n");
    260                     g_free(event);
    261                     continue;
    262                 }
    263                 recv_len = sizeof(recv_data);
    264                 reader_status = vreader_xfr_bytes(card->reader,
    265                         event->p.data.data, event->p.data.len,
    266                         recv_data, &recv_len);
    267                 DPRINTF(card, 2, "got back apdu of length %d\n", recv_len);
    268                 if (reader_status == VREADER_OK) {
    269                     emulated_push_response_apdu(card, recv_data, recv_len);
    270                 } else {
    271                     emulated_push_error(card, reader_status);
    272                 }
    273                 g_free(event);
    274             }
    275         }
    276     }
    277     return NULL;
    278 }
    279 
    280 static void *event_thread(void *arg)
    281 {
    282     int atr_len = MAX_ATR_SIZE;
    283     uint8_t atr[MAX_ATR_SIZE];
    284     VEvent *event = NULL;
    285     EmulatedState *card = arg;
    286 
    287     while (1) {
    288         const char *reader_name;
    289 
    290         event = vevent_wait_next_vevent();
    291         if (event == NULL || event->type == VEVENT_LAST) {
    292             break;
    293         }
    294         if (event->type != VEVENT_READER_INSERT) {
    295             if (card->reader == NULL && event->reader != NULL) {
    296                 /* Happens after device_add followed by card remove or insert.
    297                  * XXX: create synthetic add_reader events if vcard_emul_init
    298                  * already called, which happens if device_del and device_add
    299                  * are called */
    300                 card->reader = vreader_reference(event->reader);
    301             } else {
    302                 if (event->reader != card->reader) {
    303                     fprintf(stderr,
    304                         "ERROR: wrong reader: quitting event_thread\n");
    305                     break;
    306                 }
    307             }
    308         }
    309         switch (event->type) {
    310         case VEVENT_READER_INSERT:
    311             /* TODO: take a specific reader. i.e. track which reader
    312              * we are seeing here, check it is the one we want (the first,
    313              * or by a particular name), and ignore if we don't want it.
    314              */
    315             reader_name = vreader_get_name(event->reader);
    316             if (card->reader != NULL) {
    317                 DPRINTF(card, 2, "READER INSERT - replacing %s with %s\n",
    318                     vreader_get_name(card->reader), reader_name);
    319                 qemu_mutex_lock(&card->vreader_mutex);
    320                 vreader_free(card->reader);
    321                 qemu_mutex_unlock(&card->vreader_mutex);
    322                 emulated_push_reader_remove(card);
    323             }
    324             qemu_mutex_lock(&card->vreader_mutex);
    325             DPRINTF(card, 2, "READER INSERT %s\n", reader_name);
    326             card->reader = vreader_reference(event->reader);
    327             qemu_mutex_unlock(&card->vreader_mutex);
    328             emulated_push_reader_insert(card);
    329             break;
    330         case VEVENT_READER_REMOVE:
    331             DPRINTF(card, 2, " READER REMOVE: %s\n",
    332                     vreader_get_name(event->reader));
    333             qemu_mutex_lock(&card->vreader_mutex);
    334             vreader_free(card->reader);
    335             card->reader = NULL;
    336             qemu_mutex_unlock(&card->vreader_mutex);
    337             emulated_push_reader_remove(card);
    338             break;
    339         case VEVENT_CARD_INSERT:
    340             /* get the ATR (intended as a response to a power on from the
    341              * reader */
    342             atr_len = MAX_ATR_SIZE;
    343             vreader_power_on(event->reader, atr, &atr_len);
    344             card->atr_length = (uint8_t)atr_len;
    345             DPRINTF(card, 2, " CARD INSERT\n");
    346             emulated_push_card_insert(card, atr, atr_len);
    347             break;
    348         case VEVENT_CARD_REMOVE:
    349             DPRINTF(card, 2, " CARD REMOVE\n");
    350             emulated_push_card_remove(card);
    351             break;
    352         case VEVENT_LAST: /* quit */
    353             vevent_delete(event);
    354             return NULL;
    355         default:
    356             break;
    357         }
    358         vevent_delete(event);
    359     }
    360     return NULL;
    361 }
    362 
    363 static void card_event_handler(EventNotifier *notifier)
    364 {
    365     EmulatedState *card = container_of(notifier, EmulatedState, notifier);
    366     EmulEvent *event, *next;
    367 
    368     event_notifier_test_and_clear(&card->notifier);
    369     QEMU_LOCK_GUARD(&card->event_list_mutex);
    370     QSIMPLEQ_FOREACH_SAFE(event, &card->event_list, entry, next) {
    371         DPRINTF(card, 2, "event %s\n", emul_event_to_string(event->p.gen.type));
    372         switch (event->p.gen.type) {
    373         case EMUL_RESPONSE_APDU:
    374             ccid_card_send_apdu_to_guest(&card->base, event->p.data.data,
    375                 event->p.data.len);
    376             break;
    377         case EMUL_READER_INSERT:
    378             ccid_card_ccid_attach(&card->base);
    379             break;
    380         case EMUL_READER_REMOVE:
    381             ccid_card_ccid_detach(&card->base);
    382             break;
    383         case EMUL_CARD_INSERT:
    384             assert(event->p.data.len <= MAX_ATR_SIZE);
    385             card->atr_length = event->p.data.len;
    386             memcpy(card->atr, event->p.data.data, card->atr_length);
    387             ccid_card_card_inserted(&card->base);
    388             break;
    389         case EMUL_CARD_REMOVE:
    390             ccid_card_card_removed(&card->base);
    391             break;
    392         case EMUL_ERROR:
    393             ccid_card_card_error(&card->base, event->p.error.code);
    394             break;
    395         default:
    396             DPRINTF(card, 2, "unexpected event\n");
    397             break;
    398         }
    399         g_free(event);
    400     }
    401     QSIMPLEQ_INIT(&card->event_list);
    402 }
    403 
    404 static int init_event_notifier(EmulatedState *card, Error **errp)
    405 {
    406     if (event_notifier_init(&card->notifier, false) < 0) {
    407         error_setg(errp, "ccid-card-emul: event notifier creation failed");
    408         return -1;
    409     }
    410     event_notifier_set_handler(&card->notifier, card_event_handler);
    411     return 0;
    412 }
    413 
    414 static void clean_event_notifier(EmulatedState *card)
    415 {
    416     event_notifier_set_handler(&card->notifier, NULL);
    417     event_notifier_cleanup(&card->notifier);
    418 }
    419 
    420 #define CERTIFICATES_DEFAULT_DB "/etc/pki/nssdb"
    421 #define CERTIFICATES_ARGS_TEMPLATE\
    422     "db=\"%s\" use_hw=no soft=(,Virtual Reader,CAC,,%s,%s,%s)"
    423 
    424 static int wrap_vcard_emul_init(VCardEmulOptions *options)
    425 {
    426     static int called;
    427     static int options_was_null;
    428 
    429     if (called) {
    430         if ((options == NULL) != options_was_null) {
    431             printf("%s: warning: running emulated with certificates"
    432                    " and emulated side by side is not supported\n",
    433                    __func__);
    434             return VCARD_EMUL_FAIL;
    435         }
    436         vcard_emul_replay_insertion_events();
    437         return VCARD_EMUL_OK;
    438     }
    439     options_was_null = (options == NULL);
    440     called = 1;
    441     return vcard_emul_init(options);
    442 }
    443 
    444 static int emulated_initialize_vcard_from_certificates(EmulatedState *card)
    445 {
    446     char emul_args[200];
    447     VCardEmulOptions *options = NULL;
    448 
    449     snprintf(emul_args, sizeof(emul_args) - 1, CERTIFICATES_ARGS_TEMPLATE,
    450         card->db ? card->db : CERTIFICATES_DEFAULT_DB,
    451         card->cert1, card->cert2, card->cert3);
    452     options = vcard_emul_options(emul_args);
    453     if (options == NULL) {
    454         printf("%s: warning: not using certificates due to"
    455                " initialization error\n", __func__);
    456     }
    457     return wrap_vcard_emul_init(options);
    458 }
    459 
    460 typedef struct EnumTable {
    461     const char *name;
    462     uint32_t value;
    463 } EnumTable;
    464 
    465 static const EnumTable backend_enum_table[] = {
    466     {BACKEND_NSS_EMULATED_NAME, BACKEND_NSS_EMULATED},
    467     {BACKEND_CERTIFICATES_NAME, BACKEND_CERTIFICATES},
    468     {NULL, 0},
    469 };
    470 
    471 static uint32_t parse_enumeration(char *str,
    472     const EnumTable *table, uint32_t not_found_value)
    473 {
    474     uint32_t ret = not_found_value;
    475 
    476     if (str == NULL)
    477         return 0;
    478 
    479     while (table->name != NULL) {
    480         if (strcmp(table->name, str) == 0) {
    481             ret = table->value;
    482             break;
    483         }
    484         table++;
    485     }
    486     return ret;
    487 }
    488 
    489 static void emulated_realize(CCIDCardState *base, Error **errp)
    490 {
    491     EmulatedState *card = EMULATED_CCID_CARD(base);
    492     VCardEmulError ret;
    493     const EnumTable *ptable;
    494 
    495     QSIMPLEQ_INIT(&card->event_list);
    496     QSIMPLEQ_INIT(&card->guest_apdu_list);
    497     qemu_mutex_init(&card->event_list_mutex);
    498     qemu_mutex_init(&card->vreader_mutex);
    499     qemu_mutex_init(&card->handle_apdu_mutex);
    500     qemu_cond_init(&card->handle_apdu_cond);
    501     card->reader = NULL;
    502     card->quit_apdu_thread = 0;
    503     if (init_event_notifier(card, errp) < 0) {
    504         goto out1;
    505     }
    506 
    507     card->backend = 0;
    508     if (card->backend_str) {
    509         card->backend = parse_enumeration(card->backend_str,
    510                                           backend_enum_table, 0);
    511     }
    512 
    513     if (card->backend == 0) {
    514         error_setg(errp, "backend must be one of:");
    515         for (ptable = backend_enum_table; ptable->name != NULL; ++ptable) {
    516             error_append_hint(errp, "%s\n", ptable->name);
    517         }
    518         goto out2;
    519     }
    520 
    521     /* TODO: a passthru backened that works on local machine. third card type?*/
    522     if (card->backend == BACKEND_CERTIFICATES) {
    523         if (card->cert1 != NULL && card->cert2 != NULL && card->cert3 != NULL) {
    524             ret = emulated_initialize_vcard_from_certificates(card);
    525         } else {
    526             error_setg(errp, "%s: you must provide all three certs for"
    527                        " certificates backend", TYPE_EMULATED_CCID);
    528             goto out2;
    529         }
    530     } else {
    531         if (card->backend != BACKEND_NSS_EMULATED) {
    532             error_setg(errp, "%s: bad backend specified. The options are:%s"
    533                        " (default), %s.", TYPE_EMULATED_CCID,
    534                        BACKEND_NSS_EMULATED_NAME, BACKEND_CERTIFICATES_NAME);
    535             goto out2;
    536         }
    537         if (card->cert1 != NULL || card->cert2 != NULL || card->cert3 != NULL) {
    538             error_setg(errp, "%s: unexpected cert parameters to nss emulated "
    539                        "backend", TYPE_EMULATED_CCID);
    540             goto out2;
    541         }
    542         /* default to mirroring the local hardware readers */
    543         ret = wrap_vcard_emul_init(NULL);
    544     }
    545     if (ret != VCARD_EMUL_OK) {
    546         error_setg(errp, "%s: failed to initialize vcard", TYPE_EMULATED_CCID);
    547         goto out2;
    548     }
    549     qemu_thread_create(&card->event_thread_id, "ccid/event", event_thread,
    550                        card, QEMU_THREAD_JOINABLE);
    551     qemu_thread_create(&card->apdu_thread_id, "ccid/apdu", handle_apdu_thread,
    552                        card, QEMU_THREAD_JOINABLE);
    553 
    554     return;
    555 
    556 out2:
    557     clean_event_notifier(card);
    558 out1:
    559     qemu_cond_destroy(&card->handle_apdu_cond);
    560     qemu_mutex_destroy(&card->handle_apdu_mutex);
    561     qemu_mutex_destroy(&card->vreader_mutex);
    562     qemu_mutex_destroy(&card->event_list_mutex);
    563 }
    564 
    565 static void emulated_unrealize(CCIDCardState *base)
    566 {
    567     EmulatedState *card = EMULATED_CCID_CARD(base);
    568     VEvent *vevent = vevent_new(VEVENT_LAST, NULL, NULL);
    569 
    570     vevent_queue_vevent(vevent); /* stop vevent thread */
    571     qemu_thread_join(&card->event_thread_id);
    572 
    573     card->quit_apdu_thread = 1; /* stop handle_apdu thread */
    574     qemu_cond_signal(&card->handle_apdu_cond);
    575     qemu_thread_join(&card->apdu_thread_id);
    576 
    577     clean_event_notifier(card);
    578     /* threads exited, can destroy all condvars/mutexes */
    579     qemu_cond_destroy(&card->handle_apdu_cond);
    580     qemu_mutex_destroy(&card->handle_apdu_mutex);
    581     qemu_mutex_destroy(&card->vreader_mutex);
    582     qemu_mutex_destroy(&card->event_list_mutex);
    583 }
    584 
    585 static Property emulated_card_properties[] = {
    586     DEFINE_PROP_STRING("backend", EmulatedState, backend_str),
    587     DEFINE_PROP_STRING("cert1", EmulatedState, cert1),
    588     DEFINE_PROP_STRING("cert2", EmulatedState, cert2),
    589     DEFINE_PROP_STRING("cert3", EmulatedState, cert3),
    590     DEFINE_PROP_STRING("db", EmulatedState, db),
    591     DEFINE_PROP_UINT8("debug", EmulatedState, debug, 0),
    592     DEFINE_PROP_END_OF_LIST(),
    593 };
    594 
    595 static void emulated_class_initfn(ObjectClass *klass, void *data)
    596 {
    597     DeviceClass *dc = DEVICE_CLASS(klass);
    598     CCIDCardClass *cc = CCID_CARD_CLASS(klass);
    599 
    600     cc->realize = emulated_realize;
    601     cc->unrealize = emulated_unrealize;
    602     cc->get_atr = emulated_get_atr;
    603     cc->apdu_from_guest = emulated_apdu_from_guest;
    604     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
    605     dc->desc = "emulated smartcard";
    606     device_class_set_props(dc, emulated_card_properties);
    607 }
    608 
    609 static const TypeInfo emulated_card_info = {
    610     .name          = TYPE_EMULATED_CCID,
    611     .parent        = TYPE_CCID_CARD,
    612     .instance_size = sizeof(EmulatedState),
    613     .class_init    = emulated_class_initfn,
    614 };
    615 module_obj(TYPE_EMULATED_CCID);
    616 module_kconfig(USB);
    617 
    618 static void ccid_card_emulated_register_types(void)
    619 {
    620     type_register_static(&emulated_card_info);
    621 }
    622 
    623 type_init(ccid_card_emulated_register_types)