root / libcacard / vreader.c @ c2162a8b
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 | } |