|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.