Annotation of qemu/libcacard/vreader.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * emulate the reader
        !             3:  *
        !             4:  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
        !             5:  * See the COPYING.LIB file in the top-level directory.
        !             6:  */
        !             7: 
        !             8: #include "qemu-common.h"
        !             9: #include "qemu-thread.h"
        !            10: 
        !            11: #include "vcard.h"
        !            12: #include "vcard_emul.h"
        !            13: #include "card_7816.h"
        !            14: #include "vreader.h"
        !            15: #include "vevent.h"
        !            16: 
        !            17: struct VReaderStruct {
        !            18:     int    reference_count;
        !            19:     VCard *card;
        !            20:     char *name;
        !            21:     vreader_id_t id;
        !            22:     QemuMutex lock;
        !            23:     VReaderEmul  *reader_private;
        !            24:     VReaderEmulFree reader_private_free;
        !            25: };
        !            26: 
        !            27: /* manage locking */
        !            28: static inline void
        !            29: vreader_lock(VReader *reader)
        !            30: {
        !            31:     qemu_mutex_lock(&reader->lock);
        !            32: }
        !            33: 
        !            34: static inline void
        !            35: vreader_unlock(VReader *reader)
        !            36: {
        !            37:     qemu_mutex_unlock(&reader->lock);
        !            38: }
        !            39: 
        !            40: /*
        !            41:  * vreader constructor
        !            42:  */
        !            43: VReader *
        !            44: vreader_new(const char *name, VReaderEmul *private,
        !            45:             VReaderEmulFree private_free)
        !            46: {
        !            47:     VReader *reader;
        !            48: 
        !            49:     reader = (VReader *)qemu_malloc(sizeof(VReader));
        !            50:     qemu_mutex_init(&reader->lock);
        !            51:     reader->reference_count = 1;
        !            52:     reader->name = name ? strdup(name) : NULL;
        !            53:     reader->card = NULL;
        !            54:     reader->id = (vreader_id_t)-1;
        !            55:     reader->reader_private = private;
        !            56:     reader->reader_private_free = private_free;
        !            57:     return reader;
        !            58: }
        !            59: 
        !            60: /* get a reference */
        !            61: VReader*
        !            62: vreader_reference(VReader *reader)
        !            63: {
        !            64:     if (reader == NULL) {
        !            65:         return NULL;
        !            66:     }
        !            67:     vreader_lock(reader);
        !            68:     reader->reference_count++;
        !            69:     vreader_unlock(reader);
        !            70:     return reader;
        !            71: }
        !            72: 
        !            73: /* free a reference */
        !            74: void
        !            75: vreader_free(VReader *reader)
        !            76: {
        !            77:     if (reader == NULL) {
        !            78:         return;
        !            79:     }
        !            80:     vreader_lock(reader);
        !            81:     if (reader->reference_count-- > 1) {
        !            82:         vreader_unlock(reader);
        !            83:         return;
        !            84:     }
        !            85:     vreader_unlock(reader);
        !            86:     if (reader->card) {
        !            87:         vcard_free(reader->card);
        !            88:     }
        !            89:     if (reader->name) {
        !            90:         qemu_free(reader->name);
        !            91:     }
        !            92:     if (reader->reader_private_free) {
        !            93:         reader->reader_private_free(reader->reader_private);
        !            94:     }
        !            95:     qemu_free(reader);
        !            96:     return;
        !            97: }
        !            98: 
        !            99: static VCard *
        !           100: vreader_get_card(VReader *reader)
        !           101: {
        !           102:     VCard *card;
        !           103: 
        !           104:     vreader_lock(reader);
        !           105:     card = vcard_reference(reader->card);
        !           106:     vreader_unlock(reader);
        !           107:     return card;
        !           108: }
        !           109: 
        !           110: VReaderStatus
        !           111: vreader_card_is_present(VReader *reader)
        !           112: {
        !           113:     VCard *card = vreader_get_card(reader);
        !           114: 
        !           115:     if (card == NULL) {
        !           116:         return VREADER_NO_CARD;
        !           117:     }
        !           118:     vcard_free(card);
        !           119:     return VREADER_OK;
        !           120: }
        !           121: 
        !           122: vreader_id_t
        !           123: vreader_get_id(VReader *reader)
        !           124: {
        !           125:     if (reader == NULL) {
        !           126:         return (vreader_id_t)-1;
        !           127:     }
        !           128:     return reader->id;
        !           129: }
        !           130: 
        !           131: VReaderStatus
        !           132: vreader_set_id(VReader *reader, vreader_id_t id)
        !           133: {
        !           134:     if (reader == NULL) {
        !           135:         return VREADER_NO_CARD;
        !           136:     }
        !           137:     reader->id = id;
        !           138:     return VREADER_OK;
        !           139: }
        !           140: 
        !           141: const char *
        !           142: vreader_get_name(VReader *reader)
        !           143: {
        !           144:     if (reader == NULL) {
        !           145:         return NULL;
        !           146:     }
        !           147:     return reader->name;
        !           148: }
        !           149: 
        !           150: VReaderEmul *
        !           151: vreader_get_private(VReader *reader)
        !           152: {
        !           153:     return reader->reader_private;
        !           154: }
        !           155: 
        !           156: static VReaderStatus
        !           157: vreader_reset(VReader *reader, VCardPower power, unsigned char *atr, int *len)
        !           158: {
        !           159:     VCard *card = vreader_get_card(reader);
        !           160: 
        !           161:     if (card == NULL) {
        !           162:         return VREADER_NO_CARD;
        !           163:     }
        !           164:     /*
        !           165:      * clean up our state
        !           166:      */
        !           167:     vcard_reset(card, power);
        !           168:     if (atr) {
        !           169:         vcard_get_atr(card, atr, len);
        !           170:     }
        !           171:     vcard_free(card); /* free our reference */
        !           172:     return VREADER_OK;
        !           173: }
        !           174: 
        !           175: VReaderStatus
        !           176: vreader_power_on(VReader *reader, unsigned char *atr, int *len)
        !           177: {
        !           178:     return vreader_reset(reader, VCARD_POWER_ON, atr, len);
        !           179: }
        !           180: 
        !           181: VReaderStatus
        !           182: vreader_power_off(VReader *reader)
        !           183: {
        !           184:     return vreader_reset(reader, VCARD_POWER_OFF, NULL, 0);
        !           185: }
        !           186: 
        !           187: 
        !           188: VReaderStatus
        !           189: vreader_xfr_bytes(VReader *reader,
        !           190:                   unsigned char *send_buf, int send_buf_len,
        !           191:                   unsigned char *receive_buf, int *receive_buf_len)
        !           192: {
        !           193:     VCardAPDU *apdu;
        !           194:     VCardResponse *response = NULL;
        !           195:     VCardStatus card_status;
        !           196:     unsigned short status;
        !           197:     VCard *card = vreader_get_card(reader);
        !           198: 
        !           199:     if (card == NULL) {
        !           200:         return VREADER_NO_CARD;
        !           201:     }
        !           202: 
        !           203:     apdu = vcard_apdu_new(send_buf, send_buf_len, &status);
        !           204:     if (apdu == NULL) {
        !           205:         response = vcard_make_response(status);
        !           206:         card_status = VCARD_DONE;
        !           207:     } else {
        !           208:         card_status = vcard_process_apdu(card, apdu, &response);
        !           209:     }
        !           210:     assert(card_status == VCARD_DONE);
        !           211:     if (card_status == VCARD_DONE) {
        !           212:         int size = MIN(*receive_buf_len, response->b_total_len);
        !           213:         memcpy(receive_buf, response->b_data, size);
        !           214:         *receive_buf_len = size;
        !           215:     }
        !           216:     vcard_response_delete(response);
        !           217:     vcard_apdu_delete(apdu);
        !           218:     vcard_free(card); /* free our reference */
        !           219:     return VREADER_OK;
        !           220: }
        !           221: 
        !           222: struct VReaderListStruct {
        !           223:     VReaderListEntry *head;
        !           224:     VReaderListEntry *tail;
        !           225: };
        !           226: 
        !           227: struct VReaderListEntryStruct {
        !           228:     VReaderListEntry *next;
        !           229:     VReaderListEntry *prev;
        !           230:     VReader *reader;
        !           231: };
        !           232: 
        !           233: 
        !           234: static VReaderListEntry *
        !           235: vreader_list_entry_new(VReader *reader)
        !           236: {
        !           237:     VReaderListEntry *new_reader_list_entry;
        !           238: 
        !           239:     new_reader_list_entry = (VReaderListEntry *)
        !           240:                                qemu_malloc(sizeof(VReaderListEntry));
        !           241:     new_reader_list_entry->next = NULL;
        !           242:     new_reader_list_entry->prev = NULL;
        !           243:     new_reader_list_entry->reader = vreader_reference(reader);
        !           244:     return new_reader_list_entry;
        !           245: }
        !           246: 
        !           247: static void
        !           248: vreader_list_entry_delete(VReaderListEntry *entry)
        !           249: {
        !           250:     if (entry == NULL) {
        !           251:         return;
        !           252:     }
        !           253:     vreader_free(entry->reader);
        !           254:     qemu_free(entry);
        !           255: }
        !           256: 
        !           257: 
        !           258: static VReaderList *
        !           259: vreader_list_new(void)
        !           260: {
        !           261:     VReaderList *new_reader_list;
        !           262: 
        !           263:     new_reader_list = (VReaderList *)qemu_malloc(sizeof(VReaderList));
        !           264:     new_reader_list->head = NULL;
        !           265:     new_reader_list->tail = NULL;
        !           266:     return new_reader_list;
        !           267: }
        !           268: 
        !           269: void
        !           270: vreader_list_delete(VReaderList *list)
        !           271: {
        !           272:     VReaderListEntry *current_entry;
        !           273:     VReaderListEntry *next_entry = NULL;
        !           274:     for (current_entry = vreader_list_get_first(list); current_entry;
        !           275:          current_entry = next_entry) {
        !           276:         next_entry = vreader_list_get_next(current_entry);
        !           277:         vreader_list_entry_delete(current_entry);
        !           278:     }
        !           279:     list->head = NULL;
        !           280:     list->tail = NULL;
        !           281:     qemu_free(list);
        !           282: }
        !           283: 
        !           284: 
        !           285: VReaderListEntry *
        !           286: vreader_list_get_first(VReaderList *list)
        !           287: {
        !           288:     return list ? list->head : NULL;
        !           289: }
        !           290: 
        !           291: VReaderListEntry *
        !           292: vreader_list_get_next(VReaderListEntry *current)
        !           293: {
        !           294:     return current ? current->next : NULL;
        !           295: }
        !           296: 
        !           297: VReader *
        !           298: vreader_list_get_reader(VReaderListEntry *entry)
        !           299: {
        !           300:     return entry ? vreader_reference(entry->reader) : NULL;
        !           301: }
        !           302: 
        !           303: static void
        !           304: vreader_queue(VReaderList *list, VReaderListEntry *entry)
        !           305: {
        !           306:     if (entry == NULL) {
        !           307:         return;
        !           308:     }
        !           309:     entry->next = NULL;
        !           310:     entry->prev = list->tail;
        !           311:     if (list->head) {
        !           312:         list->tail->next = entry;
        !           313:     } else {
        !           314:         list->head = entry;
        !           315:     }
        !           316:     list->tail = entry;
        !           317: }
        !           318: 
        !           319: static void
        !           320: vreader_dequeue(VReaderList *list, VReaderListEntry *entry)
        !           321: {
        !           322:     if (entry == NULL) {
        !           323:         return;
        !           324:     }
        !           325:     if (entry->next == NULL) {
        !           326:         list->tail = entry->prev;
        !           327:     } else if (entry->prev == NULL) {
        !           328:         list->head = entry->next;
        !           329:     } else {
        !           330:         entry->prev->next = entry->next;
        !           331:         entry->next->prev = entry->prev;
        !           332:     }
        !           333:     if ((list->tail == NULL) || (list->head == NULL)) {
        !           334:         list->head = list->tail = NULL;
        !           335:     }
        !           336:     entry->next = entry->prev = NULL;
        !           337: }
        !           338: 
        !           339: static VReaderList *vreader_list;
        !           340: static QemuMutex vreader_list_mutex;
        !           341: 
        !           342: static void
        !           343: vreader_list_init(void)
        !           344: {
        !           345:     vreader_list = vreader_list_new();
        !           346:     qemu_mutex_init(&vreader_list_mutex);
        !           347: }
        !           348: 
        !           349: static void
        !           350: vreader_list_lock(void)
        !           351: {
        !           352:     qemu_mutex_lock(&vreader_list_mutex);
        !           353: }
        !           354: 
        !           355: static void
        !           356: vreader_list_unlock(void)
        !           357: {
        !           358:     qemu_mutex_unlock(&vreader_list_mutex);
        !           359: }
        !           360: 
        !           361: static VReaderList *
        !           362: vreader_copy_list(VReaderList *list)
        !           363: {
        !           364:     VReaderList *new_list = NULL;
        !           365:     VReaderListEntry *current_entry = NULL;
        !           366: 
        !           367:     new_list = vreader_list_new();
        !           368:     if (new_list == NULL) {
        !           369:         return NULL;
        !           370:     }
        !           371:     for (current_entry = vreader_list_get_first(list); current_entry;
        !           372:          current_entry = vreader_list_get_next(current_entry)) {
        !           373:         VReader *reader = vreader_list_get_reader(current_entry);
        !           374:         VReaderListEntry *new_entry = vreader_list_entry_new(reader);
        !           375: 
        !           376:         vreader_free(reader);
        !           377:         vreader_queue(new_list, new_entry);
        !           378:     }
        !           379:     return new_list;
        !           380: }
        !           381: 
        !           382: VReaderList *
        !           383: vreader_get_reader_list(void)
        !           384: {
        !           385:     VReaderList *new_reader_list;
        !           386: 
        !           387:     vreader_list_lock();
        !           388:     new_reader_list = vreader_copy_list(vreader_list);
        !           389:     vreader_list_unlock();
        !           390:     return new_reader_list;
        !           391: }
        !           392: 
        !           393: VReader *
        !           394: vreader_get_reader_by_id(vreader_id_t id)
        !           395: {
        !           396:     VReader *reader = NULL;
        !           397:     VReaderListEntry *current_entry = NULL;
        !           398: 
        !           399:     if (id == (vreader_id_t) -1) {
        !           400:         return NULL;
        !           401:     }
        !           402: 
        !           403:     vreader_list_lock();
        !           404:     for (current_entry = vreader_list_get_first(vreader_list); current_entry;
        !           405:             current_entry = vreader_list_get_next(current_entry)) {
        !           406:         VReader *creader = vreader_list_get_reader(current_entry);
        !           407:         if (creader->id == id) {
        !           408:             reader = creader;
        !           409:             break;
        !           410:         }
        !           411:         vreader_free(creader);
        !           412:     }
        !           413:     vreader_list_unlock();
        !           414:     return reader;
        !           415: }
        !           416: 
        !           417: VReader *
        !           418: vreader_get_reader_by_name(const char *name)
        !           419: {
        !           420:     VReader *reader = NULL;
        !           421:     VReaderListEntry *current_entry = NULL;
        !           422: 
        !           423:     vreader_list_lock();
        !           424:     for (current_entry = vreader_list_get_first(vreader_list); current_entry;
        !           425:             current_entry = vreader_list_get_next(current_entry)) {
        !           426:         VReader *creader = vreader_list_get_reader(current_entry);
        !           427:         if (strcmp(creader->name, name) == 0) {
        !           428:             reader = creader;
        !           429:             break;
        !           430:         }
        !           431:         vreader_free(creader);
        !           432:     }
        !           433:     vreader_list_unlock();
        !           434:     return reader;
        !           435: }
        !           436: 
        !           437: /* called from card_emul to initialize the readers */
        !           438: VReaderStatus
        !           439: vreader_add_reader(VReader *reader)
        !           440: {
        !           441:     VReaderListEntry *reader_entry;
        !           442: 
        !           443:     reader_entry = vreader_list_entry_new(reader);
        !           444:     if (reader_entry == NULL) {
        !           445:         return VREADER_OUT_OF_MEMORY;
        !           446:     }
        !           447:     vreader_list_lock();
        !           448:     vreader_queue(vreader_list, reader_entry);
        !           449:     vreader_list_unlock();
        !           450:     vevent_queue_vevent(vevent_new(VEVENT_READER_INSERT, reader, NULL));
        !           451:     return VREADER_OK;
        !           452: }
        !           453: 
        !           454: 
        !           455: VReaderStatus
        !           456: vreader_remove_reader(VReader *reader)
        !           457: {
        !           458:     VReaderListEntry *current_entry;
        !           459: 
        !           460:     vreader_list_lock();
        !           461:     for (current_entry = vreader_list_get_first(vreader_list); current_entry;
        !           462:          current_entry = vreader_list_get_next(current_entry)) {
        !           463:         if (current_entry->reader == reader) {
        !           464:             break;
        !           465:         }
        !           466:     }
        !           467:     vreader_dequeue(vreader_list, current_entry);
        !           468:     vreader_list_unlock();
        !           469:     vreader_list_entry_delete(current_entry);
        !           470:     vevent_queue_vevent(vevent_new(VEVENT_READER_REMOVE, reader, NULL));
        !           471:     return VREADER_OK;
        !           472: }
        !           473: 
        !           474: /*
        !           475:  * Generate VEVENT_CARD_INSERT or VEVENT_CARD_REMOVE based on vreader
        !           476:  * state. Separated from vreader_insert_card to allow replaying events
        !           477:  * for a given state.
        !           478:  */
        !           479: void
        !           480: vreader_queue_card_event(VReader *reader)
        !           481: {
        !           482:     vevent_queue_vevent(vevent_new(
        !           483:         reader->card ? VEVENT_CARD_INSERT : VEVENT_CARD_REMOVE, reader,
        !           484:         reader->card));
        !           485: }
        !           486: 
        !           487: /*
        !           488:  * insert/remove a new card. for removal, card == NULL
        !           489:  */
        !           490: VReaderStatus
        !           491: vreader_insert_card(VReader *reader, VCard *card)
        !           492: {
        !           493:     vreader_lock(reader);
        !           494:     if (reader->card) {
        !           495:         /* decrement reference count */
        !           496:         vcard_free(reader->card);
        !           497:         reader->card = NULL;
        !           498:     }
        !           499:     reader->card = vcard_reference(card);
        !           500:     vreader_unlock(reader);
        !           501:     vreader_queue_card_event(reader);
        !           502:     return VREADER_OK;
        !           503: }
        !           504: 
        !           505: /*
        !           506:  * initialize all the static reader structures
        !           507:  */
        !           508: void
        !           509: vreader_init(void)
        !           510: {
        !           511:     vreader_list_init();
        !           512: }
        !           513: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.