Statistics
| Branch: | Revision:

root / libcacard / vreader.c @ 992aeb8e

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