Statistics
| Branch: | Revision:

root / libcacard / vreader.c @ 111a38b0

History | View | Annotate | Download (11.2 kB)

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