]> Git Repo - qemu.git/blob - libcacard/vreader.c
Update Makefile to actually install the new efi-enabled nic roms that are used by...
[qemu.git] / libcacard / vreader.c
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 = g_strdup(name);
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
This page took 0.051271 seconds and 4 git commands to generate.