Statistics
| Branch: | Revision:

root / libcacard / vreader.c @ 26ca8c06

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 *)g_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
        g_free(reader->name);
91
    }
92
    if (reader->reader_private_free) {
93
        reader->reader_private_free(reader->reader_private);
94
    }
95
    g_free(reader);
96
}
97

    
98
static VCard *
99
vreader_get_card(VReader *reader)
100
{
101
    VCard *card;
102

    
103
    vreader_lock(reader);
104
    card = vcard_reference(reader->card);
105
    vreader_unlock(reader);
106
    return card;
107
}
108

    
109
VReaderStatus
110
vreader_card_is_present(VReader *reader)
111
{
112
    VCard *card = vreader_get_card(reader);
113

    
114
    if (card == NULL) {
115
        return VREADER_NO_CARD;
116
    }
117
    vcard_free(card);
118
    return VREADER_OK;
119
}
120

    
121
vreader_id_t
122
vreader_get_id(VReader *reader)
123
{
124
    if (reader == NULL) {
125
        return (vreader_id_t)-1;
126
    }
127
    return reader->id;
128
}
129

    
130
VReaderStatus
131
vreader_set_id(VReader *reader, vreader_id_t id)
132
{
133
    if (reader == NULL) {
134
        return VREADER_NO_CARD;
135
    }
136
    reader->id = id;
137
    return VREADER_OK;
138
}
139

    
140
const char *
141
vreader_get_name(VReader *reader)
142
{
143
    if (reader == NULL) {
144
        return NULL;
145
    }
146
    return reader->name;
147
}
148

    
149
VReaderEmul *
150
vreader_get_private(VReader *reader)
151
{
152
    return reader->reader_private;
153
}
154

    
155
static VReaderStatus
156
vreader_reset(VReader *reader, VCardPower power, unsigned char *atr, int *len)
157
{
158
    VCard *card = vreader_get_card(reader);
159

    
160
    if (card == NULL) {
161
        return VREADER_NO_CARD;
162
    }
163
    /*
164
     * clean up our state
165
     */
166
    vcard_reset(card, power);
167
    if (atr) {
168
        vcard_get_atr(card, atr, len);
169
    }
170
    vcard_free(card); /* free our reference */
171
    return VREADER_OK;
172
}
173

    
174
VReaderStatus
175
vreader_power_on(VReader *reader, unsigned char *atr, int *len)
176
{
177
    return vreader_reset(reader, VCARD_POWER_ON, atr, len);
178
}
179

    
180
VReaderStatus
181
vreader_power_off(VReader *reader)
182
{
183
    return vreader_reset(reader, VCARD_POWER_OFF, NULL, 0);
184
}
185

    
186

    
187
VReaderStatus
188
vreader_xfr_bytes(VReader *reader,
189
                  unsigned char *send_buf, int send_buf_len,
190
                  unsigned char *receive_buf, int *receive_buf_len)
191
{
192
    VCardAPDU *apdu;
193
    VCardResponse *response = NULL;
194
    VCardStatus card_status;
195
    unsigned short status;
196
    VCard *card = vreader_get_card(reader);
197

    
198
    if (card == NULL) {
199
        return VREADER_NO_CARD;
200
    }
201

    
202
    apdu = vcard_apdu_new(send_buf, send_buf_len, &status);
203
    if (apdu == NULL) {
204
        response = vcard_make_response(status);
205
        card_status = VCARD_DONE;
206
    } else {
207
        card_status = vcard_process_apdu(card, apdu, &response);
208
    }
209
    assert(card_status == VCARD_DONE);
210
    if (card_status == VCARD_DONE) {
211
        int size = MIN(*receive_buf_len, response->b_total_len);
212
        memcpy(receive_buf, response->b_data, size);
213
        *receive_buf_len = size;
214
    }
215
    vcard_response_delete(response);
216
    vcard_apdu_delete(apdu);
217
    vcard_free(card); /* free our reference */
218
    return VREADER_OK;
219
}
220

    
221
struct VReaderListStruct {
222
    VReaderListEntry *head;
223
    VReaderListEntry *tail;
224
};
225

    
226
struct VReaderListEntryStruct {
227
    VReaderListEntry *next;
228
    VReaderListEntry *prev;
229
    VReader *reader;
230
};
231

    
232

    
233
static VReaderListEntry *
234
vreader_list_entry_new(VReader *reader)
235
{
236
    VReaderListEntry *new_reader_list_entry;
237

    
238
    new_reader_list_entry = (VReaderListEntry *)
239
                               g_malloc(sizeof(VReaderListEntry));
240
    new_reader_list_entry->next = NULL;
241
    new_reader_list_entry->prev = NULL;
242
    new_reader_list_entry->reader = vreader_reference(reader);
243
    return new_reader_list_entry;
244
}
245

    
246
static void
247
vreader_list_entry_delete(VReaderListEntry *entry)
248
{
249
    if (entry == NULL) {
250
        return;
251
    }
252
    vreader_free(entry->reader);
253
    g_free(entry);
254
}
255

    
256

    
257
static VReaderList *
258
vreader_list_new(void)
259
{
260
    VReaderList *new_reader_list;
261

    
262
    new_reader_list = (VReaderList *)g_malloc(sizeof(VReaderList));
263
    new_reader_list->head = NULL;
264
    new_reader_list->tail = NULL;
265
    return new_reader_list;
266
}
267

    
268
void
269
vreader_list_delete(VReaderList *list)
270
{
271
    VReaderListEntry *current_entry;
272
    VReaderListEntry *next_entry = NULL;
273
    for (current_entry = vreader_list_get_first(list); current_entry;
274
         current_entry = next_entry) {
275
        next_entry = vreader_list_get_next(current_entry);
276
        vreader_list_entry_delete(current_entry);
277
    }
278
    list->head = NULL;
279
    list->tail = NULL;
280
    g_free(list);
281
}
282

    
283

    
284
VReaderListEntry *
285
vreader_list_get_first(VReaderList *list)
286
{
287
    return list ? list->head : NULL;
288
}
289

    
290
VReaderListEntry *
291
vreader_list_get_next(VReaderListEntry *current)
292
{
293
    return current ? current->next : NULL;
294
}
295

    
296
VReader *
297
vreader_list_get_reader(VReaderListEntry *entry)
298
{
299
    return entry ? vreader_reference(entry->reader) : NULL;
300
}
301

    
302
static void
303
vreader_queue(VReaderList *list, VReaderListEntry *entry)
304
{
305
    if (entry == NULL) {
306
        return;
307
    }
308
    entry->next = NULL;
309
    entry->prev = list->tail;
310
    if (list->head) {
311
        list->tail->next = entry;
312
    } else {
313
        list->head = entry;
314
    }
315
    list->tail = entry;
316
}
317

    
318
static void
319
vreader_dequeue(VReaderList *list, VReaderListEntry *entry)
320
{
321
    if (entry == NULL) {
322
        return;
323
    }
324
    if (entry->next == NULL) {
325
        list->tail = entry->prev;
326
    } else if (entry->prev == NULL) {
327
        list->head = entry->next;
328
    } else {
329
        entry->prev->next = entry->next;
330
        entry->next->prev = entry->prev;
331
    }
332
    if ((list->tail == NULL) || (list->head == NULL)) {
333
        list->head = list->tail = NULL;
334
    }
335
    entry->next = entry->prev = NULL;
336
}
337

    
338
static VReaderList *vreader_list;
339
static QemuMutex vreader_list_mutex;
340

    
341
static void
342
vreader_list_init(void)
343
{
344
    vreader_list = vreader_list_new();
345
    qemu_mutex_init(&vreader_list_mutex);
346
}
347

    
348
static void
349
vreader_list_lock(void)
350
{
351
    qemu_mutex_lock(&vreader_list_mutex);
352
}
353

    
354
static void
355
vreader_list_unlock(void)
356
{
357
    qemu_mutex_unlock(&vreader_list_mutex);
358
}
359

    
360
static VReaderList *
361
vreader_copy_list(VReaderList *list)
362
{
363
    VReaderList *new_list = NULL;
364
    VReaderListEntry *current_entry = NULL;
365

    
366
    new_list = vreader_list_new();
367
    if (new_list == NULL) {
368
        return NULL;
369
    }
370
    for (current_entry = vreader_list_get_first(list); current_entry;
371
         current_entry = vreader_list_get_next(current_entry)) {
372
        VReader *reader = vreader_list_get_reader(current_entry);
373
        VReaderListEntry *new_entry = vreader_list_entry_new(reader);
374

    
375
        vreader_free(reader);
376
        vreader_queue(new_list, new_entry);
377
    }
378
    return new_list;
379
}
380

    
381
VReaderList *
382
vreader_get_reader_list(void)
383
{
384
    VReaderList *new_reader_list;
385

    
386
    vreader_list_lock();
387
    new_reader_list = vreader_copy_list(vreader_list);
388
    vreader_list_unlock();
389
    return new_reader_list;
390
}
391

    
392
VReader *
393
vreader_get_reader_by_id(vreader_id_t id)
394
{
395
    VReader *reader = NULL;
396
    VReaderListEntry *current_entry = NULL;
397

    
398
    if (id == (vreader_id_t) -1) {
399
        return NULL;
400
    }
401

    
402
    vreader_list_lock();
403
    for (current_entry = vreader_list_get_first(vreader_list); current_entry;
404
            current_entry = vreader_list_get_next(current_entry)) {
405
        VReader *creader = vreader_list_get_reader(current_entry);
406
        if (creader->id == id) {
407
            reader = creader;
408
            break;
409
        }
410
        vreader_free(creader);
411
    }
412
    vreader_list_unlock();
413
    return reader;
414
}
415

    
416
VReader *
417
vreader_get_reader_by_name(const char *name)
418
{
419
    VReader *reader = NULL;
420
    VReaderListEntry *current_entry = NULL;
421

    
422
    vreader_list_lock();
423
    for (current_entry = vreader_list_get_first(vreader_list); current_entry;
424
            current_entry = vreader_list_get_next(current_entry)) {
425
        VReader *creader = vreader_list_get_reader(current_entry);
426
        if (strcmp(creader->name, name) == 0) {
427
            reader = creader;
428
            break;
429
        }
430
        vreader_free(creader);
431
    }
432
    vreader_list_unlock();
433
    return reader;
434
}
435

    
436
/* called from card_emul to initialize the readers */
437
VReaderStatus
438
vreader_add_reader(VReader *reader)
439
{
440
    VReaderListEntry *reader_entry;
441

    
442
    reader_entry = vreader_list_entry_new(reader);
443
    if (reader_entry == NULL) {
444
        return VREADER_OUT_OF_MEMORY;
445
    }
446
    vreader_list_lock();
447
    vreader_queue(vreader_list, reader_entry);
448
    vreader_list_unlock();
449
    vevent_queue_vevent(vevent_new(VEVENT_READER_INSERT, reader, NULL));
450
    return VREADER_OK;
451
}
452

    
453

    
454
VReaderStatus
455
vreader_remove_reader(VReader *reader)
456
{
457
    VReaderListEntry *current_entry;
458

    
459
    vreader_list_lock();
460
    for (current_entry = vreader_list_get_first(vreader_list); current_entry;
461
         current_entry = vreader_list_get_next(current_entry)) {
462
        if (current_entry->reader == reader) {
463
            break;
464
        }
465
    }
466
    vreader_dequeue(vreader_list, current_entry);
467
    vreader_list_unlock();
468
    vreader_list_entry_delete(current_entry);
469
    vevent_queue_vevent(vevent_new(VEVENT_READER_REMOVE, reader, NULL));
470
    return VREADER_OK;
471
}
472

    
473
/*
474
 * Generate VEVENT_CARD_INSERT or VEVENT_CARD_REMOVE based on vreader
475
 * state. Separated from vreader_insert_card to allow replaying events
476
 * for a given state.
477
 */
478
void
479
vreader_queue_card_event(VReader *reader)
480
{
481
    vevent_queue_vevent(vevent_new(
482
        reader->card ? VEVENT_CARD_INSERT : VEVENT_CARD_REMOVE, reader,
483
        reader->card));
484
}
485

    
486
/*
487
 * insert/remove a new card. for removal, card == NULL
488
 */
489
VReaderStatus
490
vreader_insert_card(VReader *reader, VCard *card)
491
{
492
    vreader_lock(reader);
493
    if (reader->card) {
494
        /* decrement reference count */
495
        vcard_free(reader->card);
496
        reader->card = NULL;
497
    }
498
    reader->card = vcard_reference(card);
499
    vreader_unlock(reader);
500
    vreader_queue_card_event(reader);
501
    return VREADER_OK;
502
}
503

    
504
/*
505
 * initialize all the static reader structures
506
 */
507
void
508
vreader_init(void)
509
{
510
    vreader_list_init();
511
}
512