]> git.proxmox.com Git - qemu.git/blob - libcacard/vreader.c
Merge branch 'target-arm.next' of git://git.linaro.org/people/pmaydell/qemu-arm
[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