]> git.proxmox.com Git - qemu.git/blame - libcacard/vreader.c
net: Refactor net_client_types
[qemu.git] / libcacard / vreader.c
CommitLineData
111a38b0
RR
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
17struct 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 */
28static inline void
29vreader_lock(VReader *reader)
30{
31 qemu_mutex_lock(&reader->lock);
32}
33
34static inline void
35vreader_unlock(VReader *reader)
36{
37 qemu_mutex_unlock(&reader->lock);
38}
39
40/*
41 * vreader constructor
42 */
43VReader *
44vreader_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 */
61VReader*
62vreader_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 */
74void
75vreader_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
99static VCard *
100vreader_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
110VReaderStatus
111vreader_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
122vreader_id_t
123vreader_get_id(VReader *reader)
124{
125 if (reader == NULL) {
126 return (vreader_id_t)-1;
127 }
128 return reader->id;
129}
130
131VReaderStatus
132vreader_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
141const char *
142vreader_get_name(VReader *reader)
143{
144 if (reader == NULL) {
145 return NULL;
146 }
147 return reader->name;
148}
149
150VReaderEmul *
151vreader_get_private(VReader *reader)
152{
153 return reader->reader_private;
154}
155
156static VReaderStatus
157vreader_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
175VReaderStatus
176vreader_power_on(VReader *reader, unsigned char *atr, int *len)
177{
178 return vreader_reset(reader, VCARD_POWER_ON, atr, len);
179}
180
181VReaderStatus
182vreader_power_off(VReader *reader)
183{
184 return vreader_reset(reader, VCARD_POWER_OFF, NULL, 0);
185}
186
187
188VReaderStatus
189vreader_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
222struct VReaderListStruct {
223 VReaderListEntry *head;
224 VReaderListEntry *tail;
225};
226
227struct VReaderListEntryStruct {
228 VReaderListEntry *next;
229 VReaderListEntry *prev;
230 VReader *reader;
231};
232
233
234static VReaderListEntry *
235vreader_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
247static void
248vreader_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
258static VReaderList *
259vreader_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
269void
270vreader_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
285VReaderListEntry *
286vreader_list_get_first(VReaderList *list)
287{
288 return list ? list->head : NULL;
289}
290
291VReaderListEntry *
292vreader_list_get_next(VReaderListEntry *current)
293{
294 return current ? current->next : NULL;
295}
296
297VReader *
298vreader_list_get_reader(VReaderListEntry *entry)
299{
300 return entry ? vreader_reference(entry->reader) : NULL;
301}
302
303static void
304vreader_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
319static void
320vreader_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
339static VReaderList *vreader_list;
340static QemuMutex vreader_list_mutex;
341
342static void
343vreader_list_init(void)
344{
345 vreader_list = vreader_list_new();
346 qemu_mutex_init(&vreader_list_mutex);
347}
348
349static void
350vreader_list_lock(void)
351{
352 qemu_mutex_lock(&vreader_list_mutex);
353}
354
355static void
356vreader_list_unlock(void)
357{
358 qemu_mutex_unlock(&vreader_list_mutex);
359}
360
361static VReaderList *
362vreader_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
382VReaderList *
383vreader_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
393VReader *
394vreader_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
417VReader *
418vreader_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 */
438VReaderStatus
439vreader_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
455VReaderStatus
456vreader_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 */
479void
480vreader_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 */
490VReaderStatus
491vreader_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 */
508void
509vreader_init(void)
510{
511 vreader_list_init();
512}
513