Statistics
| Branch: | Revision:

root / libcacard / vreader.c @ 92f562ec

History | View | Annotate | Download (11.2 kB)

1 111a38b0 Robert Relyea
/*
2 111a38b0 Robert Relyea
 * emulate the reader
3 111a38b0 Robert Relyea
 *
4 111a38b0 Robert Relyea
 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
5 111a38b0 Robert Relyea
 * See the COPYING.LIB file in the top-level directory.
6 111a38b0 Robert Relyea
 */
7 111a38b0 Robert Relyea
8 111a38b0 Robert Relyea
#include "qemu-common.h"
9 111a38b0 Robert Relyea
#include "qemu-thread.h"
10 111a38b0 Robert Relyea
11 111a38b0 Robert Relyea
#include "vcard.h"
12 111a38b0 Robert Relyea
#include "vcard_emul.h"
13 111a38b0 Robert Relyea
#include "card_7816.h"
14 111a38b0 Robert Relyea
#include "vreader.h"
15 111a38b0 Robert Relyea
#include "vevent.h"
16 111a38b0 Robert Relyea
17 111a38b0 Robert Relyea
struct VReaderStruct {
18 111a38b0 Robert Relyea
    int    reference_count;
19 111a38b0 Robert Relyea
    VCard *card;
20 111a38b0 Robert Relyea
    char *name;
21 111a38b0 Robert Relyea
    vreader_id_t id;
22 111a38b0 Robert Relyea
    QemuMutex lock;
23 111a38b0 Robert Relyea
    VReaderEmul  *reader_private;
24 111a38b0 Robert Relyea
    VReaderEmulFree reader_private_free;
25 111a38b0 Robert Relyea
};
26 111a38b0 Robert Relyea
27 111a38b0 Robert Relyea
/* manage locking */
28 111a38b0 Robert Relyea
static inline void
29 111a38b0 Robert Relyea
vreader_lock(VReader *reader)
30 111a38b0 Robert Relyea
{
31 111a38b0 Robert Relyea
    qemu_mutex_lock(&reader->lock);
32 111a38b0 Robert Relyea
}
33 111a38b0 Robert Relyea
34 111a38b0 Robert Relyea
static inline void
35 111a38b0 Robert Relyea
vreader_unlock(VReader *reader)
36 111a38b0 Robert Relyea
{
37 111a38b0 Robert Relyea
    qemu_mutex_unlock(&reader->lock);
38 111a38b0 Robert Relyea
}
39 111a38b0 Robert Relyea
40 111a38b0 Robert Relyea
/*
41 111a38b0 Robert Relyea
 * vreader constructor
42 111a38b0 Robert Relyea
 */
43 111a38b0 Robert Relyea
VReader *
44 111a38b0 Robert Relyea
vreader_new(const char *name, VReaderEmul *private,
45 111a38b0 Robert Relyea
            VReaderEmulFree private_free)
46 111a38b0 Robert Relyea
{
47 111a38b0 Robert Relyea
    VReader *reader;
48 111a38b0 Robert Relyea
49 7267c094 Anthony Liguori
    reader = (VReader *)g_malloc(sizeof(VReader));
50 111a38b0 Robert Relyea
    qemu_mutex_init(&reader->lock);
51 111a38b0 Robert Relyea
    reader->reference_count = 1;
52 111a38b0 Robert Relyea
    reader->name = name ? strdup(name) : NULL;
53 111a38b0 Robert Relyea
    reader->card = NULL;
54 111a38b0 Robert Relyea
    reader->id = (vreader_id_t)-1;
55 111a38b0 Robert Relyea
    reader->reader_private = private;
56 111a38b0 Robert Relyea
    reader->reader_private_free = private_free;
57 111a38b0 Robert Relyea
    return reader;
58 111a38b0 Robert Relyea
}
59 111a38b0 Robert Relyea
60 111a38b0 Robert Relyea
/* get a reference */
61 111a38b0 Robert Relyea
VReader*
62 111a38b0 Robert Relyea
vreader_reference(VReader *reader)
63 111a38b0 Robert Relyea
{
64 111a38b0 Robert Relyea
    if (reader == NULL) {
65 111a38b0 Robert Relyea
        return NULL;
66 111a38b0 Robert Relyea
    }
67 111a38b0 Robert Relyea
    vreader_lock(reader);
68 111a38b0 Robert Relyea
    reader->reference_count++;
69 111a38b0 Robert Relyea
    vreader_unlock(reader);
70 111a38b0 Robert Relyea
    return reader;
71 111a38b0 Robert Relyea
}
72 111a38b0 Robert Relyea
73 111a38b0 Robert Relyea
/* free a reference */
74 111a38b0 Robert Relyea
void
75 111a38b0 Robert Relyea
vreader_free(VReader *reader)
76 111a38b0 Robert Relyea
{
77 111a38b0 Robert Relyea
    if (reader == NULL) {
78 111a38b0 Robert Relyea
        return;
79 111a38b0 Robert Relyea
    }
80 111a38b0 Robert Relyea
    vreader_lock(reader);
81 111a38b0 Robert Relyea
    if (reader->reference_count-- > 1) {
82 111a38b0 Robert Relyea
        vreader_unlock(reader);
83 111a38b0 Robert Relyea
        return;
84 111a38b0 Robert Relyea
    }
85 111a38b0 Robert Relyea
    vreader_unlock(reader);
86 111a38b0 Robert Relyea
    if (reader->card) {
87 111a38b0 Robert Relyea
        vcard_free(reader->card);
88 111a38b0 Robert Relyea
    }
89 111a38b0 Robert Relyea
    if (reader->name) {
90 7267c094 Anthony Liguori
        g_free(reader->name);
91 111a38b0 Robert Relyea
    }
92 111a38b0 Robert Relyea
    if (reader->reader_private_free) {
93 111a38b0 Robert Relyea
        reader->reader_private_free(reader->reader_private);
94 111a38b0 Robert Relyea
    }
95 7267c094 Anthony Liguori
    g_free(reader);
96 111a38b0 Robert Relyea
    return;
97 111a38b0 Robert Relyea
}
98 111a38b0 Robert Relyea
99 111a38b0 Robert Relyea
static VCard *
100 111a38b0 Robert Relyea
vreader_get_card(VReader *reader)
101 111a38b0 Robert Relyea
{
102 111a38b0 Robert Relyea
    VCard *card;
103 111a38b0 Robert Relyea
104 111a38b0 Robert Relyea
    vreader_lock(reader);
105 111a38b0 Robert Relyea
    card = vcard_reference(reader->card);
106 111a38b0 Robert Relyea
    vreader_unlock(reader);
107 111a38b0 Robert Relyea
    return card;
108 111a38b0 Robert Relyea
}
109 111a38b0 Robert Relyea
110 111a38b0 Robert Relyea
VReaderStatus
111 111a38b0 Robert Relyea
vreader_card_is_present(VReader *reader)
112 111a38b0 Robert Relyea
{
113 111a38b0 Robert Relyea
    VCard *card = vreader_get_card(reader);
114 111a38b0 Robert Relyea
115 111a38b0 Robert Relyea
    if (card == NULL) {
116 111a38b0 Robert Relyea
        return VREADER_NO_CARD;
117 111a38b0 Robert Relyea
    }
118 111a38b0 Robert Relyea
    vcard_free(card);
119 111a38b0 Robert Relyea
    return VREADER_OK;
120 111a38b0 Robert Relyea
}
121 111a38b0 Robert Relyea
122 111a38b0 Robert Relyea
vreader_id_t
123 111a38b0 Robert Relyea
vreader_get_id(VReader *reader)
124 111a38b0 Robert Relyea
{
125 111a38b0 Robert Relyea
    if (reader == NULL) {
126 111a38b0 Robert Relyea
        return (vreader_id_t)-1;
127 111a38b0 Robert Relyea
    }
128 111a38b0 Robert Relyea
    return reader->id;
129 111a38b0 Robert Relyea
}
130 111a38b0 Robert Relyea
131 111a38b0 Robert Relyea
VReaderStatus
132 111a38b0 Robert Relyea
vreader_set_id(VReader *reader, vreader_id_t id)
133 111a38b0 Robert Relyea
{
134 111a38b0 Robert Relyea
    if (reader == NULL) {
135 111a38b0 Robert Relyea
        return VREADER_NO_CARD;
136 111a38b0 Robert Relyea
    }
137 111a38b0 Robert Relyea
    reader->id = id;
138 111a38b0 Robert Relyea
    return VREADER_OK;
139 111a38b0 Robert Relyea
}
140 111a38b0 Robert Relyea
141 111a38b0 Robert Relyea
const char *
142 111a38b0 Robert Relyea
vreader_get_name(VReader *reader)
143 111a38b0 Robert Relyea
{
144 111a38b0 Robert Relyea
    if (reader == NULL) {
145 111a38b0 Robert Relyea
        return NULL;
146 111a38b0 Robert Relyea
    }
147 111a38b0 Robert Relyea
    return reader->name;
148 111a38b0 Robert Relyea
}
149 111a38b0 Robert Relyea
150 111a38b0 Robert Relyea
VReaderEmul *
151 111a38b0 Robert Relyea
vreader_get_private(VReader *reader)
152 111a38b0 Robert Relyea
{
153 111a38b0 Robert Relyea
    return reader->reader_private;
154 111a38b0 Robert Relyea
}
155 111a38b0 Robert Relyea
156 111a38b0 Robert Relyea
static VReaderStatus
157 111a38b0 Robert Relyea
vreader_reset(VReader *reader, VCardPower power, unsigned char *atr, int *len)
158 111a38b0 Robert Relyea
{
159 111a38b0 Robert Relyea
    VCard *card = vreader_get_card(reader);
160 111a38b0 Robert Relyea
161 111a38b0 Robert Relyea
    if (card == NULL) {
162 111a38b0 Robert Relyea
        return VREADER_NO_CARD;
163 111a38b0 Robert Relyea
    }
164 111a38b0 Robert Relyea
    /*
165 111a38b0 Robert Relyea
     * clean up our state
166 111a38b0 Robert Relyea
     */
167 111a38b0 Robert Relyea
    vcard_reset(card, power);
168 111a38b0 Robert Relyea
    if (atr) {
169 111a38b0 Robert Relyea
        vcard_get_atr(card, atr, len);
170 111a38b0 Robert Relyea
    }
171 111a38b0 Robert Relyea
    vcard_free(card); /* free our reference */
172 111a38b0 Robert Relyea
    return VREADER_OK;
173 111a38b0 Robert Relyea
}
174 111a38b0 Robert Relyea
175 111a38b0 Robert Relyea
VReaderStatus
176 111a38b0 Robert Relyea
vreader_power_on(VReader *reader, unsigned char *atr, int *len)
177 111a38b0 Robert Relyea
{
178 111a38b0 Robert Relyea
    return vreader_reset(reader, VCARD_POWER_ON, atr, len);
179 111a38b0 Robert Relyea
}
180 111a38b0 Robert Relyea
181 111a38b0 Robert Relyea
VReaderStatus
182 111a38b0 Robert Relyea
vreader_power_off(VReader *reader)
183 111a38b0 Robert Relyea
{
184 111a38b0 Robert Relyea
    return vreader_reset(reader, VCARD_POWER_OFF, NULL, 0);
185 111a38b0 Robert Relyea
}
186 111a38b0 Robert Relyea
187 111a38b0 Robert Relyea
188 111a38b0 Robert Relyea
VReaderStatus
189 111a38b0 Robert Relyea
vreader_xfr_bytes(VReader *reader,
190 111a38b0 Robert Relyea
                  unsigned char *send_buf, int send_buf_len,
191 111a38b0 Robert Relyea
                  unsigned char *receive_buf, int *receive_buf_len)
192 111a38b0 Robert Relyea
{
193 111a38b0 Robert Relyea
    VCardAPDU *apdu;
194 111a38b0 Robert Relyea
    VCardResponse *response = NULL;
195 111a38b0 Robert Relyea
    VCardStatus card_status;
196 111a38b0 Robert Relyea
    unsigned short status;
197 111a38b0 Robert Relyea
    VCard *card = vreader_get_card(reader);
198 111a38b0 Robert Relyea
199 111a38b0 Robert Relyea
    if (card == NULL) {
200 111a38b0 Robert Relyea
        return VREADER_NO_CARD;
201 111a38b0 Robert Relyea
    }
202 111a38b0 Robert Relyea
203 111a38b0 Robert Relyea
    apdu = vcard_apdu_new(send_buf, send_buf_len, &status);
204 111a38b0 Robert Relyea
    if (apdu == NULL) {
205 111a38b0 Robert Relyea
        response = vcard_make_response(status);
206 111a38b0 Robert Relyea
        card_status = VCARD_DONE;
207 111a38b0 Robert Relyea
    } else {
208 111a38b0 Robert Relyea
        card_status = vcard_process_apdu(card, apdu, &response);
209 111a38b0 Robert Relyea
    }
210 111a38b0 Robert Relyea
    assert(card_status == VCARD_DONE);
211 111a38b0 Robert Relyea
    if (card_status == VCARD_DONE) {
212 111a38b0 Robert Relyea
        int size = MIN(*receive_buf_len, response->b_total_len);
213 111a38b0 Robert Relyea
        memcpy(receive_buf, response->b_data, size);
214 111a38b0 Robert Relyea
        *receive_buf_len = size;
215 111a38b0 Robert Relyea
    }
216 111a38b0 Robert Relyea
    vcard_response_delete(response);
217 111a38b0 Robert Relyea
    vcard_apdu_delete(apdu);
218 111a38b0 Robert Relyea
    vcard_free(card); /* free our reference */
219 111a38b0 Robert Relyea
    return VREADER_OK;
220 111a38b0 Robert Relyea
}
221 111a38b0 Robert Relyea
222 111a38b0 Robert Relyea
struct VReaderListStruct {
223 111a38b0 Robert Relyea
    VReaderListEntry *head;
224 111a38b0 Robert Relyea
    VReaderListEntry *tail;
225 111a38b0 Robert Relyea
};
226 111a38b0 Robert Relyea
227 111a38b0 Robert Relyea
struct VReaderListEntryStruct {
228 111a38b0 Robert Relyea
    VReaderListEntry *next;
229 111a38b0 Robert Relyea
    VReaderListEntry *prev;
230 111a38b0 Robert Relyea
    VReader *reader;
231 111a38b0 Robert Relyea
};
232 111a38b0 Robert Relyea
233 111a38b0 Robert Relyea
234 111a38b0 Robert Relyea
static VReaderListEntry *
235 111a38b0 Robert Relyea
vreader_list_entry_new(VReader *reader)
236 111a38b0 Robert Relyea
{
237 111a38b0 Robert Relyea
    VReaderListEntry *new_reader_list_entry;
238 111a38b0 Robert Relyea
239 111a38b0 Robert Relyea
    new_reader_list_entry = (VReaderListEntry *)
240 7267c094 Anthony Liguori
                               g_malloc(sizeof(VReaderListEntry));
241 111a38b0 Robert Relyea
    new_reader_list_entry->next = NULL;
242 111a38b0 Robert Relyea
    new_reader_list_entry->prev = NULL;
243 111a38b0 Robert Relyea
    new_reader_list_entry->reader = vreader_reference(reader);
244 111a38b0 Robert Relyea
    return new_reader_list_entry;
245 111a38b0 Robert Relyea
}
246 111a38b0 Robert Relyea
247 111a38b0 Robert Relyea
static void
248 111a38b0 Robert Relyea
vreader_list_entry_delete(VReaderListEntry *entry)
249 111a38b0 Robert Relyea
{
250 111a38b0 Robert Relyea
    if (entry == NULL) {
251 111a38b0 Robert Relyea
        return;
252 111a38b0 Robert Relyea
    }
253 111a38b0 Robert Relyea
    vreader_free(entry->reader);
254 7267c094 Anthony Liguori
    g_free(entry);
255 111a38b0 Robert Relyea
}
256 111a38b0 Robert Relyea
257 111a38b0 Robert Relyea
258 111a38b0 Robert Relyea
static VReaderList *
259 111a38b0 Robert Relyea
vreader_list_new(void)
260 111a38b0 Robert Relyea
{
261 111a38b0 Robert Relyea
    VReaderList *new_reader_list;
262 111a38b0 Robert Relyea
263 7267c094 Anthony Liguori
    new_reader_list = (VReaderList *)g_malloc(sizeof(VReaderList));
264 111a38b0 Robert Relyea
    new_reader_list->head = NULL;
265 111a38b0 Robert Relyea
    new_reader_list->tail = NULL;
266 111a38b0 Robert Relyea
    return new_reader_list;
267 111a38b0 Robert Relyea
}
268 111a38b0 Robert Relyea
269 111a38b0 Robert Relyea
void
270 111a38b0 Robert Relyea
vreader_list_delete(VReaderList *list)
271 111a38b0 Robert Relyea
{
272 111a38b0 Robert Relyea
    VReaderListEntry *current_entry;
273 111a38b0 Robert Relyea
    VReaderListEntry *next_entry = NULL;
274 111a38b0 Robert Relyea
    for (current_entry = vreader_list_get_first(list); current_entry;
275 111a38b0 Robert Relyea
         current_entry = next_entry) {
276 111a38b0 Robert Relyea
        next_entry = vreader_list_get_next(current_entry);
277 111a38b0 Robert Relyea
        vreader_list_entry_delete(current_entry);
278 111a38b0 Robert Relyea
    }
279 111a38b0 Robert Relyea
    list->head = NULL;
280 111a38b0 Robert Relyea
    list->tail = NULL;
281 7267c094 Anthony Liguori
    g_free(list);
282 111a38b0 Robert Relyea
}
283 111a38b0 Robert Relyea
284 111a38b0 Robert Relyea
285 111a38b0 Robert Relyea
VReaderListEntry *
286 111a38b0 Robert Relyea
vreader_list_get_first(VReaderList *list)
287 111a38b0 Robert Relyea
{
288 111a38b0 Robert Relyea
    return list ? list->head : NULL;
289 111a38b0 Robert Relyea
}
290 111a38b0 Robert Relyea
291 111a38b0 Robert Relyea
VReaderListEntry *
292 111a38b0 Robert Relyea
vreader_list_get_next(VReaderListEntry *current)
293 111a38b0 Robert Relyea
{
294 111a38b0 Robert Relyea
    return current ? current->next : NULL;
295 111a38b0 Robert Relyea
}
296 111a38b0 Robert Relyea
297 111a38b0 Robert Relyea
VReader *
298 111a38b0 Robert Relyea
vreader_list_get_reader(VReaderListEntry *entry)
299 111a38b0 Robert Relyea
{
300 111a38b0 Robert Relyea
    return entry ? vreader_reference(entry->reader) : NULL;
301 111a38b0 Robert Relyea
}
302 111a38b0 Robert Relyea
303 111a38b0 Robert Relyea
static void
304 111a38b0 Robert Relyea
vreader_queue(VReaderList *list, VReaderListEntry *entry)
305 111a38b0 Robert Relyea
{
306 111a38b0 Robert Relyea
    if (entry == NULL) {
307 111a38b0 Robert Relyea
        return;
308 111a38b0 Robert Relyea
    }
309 111a38b0 Robert Relyea
    entry->next = NULL;
310 111a38b0 Robert Relyea
    entry->prev = list->tail;
311 111a38b0 Robert Relyea
    if (list->head) {
312 111a38b0 Robert Relyea
        list->tail->next = entry;
313 111a38b0 Robert Relyea
    } else {
314 111a38b0 Robert Relyea
        list->head = entry;
315 111a38b0 Robert Relyea
    }
316 111a38b0 Robert Relyea
    list->tail = entry;
317 111a38b0 Robert Relyea
}
318 111a38b0 Robert Relyea
319 111a38b0 Robert Relyea
static void
320 111a38b0 Robert Relyea
vreader_dequeue(VReaderList *list, VReaderListEntry *entry)
321 111a38b0 Robert Relyea
{
322 111a38b0 Robert Relyea
    if (entry == NULL) {
323 111a38b0 Robert Relyea
        return;
324 111a38b0 Robert Relyea
    }
325 111a38b0 Robert Relyea
    if (entry->next == NULL) {
326 111a38b0 Robert Relyea
        list->tail = entry->prev;
327 111a38b0 Robert Relyea
    } else if (entry->prev == NULL) {
328 111a38b0 Robert Relyea
        list->head = entry->next;
329 111a38b0 Robert Relyea
    } else {
330 111a38b0 Robert Relyea
        entry->prev->next = entry->next;
331 111a38b0 Robert Relyea
        entry->next->prev = entry->prev;
332 111a38b0 Robert Relyea
    }
333 111a38b0 Robert Relyea
    if ((list->tail == NULL) || (list->head == NULL)) {
334 111a38b0 Robert Relyea
        list->head = list->tail = NULL;
335 111a38b0 Robert Relyea
    }
336 111a38b0 Robert Relyea
    entry->next = entry->prev = NULL;
337 111a38b0 Robert Relyea
}
338 111a38b0 Robert Relyea
339 111a38b0 Robert Relyea
static VReaderList *vreader_list;
340 111a38b0 Robert Relyea
static QemuMutex vreader_list_mutex;
341 111a38b0 Robert Relyea
342 111a38b0 Robert Relyea
static void
343 111a38b0 Robert Relyea
vreader_list_init(void)
344 111a38b0 Robert Relyea
{
345 111a38b0 Robert Relyea
    vreader_list = vreader_list_new();
346 111a38b0 Robert Relyea
    qemu_mutex_init(&vreader_list_mutex);
347 111a38b0 Robert Relyea
}
348 111a38b0 Robert Relyea
349 111a38b0 Robert Relyea
static void
350 111a38b0 Robert Relyea
vreader_list_lock(void)
351 111a38b0 Robert Relyea
{
352 111a38b0 Robert Relyea
    qemu_mutex_lock(&vreader_list_mutex);
353 111a38b0 Robert Relyea
}
354 111a38b0 Robert Relyea
355 111a38b0 Robert Relyea
static void
356 111a38b0 Robert Relyea
vreader_list_unlock(void)
357 111a38b0 Robert Relyea
{
358 111a38b0 Robert Relyea
    qemu_mutex_unlock(&vreader_list_mutex);
359 111a38b0 Robert Relyea
}
360 111a38b0 Robert Relyea
361 111a38b0 Robert Relyea
static VReaderList *
362 111a38b0 Robert Relyea
vreader_copy_list(VReaderList *list)
363 111a38b0 Robert Relyea
{
364 111a38b0 Robert Relyea
    VReaderList *new_list = NULL;
365 111a38b0 Robert Relyea
    VReaderListEntry *current_entry = NULL;
366 111a38b0 Robert Relyea
367 111a38b0 Robert Relyea
    new_list = vreader_list_new();
368 111a38b0 Robert Relyea
    if (new_list == NULL) {
369 111a38b0 Robert Relyea
        return NULL;
370 111a38b0 Robert Relyea
    }
371 111a38b0 Robert Relyea
    for (current_entry = vreader_list_get_first(list); current_entry;
372 111a38b0 Robert Relyea
         current_entry = vreader_list_get_next(current_entry)) {
373 111a38b0 Robert Relyea
        VReader *reader = vreader_list_get_reader(current_entry);
374 111a38b0 Robert Relyea
        VReaderListEntry *new_entry = vreader_list_entry_new(reader);
375 111a38b0 Robert Relyea
376 111a38b0 Robert Relyea
        vreader_free(reader);
377 111a38b0 Robert Relyea
        vreader_queue(new_list, new_entry);
378 111a38b0 Robert Relyea
    }
379 111a38b0 Robert Relyea
    return new_list;
380 111a38b0 Robert Relyea
}
381 111a38b0 Robert Relyea
382 111a38b0 Robert Relyea
VReaderList *
383 111a38b0 Robert Relyea
vreader_get_reader_list(void)
384 111a38b0 Robert Relyea
{
385 111a38b0 Robert Relyea
    VReaderList *new_reader_list;
386 111a38b0 Robert Relyea
387 111a38b0 Robert Relyea
    vreader_list_lock();
388 111a38b0 Robert Relyea
    new_reader_list = vreader_copy_list(vreader_list);
389 111a38b0 Robert Relyea
    vreader_list_unlock();
390 111a38b0 Robert Relyea
    return new_reader_list;
391 111a38b0 Robert Relyea
}
392 111a38b0 Robert Relyea
393 111a38b0 Robert Relyea
VReader *
394 111a38b0 Robert Relyea
vreader_get_reader_by_id(vreader_id_t id)
395 111a38b0 Robert Relyea
{
396 111a38b0 Robert Relyea
    VReader *reader = NULL;
397 111a38b0 Robert Relyea
    VReaderListEntry *current_entry = NULL;
398 111a38b0 Robert Relyea
399 111a38b0 Robert Relyea
    if (id == (vreader_id_t) -1) {
400 111a38b0 Robert Relyea
        return NULL;
401 111a38b0 Robert Relyea
    }
402 111a38b0 Robert Relyea
403 111a38b0 Robert Relyea
    vreader_list_lock();
404 111a38b0 Robert Relyea
    for (current_entry = vreader_list_get_first(vreader_list); current_entry;
405 111a38b0 Robert Relyea
            current_entry = vreader_list_get_next(current_entry)) {
406 111a38b0 Robert Relyea
        VReader *creader = vreader_list_get_reader(current_entry);
407 111a38b0 Robert Relyea
        if (creader->id == id) {
408 111a38b0 Robert Relyea
            reader = creader;
409 111a38b0 Robert Relyea
            break;
410 111a38b0 Robert Relyea
        }
411 111a38b0 Robert Relyea
        vreader_free(creader);
412 111a38b0 Robert Relyea
    }
413 111a38b0 Robert Relyea
    vreader_list_unlock();
414 111a38b0 Robert Relyea
    return reader;
415 111a38b0 Robert Relyea
}
416 111a38b0 Robert Relyea
417 111a38b0 Robert Relyea
VReader *
418 111a38b0 Robert Relyea
vreader_get_reader_by_name(const char *name)
419 111a38b0 Robert Relyea
{
420 111a38b0 Robert Relyea
    VReader *reader = NULL;
421 111a38b0 Robert Relyea
    VReaderListEntry *current_entry = NULL;
422 111a38b0 Robert Relyea
423 111a38b0 Robert Relyea
    vreader_list_lock();
424 111a38b0 Robert Relyea
    for (current_entry = vreader_list_get_first(vreader_list); current_entry;
425 111a38b0 Robert Relyea
            current_entry = vreader_list_get_next(current_entry)) {
426 111a38b0 Robert Relyea
        VReader *creader = vreader_list_get_reader(current_entry);
427 111a38b0 Robert Relyea
        if (strcmp(creader->name, name) == 0) {
428 111a38b0 Robert Relyea
            reader = creader;
429 111a38b0 Robert Relyea
            break;
430 111a38b0 Robert Relyea
        }
431 111a38b0 Robert Relyea
        vreader_free(creader);
432 111a38b0 Robert Relyea
    }
433 111a38b0 Robert Relyea
    vreader_list_unlock();
434 111a38b0 Robert Relyea
    return reader;
435 111a38b0 Robert Relyea
}
436 111a38b0 Robert Relyea
437 111a38b0 Robert Relyea
/* called from card_emul to initialize the readers */
438 111a38b0 Robert Relyea
VReaderStatus
439 111a38b0 Robert Relyea
vreader_add_reader(VReader *reader)
440 111a38b0 Robert Relyea
{
441 111a38b0 Robert Relyea
    VReaderListEntry *reader_entry;
442 111a38b0 Robert Relyea
443 111a38b0 Robert Relyea
    reader_entry = vreader_list_entry_new(reader);
444 111a38b0 Robert Relyea
    if (reader_entry == NULL) {
445 111a38b0 Robert Relyea
        return VREADER_OUT_OF_MEMORY;
446 111a38b0 Robert Relyea
    }
447 111a38b0 Robert Relyea
    vreader_list_lock();
448 111a38b0 Robert Relyea
    vreader_queue(vreader_list, reader_entry);
449 111a38b0 Robert Relyea
    vreader_list_unlock();
450 111a38b0 Robert Relyea
    vevent_queue_vevent(vevent_new(VEVENT_READER_INSERT, reader, NULL));
451 111a38b0 Robert Relyea
    return VREADER_OK;
452 111a38b0 Robert Relyea
}
453 111a38b0 Robert Relyea
454 111a38b0 Robert Relyea
455 111a38b0 Robert Relyea
VReaderStatus
456 111a38b0 Robert Relyea
vreader_remove_reader(VReader *reader)
457 111a38b0 Robert Relyea
{
458 111a38b0 Robert Relyea
    VReaderListEntry *current_entry;
459 111a38b0 Robert Relyea
460 111a38b0 Robert Relyea
    vreader_list_lock();
461 111a38b0 Robert Relyea
    for (current_entry = vreader_list_get_first(vreader_list); current_entry;
462 111a38b0 Robert Relyea
         current_entry = vreader_list_get_next(current_entry)) {
463 111a38b0 Robert Relyea
        if (current_entry->reader == reader) {
464 111a38b0 Robert Relyea
            break;
465 111a38b0 Robert Relyea
        }
466 111a38b0 Robert Relyea
    }
467 111a38b0 Robert Relyea
    vreader_dequeue(vreader_list, current_entry);
468 111a38b0 Robert Relyea
    vreader_list_unlock();
469 111a38b0 Robert Relyea
    vreader_list_entry_delete(current_entry);
470 111a38b0 Robert Relyea
    vevent_queue_vevent(vevent_new(VEVENT_READER_REMOVE, reader, NULL));
471 111a38b0 Robert Relyea
    return VREADER_OK;
472 111a38b0 Robert Relyea
}
473 111a38b0 Robert Relyea
474 111a38b0 Robert Relyea
/*
475 111a38b0 Robert Relyea
 * Generate VEVENT_CARD_INSERT or VEVENT_CARD_REMOVE based on vreader
476 111a38b0 Robert Relyea
 * state. Separated from vreader_insert_card to allow replaying events
477 111a38b0 Robert Relyea
 * for a given state.
478 111a38b0 Robert Relyea
 */
479 111a38b0 Robert Relyea
void
480 111a38b0 Robert Relyea
vreader_queue_card_event(VReader *reader)
481 111a38b0 Robert Relyea
{
482 111a38b0 Robert Relyea
    vevent_queue_vevent(vevent_new(
483 111a38b0 Robert Relyea
        reader->card ? VEVENT_CARD_INSERT : VEVENT_CARD_REMOVE, reader,
484 111a38b0 Robert Relyea
        reader->card));
485 111a38b0 Robert Relyea
}
486 111a38b0 Robert Relyea
487 111a38b0 Robert Relyea
/*
488 111a38b0 Robert Relyea
 * insert/remove a new card. for removal, card == NULL
489 111a38b0 Robert Relyea
 */
490 111a38b0 Robert Relyea
VReaderStatus
491 111a38b0 Robert Relyea
vreader_insert_card(VReader *reader, VCard *card)
492 111a38b0 Robert Relyea
{
493 111a38b0 Robert Relyea
    vreader_lock(reader);
494 111a38b0 Robert Relyea
    if (reader->card) {
495 111a38b0 Robert Relyea
        /* decrement reference count */
496 111a38b0 Robert Relyea
        vcard_free(reader->card);
497 111a38b0 Robert Relyea
        reader->card = NULL;
498 111a38b0 Robert Relyea
    }
499 111a38b0 Robert Relyea
    reader->card = vcard_reference(card);
500 111a38b0 Robert Relyea
    vreader_unlock(reader);
501 111a38b0 Robert Relyea
    vreader_queue_card_event(reader);
502 111a38b0 Robert Relyea
    return VREADER_OK;
503 111a38b0 Robert Relyea
}
504 111a38b0 Robert Relyea
505 111a38b0 Robert Relyea
/*
506 111a38b0 Robert Relyea
 * initialize all the static reader structures
507 111a38b0 Robert Relyea
 */
508 111a38b0 Robert Relyea
void
509 111a38b0 Robert Relyea
vreader_init(void)
510 111a38b0 Robert Relyea
{
511 111a38b0 Robert Relyea
    vreader_list_init();
512 111a38b0 Robert Relyea
}