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 | } |