|
|
1.1 root 1: /*
2: * Copyright (C) 2011 Red Hat, Inc.
3: *
4: * CCID Device emulation
5: *
6: * Written by Alon Levy, with contributions from Robert Relyea.
7: *
8: * Based on usb-serial.c, see its copyright and attributions below.
9: *
10: * This work is licensed under the terms of the GNU GPL, version 2.1 or later.
11: * See the COPYING file in the top-level directory.
12: * ------- (original copyright & attribution for usb-serial.c below) --------
13: * Copyright (c) 2006 CodeSourcery.
14: * Copyright (c) 2008 Samuel Thibault <[email protected]>
15: * Written by Paul Brook, reused for FTDI by Samuel Thibault,
16: */
17:
18: /*
19: * References:
20: *
21: * CCID Specification Revision 1.1 April 22nd 2005
22: * "Universal Serial Bus, Device Class: Smart Card"
23: * Specification for Integrated Circuit(s) Cards Interface Devices
24: *
25: * Endianness note: from the spec (1.3)
26: * "Fields that are larger than a byte are stored in little endian"
27: *
28: * KNOWN BUGS
29: * 1. remove/insert can sometimes result in removed state instead of inserted.
30: * This is a result of the following:
31: * symptom: dmesg shows ERMOTEIO (-121), pcscd shows -99. This can happen
32: * when a short packet is sent, as seen in uhci-usb.c, resulting from a urb
33: * from the guest requesting SPD and us returning a smaller packet.
34: * Not sure which messages trigger this.
35: */
36:
37: #include "qemu-common.h"
38: #include "qemu-error.h"
39: #include "hw/usb.h"
40: #include "hw/usb/desc.h"
41: #include "monitor.h"
42:
43: #include "hw/ccid.h"
44:
45: #define DPRINTF(s, lvl, fmt, ...) \
46: do { \
47: if (lvl <= s->debug) { \
48: printf("usb-ccid: " fmt , ## __VA_ARGS__); \
49: } \
50: } while (0)
51:
52: #define D_WARN 1
53: #define D_INFO 2
54: #define D_MORE_INFO 3
55: #define D_VERBOSE 4
56:
57: #define CCID_DEV_NAME "usb-ccid"
58:
59: /*
60: * The two options for variable sized buffers:
61: * make them constant size, for large enough constant,
62: * or handle the migration complexity - VMState doesn't handle this case.
63: * sizes are expected never to be exceeded, unless guest misbehaves.
64: */
65: #define BULK_OUT_DATA_SIZE 65536
66: #define PENDING_ANSWERS_NUM 128
67:
68: #define BULK_IN_BUF_SIZE 384
69: #define BULK_IN_PENDING_NUM 8
70:
71: #define InterfaceOutClass \
72: ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)<<8)
73:
74: #define InterfaceInClass \
75: ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE)<<8)
76:
77: #define CCID_MAX_PACKET_SIZE 64
78:
79: #define CCID_CONTROL_ABORT 0x1
80: #define CCID_CONTROL_GET_CLOCK_FREQUENCIES 0x2
81: #define CCID_CONTROL_GET_DATA_RATES 0x3
82:
83: #define CCID_PRODUCT_DESCRIPTION "QEMU USB CCID"
84: #define CCID_VENDOR_DESCRIPTION "QEMU " QEMU_VERSION
85: #define CCID_INTERFACE_NAME "CCID Interface"
86: #define CCID_SERIAL_NUMBER_STRING "1"
87: /*
88: * Using Gemplus Vendor and Product id
89: * Effect on various drivers:
90: * usbccid.sys (winxp, others untested) is a class driver so it doesn't care.
91: * linux has a number of class drivers, but openct filters based on
92: * vendor/product (/etc/openct.conf under fedora), hence Gemplus.
93: */
94: #define CCID_VENDOR_ID 0x08e6
95: #define CCID_PRODUCT_ID 0x4433
96: #define CCID_DEVICE_VERSION 0x0000
97:
98: /*
99: * BULK_OUT messages from PC to Reader
100: * Defined in CCID Rev 1.1 6.1 (page 26)
101: */
102: #define CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOn 0x62
103: #define CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOff 0x63
104: #define CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus 0x65
105: #define CCID_MESSAGE_TYPE_PC_to_RDR_XfrBlock 0x6f
106: #define CCID_MESSAGE_TYPE_PC_to_RDR_GetParameters 0x6c
107: #define CCID_MESSAGE_TYPE_PC_to_RDR_ResetParameters 0x6d
108: #define CCID_MESSAGE_TYPE_PC_to_RDR_SetParameters 0x61
109: #define CCID_MESSAGE_TYPE_PC_to_RDR_Escape 0x6b
110: #define CCID_MESSAGE_TYPE_PC_to_RDR_IccClock 0x6e
111: #define CCID_MESSAGE_TYPE_PC_to_RDR_T0APDU 0x6a
112: #define CCID_MESSAGE_TYPE_PC_to_RDR_Secure 0x69
113: #define CCID_MESSAGE_TYPE_PC_to_RDR_Mechanical 0x71
114: #define CCID_MESSAGE_TYPE_PC_to_RDR_Abort 0x72
115: #define CCID_MESSAGE_TYPE_PC_to_RDR_SetDataRateAndClockFrequency 0x73
116:
117: /*
118: * BULK_IN messages from Reader to PC
119: * Defined in CCID Rev 1.1 6.2 (page 48)
120: */
121: #define CCID_MESSAGE_TYPE_RDR_to_PC_DataBlock 0x80
122: #define CCID_MESSAGE_TYPE_RDR_to_PC_SlotStatus 0x81
123: #define CCID_MESSAGE_TYPE_RDR_to_PC_Parameters 0x82
124: #define CCID_MESSAGE_TYPE_RDR_to_PC_Escape 0x83
125: #define CCID_MESSAGE_TYPE_RDR_to_PC_DataRateAndClockFrequency 0x84
126:
127: /*
128: * INTERRUPT_IN messages from Reader to PC
129: * Defined in CCID Rev 1.1 6.3 (page 56)
130: */
131: #define CCID_MESSAGE_TYPE_RDR_to_PC_NotifySlotChange 0x50
132: #define CCID_MESSAGE_TYPE_RDR_to_PC_HardwareError 0x51
133:
134: /*
135: * Endpoints for CCID - addresses are up to us to decide.
136: * To support slot insertion and removal we must have an interrupt in ep
137: * in addition we need a bulk in and bulk out ep
138: * 5.2, page 20
139: */
140: #define CCID_INT_IN_EP 1
141: #define CCID_BULK_IN_EP 2
142: #define CCID_BULK_OUT_EP 3
143:
144: /* bmSlotICCState masks */
145: #define SLOT_0_STATE_MASK 1
146: #define SLOT_0_CHANGED_MASK 2
147:
148: /* Status codes that go in bStatus (see 6.2.6) */
149: enum {
150: ICC_STATUS_PRESENT_ACTIVE = 0,
151: ICC_STATUS_PRESENT_INACTIVE,
152: ICC_STATUS_NOT_PRESENT
153: };
154:
155: enum {
156: COMMAND_STATUS_NO_ERROR = 0,
157: COMMAND_STATUS_FAILED,
158: COMMAND_STATUS_TIME_EXTENSION_REQUIRED
159: };
160:
161: /* Error codes that go in bError (see 6.2.6) */
162: enum {
163: ERROR_CMD_NOT_SUPPORTED = 0,
164: ERROR_CMD_ABORTED = -1,
165: ERROR_ICC_MUTE = -2,
166: ERROR_XFR_PARITY_ERROR = -3,
167: ERROR_XFR_OVERRUN = -4,
168: ERROR_HW_ERROR = -5,
169: };
170:
171: /* 6.2.6 RDR_to_PC_SlotStatus definitions */
172: enum {
173: CLOCK_STATUS_RUNNING = 0,
174: /*
175: * 0 - Clock Running, 1 - Clock stopped in State L, 2 - H,
176: * 3 - unknown state. rest are RFU
177: */
178: };
179:
180: typedef struct QEMU_PACKED CCID_Header {
181: uint8_t bMessageType;
182: uint32_t dwLength;
183: uint8_t bSlot;
184: uint8_t bSeq;
185: } CCID_Header;
186:
187: typedef struct QEMU_PACKED CCID_BULK_IN {
188: CCID_Header hdr;
189: uint8_t bStatus; /* Only used in BULK_IN */
190: uint8_t bError; /* Only used in BULK_IN */
191: } CCID_BULK_IN;
192:
193: typedef struct QEMU_PACKED CCID_SlotStatus {
194: CCID_BULK_IN b;
195: uint8_t bClockStatus;
196: } CCID_SlotStatus;
197:
198: typedef struct QEMU_PACKED CCID_Parameter {
199: CCID_BULK_IN b;
200: uint8_t bProtocolNum;
201: uint8_t abProtocolDataStructure[0];
202: } CCID_Parameter;
203:
204: typedef struct QEMU_PACKED CCID_DataBlock {
205: CCID_BULK_IN b;
206: uint8_t bChainParameter;
207: uint8_t abData[0];
208: } CCID_DataBlock;
209:
210: /* 6.1.4 PC_to_RDR_XfrBlock */
211: typedef struct QEMU_PACKED CCID_XferBlock {
212: CCID_Header hdr;
213: uint8_t bBWI; /* Block Waiting Timeout */
214: uint16_t wLevelParameter; /* XXX currently unused */
215: uint8_t abData[0];
216: } CCID_XferBlock;
217:
218: typedef struct QEMU_PACKED CCID_IccPowerOn {
219: CCID_Header hdr;
220: uint8_t bPowerSelect;
221: uint16_t abRFU;
222: } CCID_IccPowerOn;
223:
224: typedef struct QEMU_PACKED CCID_IccPowerOff {
225: CCID_Header hdr;
226: uint16_t abRFU;
227: } CCID_IccPowerOff;
228:
229: typedef struct QEMU_PACKED CCID_SetParameters {
230: CCID_Header hdr;
231: uint8_t bProtocolNum;
232: uint16_t abRFU;
233: uint8_t abProtocolDataStructure[0];
234: } CCID_SetParameters;
235:
236: typedef struct CCID_Notify_Slot_Change {
237: uint8_t bMessageType; /* CCID_MESSAGE_TYPE_RDR_to_PC_NotifySlotChange */
238: uint8_t bmSlotICCState;
239: } CCID_Notify_Slot_Change;
240:
241: /* used for DataBlock response to XferBlock */
242: typedef struct Answer {
243: uint8_t slot;
244: uint8_t seq;
245: } Answer;
246:
247: /* pending BULK_IN messages */
248: typedef struct BulkIn {
249: uint8_t data[BULK_IN_BUF_SIZE];
250: uint32_t len;
251: uint32_t pos;
252: } BulkIn;
253:
254: enum {
255: MIGRATION_NONE,
256: MIGRATION_MIGRATED,
257: };
258:
259: typedef struct CCIDBus {
260: BusState qbus;
261: } CCIDBus;
262:
263: #define MAX_PROTOCOL_SIZE 7
264:
265: /*
266: * powered - defaults to true, changed by PowerOn/PowerOff messages
267: */
268: typedef struct USBCCIDState {
269: USBDevice dev;
270: USBEndpoint *intr;
271: CCIDBus bus;
272: CCIDCardState *card;
273: BulkIn bulk_in_pending[BULK_IN_PENDING_NUM]; /* circular */
274: uint32_t bulk_in_pending_start;
275: uint32_t bulk_in_pending_end; /* first free */
276: uint32_t bulk_in_pending_num;
277: BulkIn *current_bulk_in;
278: uint8_t bulk_out_data[BULK_OUT_DATA_SIZE];
279: uint32_t bulk_out_pos;
280: uint64_t last_answer_error;
281: Answer pending_answers[PENDING_ANSWERS_NUM];
282: uint32_t pending_answers_start;
283: uint32_t pending_answers_end;
284: uint32_t pending_answers_num;
285: uint8_t bError;
286: uint8_t bmCommandStatus;
287: uint8_t bProtocolNum;
288: uint8_t abProtocolDataStructure[MAX_PROTOCOL_SIZE];
289: uint32_t ulProtocolDataStructureSize;
290: uint32_t state_vmstate;
291: uint32_t migration_target_ip;
292: uint16_t migration_target_port;
293: uint8_t migration_state;
294: uint8_t bmSlotICCState;
295: uint8_t powered;
296: uint8_t notify_slot_change;
297: uint8_t debug;
298: } USBCCIDState;
299:
300: /*
301: * CCID Spec chapter 4: CCID uses a standard device descriptor per Chapter 9,
302: * "USB Device Framework", section 9.6.1, in the Universal Serial Bus
303: * Specification.
304: *
305: * This device implemented based on the spec and with an Athena Smart Card
306: * Reader as reference:
307: * 0dc3:1004 Athena Smartcard Solutions, Inc.
308: */
309:
310: static const uint8_t qemu_ccid_descriptor[] = {
311: /* Smart Card Device Class Descriptor */
312: 0x36, /* u8 bLength; */
313: 0x21, /* u8 bDescriptorType; Functional */
314: 0x10, 0x01, /* u16 bcdCCID; CCID Specification Release Number. */
315: 0x00, /*
316: * u8 bMaxSlotIndex; The index of the highest available
317: * slot on this device. All slots are consecutive starting
318: * at 00h.
319: */
320: 0x07, /* u8 bVoltageSupport; 01h - 5.0v, 02h - 3.0, 03 - 1.8 */
321:
322: 0x03, 0x00, /* u32 dwProtocols; RRRR PPPP. RRRR = 0000h.*/
323: 0x00, 0x00, /* PPPP: 0001h = Protocol T=0, 0002h = Protocol T=1 */
324: /* u32 dwDefaultClock; in kHZ (0x0fa0 is 4 MHz) */
325: 0xa0, 0x0f, 0x00, 0x00,
326: /* u32 dwMaximumClock; */
327: 0x00, 0x00, 0x01, 0x00,
328: 0x00, /* u8 bNumClockSupported; *
329: * 0 means just the default and max. */
330: /* u32 dwDataRate ;bps. 9600 == 00002580h */
331: 0x80, 0x25, 0x00, 0x00,
332: /* u32 dwMaxDataRate ; 11520 bps == 0001C200h */
333: 0x00, 0xC2, 0x01, 0x00,
334: 0x00, /* u8 bNumDataRatesSupported; 00 means all rates between
335: * default and max */
336: /* u32 dwMaxIFSD; *
337: * maximum IFSD supported by CCID for protocol *
338: * T=1 (Maximum seen from various cards) */
339: 0xfe, 0x00, 0x00, 0x00,
340: /* u32 dwSyncProtocols; 1 - 2-wire, 2 - 3-wire, 4 - I2C */
341: 0x00, 0x00, 0x00, 0x00,
342: /* u32 dwMechanical; 0 - no special characteristics. */
343: 0x00, 0x00, 0x00, 0x00,
344: /*
345: * u32 dwFeatures;
346: * 0 - No special characteristics
347: * + 2 Automatic parameter configuration based on ATR data
348: * + 4 Automatic activation of ICC on inserting
349: * + 8 Automatic ICC voltage selection
350: * + 10 Automatic ICC clock frequency change
351: * + 20 Automatic baud rate change
352: * + 40 Automatic parameters negotiation made by the CCID
353: * + 80 automatic PPS made by the CCID
354: * 100 CCID can set ICC in clock stop mode
355: * 200 NAD value other then 00 accepted (T=1 protocol)
356: * + 400 Automatic IFSD exchange as first exchange (T=1)
357: * One of the following only:
358: * + 10000 TPDU level exchanges with CCID
359: * 20000 Short APDU level exchange with CCID
360: * 40000 Short and Extended APDU level exchange with CCID
361: *
362: * + 100000 USB Wake up signaling supported on card
363: * insertion and removal. Must set bit 5 in bmAttributes
364: * in Configuration descriptor if 100000 is set.
365: */
366: 0xfe, 0x04, 0x11, 0x00,
367: /*
368: * u32 dwMaxCCIDMessageLength; For extended APDU in
369: * [261 + 10 , 65544 + 10]. Otherwise the minimum is
370: * wMaxPacketSize of the Bulk-OUT endpoint
371: */
372: 0x12, 0x00, 0x01, 0x00,
373: 0xFF, /*
374: * u8 bClassGetResponse; Significant only for CCID that
375: * offers an APDU level for exchanges. Indicates the
376: * default class value used by the CCID when it sends a
377: * Get Response command to perform the transportation of
378: * an APDU by T=0 protocol
379: * FFh indicates that the CCID echos the class of the APDU.
380: */
381: 0xFF, /*
382: * u8 bClassEnvelope; EAPDU only. Envelope command for
383: * T=0
384: */
385: 0x00, 0x00, /*
386: * u16 wLcdLayout; XXYY Number of lines (XX) and chars per
387: * line for LCD display used for PIN entry. 0000 - no LCD
388: */
389: 0x01, /*
390: * u8 bPINSupport; 01h PIN Verification,
391: * 02h PIN Modification
392: */
393: 0x01, /* u8 bMaxCCIDBusySlots; */
394: };
395:
396: enum {
397: STR_MANUFACTURER = 1,
398: STR_PRODUCT,
399: STR_SERIALNUMBER,
400: STR_INTERFACE,
401: };
402:
403: static const USBDescStrings desc_strings = {
404: [STR_MANUFACTURER] = "QEMU " QEMU_VERSION,
405: [STR_PRODUCT] = "QEMU USB CCID",
406: [STR_SERIALNUMBER] = "1",
407: [STR_INTERFACE] = "CCID Interface",
408: };
409:
410: static const USBDescIface desc_iface0 = {
411: .bInterfaceNumber = 0,
412: .bNumEndpoints = 3,
413: .bInterfaceClass = 0x0b,
414: .bInterfaceSubClass = 0x00,
415: .bInterfaceProtocol = 0x00,
416: .iInterface = STR_INTERFACE,
417: .ndesc = 1,
418: .descs = (USBDescOther[]) {
419: {
420: /* smartcard descriptor */
421: .data = qemu_ccid_descriptor,
422: },
423: },
424: .eps = (USBDescEndpoint[]) {
425: {
426: .bEndpointAddress = USB_DIR_IN | CCID_INT_IN_EP,
427: .bmAttributes = USB_ENDPOINT_XFER_INT,
428: .bInterval = 255,
429: .wMaxPacketSize = 64,
430: },{
431: .bEndpointAddress = USB_DIR_IN | CCID_BULK_IN_EP,
432: .bmAttributes = USB_ENDPOINT_XFER_BULK,
433: .wMaxPacketSize = 64,
434: },{
435: .bEndpointAddress = USB_DIR_OUT | CCID_BULK_OUT_EP,
436: .bmAttributes = USB_ENDPOINT_XFER_BULK,
437: .wMaxPacketSize = 64,
438: },
439: }
440: };
441:
442: static const USBDescDevice desc_device = {
443: .bcdUSB = 0x0110,
444: .bMaxPacketSize0 = 64,
445: .bNumConfigurations = 1,
446: .confs = (USBDescConfig[]) {
447: {
448: .bNumInterfaces = 1,
449: .bConfigurationValue = 1,
450: .bmAttributes = 0xe0,
451: .bMaxPower = 50,
452: .nif = 1,
453: .ifs = &desc_iface0,
454: },
455: },
456: };
457:
458: static const USBDesc desc_ccid = {
459: .id = {
460: .idVendor = CCID_VENDOR_ID,
461: .idProduct = CCID_PRODUCT_ID,
462: .bcdDevice = CCID_DEVICE_VERSION,
463: .iManufacturer = STR_MANUFACTURER,
464: .iProduct = STR_PRODUCT,
465: .iSerialNumber = STR_SERIALNUMBER,
466: },
467: .full = &desc_device,
468: .str = desc_strings,
469: };
470:
471: static const uint8_t *ccid_card_get_atr(CCIDCardState *card, uint32_t *len)
472: {
473: CCIDCardClass *cc = CCID_CARD_GET_CLASS(card);
474: if (cc->get_atr) {
475: return cc->get_atr(card, len);
476: }
477: return NULL;
478: }
479:
480: static void ccid_card_apdu_from_guest(CCIDCardState *card,
481: const uint8_t *apdu,
482: uint32_t len)
483: {
484: CCIDCardClass *cc = CCID_CARD_GET_CLASS(card);
485: if (cc->apdu_from_guest) {
486: cc->apdu_from_guest(card, apdu, len);
487: }
488: }
489:
490: static int ccid_card_exitfn(CCIDCardState *card)
491: {
492: CCIDCardClass *cc = CCID_CARD_GET_CLASS(card);
493: if (cc->exitfn) {
494: return cc->exitfn(card);
495: }
496: return 0;
497: }
498:
499: static int ccid_card_initfn(CCIDCardState *card)
500: {
501: CCIDCardClass *cc = CCID_CARD_GET_CLASS(card);
502: if (cc->initfn) {
503: return cc->initfn(card);
504: }
505: return 0;
506: }
507:
508: static bool ccid_has_pending_answers(USBCCIDState *s)
509: {
510: return s->pending_answers_num > 0;
511: }
512:
513: static void ccid_clear_pending_answers(USBCCIDState *s)
514: {
515: s->pending_answers_num = 0;
516: s->pending_answers_start = 0;
517: s->pending_answers_end = 0;
518: }
519:
520: static void ccid_print_pending_answers(USBCCIDState *s)
521: {
522: Answer *answer;
523: int i, count;
524:
525: DPRINTF(s, D_VERBOSE, "usb-ccid: pending answers:");
526: if (!ccid_has_pending_answers(s)) {
527: DPRINTF(s, D_VERBOSE, " empty\n");
528: return;
529: }
530: for (i = s->pending_answers_start, count = s->pending_answers_num ;
531: count > 0; count--, i++) {
532: answer = &s->pending_answers[i % PENDING_ANSWERS_NUM];
533: if (count == 1) {
534: DPRINTF(s, D_VERBOSE, "%d:%d\n", answer->slot, answer->seq);
535: } else {
536: DPRINTF(s, D_VERBOSE, "%d:%d,", answer->slot, answer->seq);
537: }
538: }
539: }
540:
541: static void ccid_add_pending_answer(USBCCIDState *s, CCID_Header *hdr)
542: {
543: Answer *answer;
544:
545: assert(s->pending_answers_num < PENDING_ANSWERS_NUM);
546: s->pending_answers_num++;
547: answer =
548: &s->pending_answers[(s->pending_answers_end++) % PENDING_ANSWERS_NUM];
549: answer->slot = hdr->bSlot;
550: answer->seq = hdr->bSeq;
551: ccid_print_pending_answers(s);
552: }
553:
554: static void ccid_remove_pending_answer(USBCCIDState *s,
555: uint8_t *slot, uint8_t *seq)
556: {
557: Answer *answer;
558:
559: assert(s->pending_answers_num > 0);
560: s->pending_answers_num--;
561: answer =
562: &s->pending_answers[(s->pending_answers_start++) % PENDING_ANSWERS_NUM];
563: *slot = answer->slot;
564: *seq = answer->seq;
565: ccid_print_pending_answers(s);
566: }
567:
568: static void ccid_bulk_in_clear(USBCCIDState *s)
569: {
570: s->bulk_in_pending_start = 0;
571: s->bulk_in_pending_end = 0;
572: s->bulk_in_pending_num = 0;
573: }
574:
575: static void ccid_bulk_in_release(USBCCIDState *s)
576: {
577: assert(s->current_bulk_in != NULL);
578: s->current_bulk_in->pos = 0;
579: s->current_bulk_in = NULL;
580: }
581:
582: static void ccid_bulk_in_get(USBCCIDState *s)
583: {
584: if (s->current_bulk_in != NULL || s->bulk_in_pending_num == 0) {
585: return;
586: }
587: assert(s->bulk_in_pending_num > 0);
588: s->bulk_in_pending_num--;
589: s->current_bulk_in =
590: &s->bulk_in_pending[(s->bulk_in_pending_start++) % BULK_IN_PENDING_NUM];
591: }
592:
593: static void *ccid_reserve_recv_buf(USBCCIDState *s, uint16_t len)
594: {
595: BulkIn *bulk_in;
596:
597: DPRINTF(s, D_VERBOSE, "%s: QUEUE: reserve %d bytes\n", __func__, len);
598:
599: /* look for an existing element */
600: if (len > BULK_IN_BUF_SIZE) {
601: DPRINTF(s, D_WARN, "usb-ccid.c: %s: len larger then max (%d>%d). "
602: "discarding message.\n",
603: __func__, len, BULK_IN_BUF_SIZE);
604: return NULL;
605: }
606: if (s->bulk_in_pending_num >= BULK_IN_PENDING_NUM) {
607: DPRINTF(s, D_WARN, "usb-ccid.c: %s: No free bulk_in buffers. "
608: "discarding message.\n", __func__);
609: return NULL;
610: }
611: bulk_in =
612: &s->bulk_in_pending[(s->bulk_in_pending_end++) % BULK_IN_PENDING_NUM];
613: s->bulk_in_pending_num++;
614: bulk_in->len = len;
615: return bulk_in->data;
616: }
617:
618: static void ccid_reset(USBCCIDState *s)
619: {
620: ccid_bulk_in_clear(s);
621: ccid_clear_pending_answers(s);
622: }
623:
624: static void ccid_detach(USBCCIDState *s)
625: {
626: ccid_reset(s);
627: }
628:
629: static void ccid_handle_reset(USBDevice *dev)
630: {
631: USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
632:
633: DPRINTF(s, 1, "Reset\n");
634:
635: ccid_reset(s);
636: }
637:
638: static int ccid_handle_control(USBDevice *dev, USBPacket *p, int request,
639: int value, int index, int length, uint8_t *data)
640: {
641: USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
642: int ret = 0;
643:
644: DPRINTF(s, 1, "got control %x, value %x\n", request, value);
645: ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
646: if (ret >= 0) {
647: return ret;
648: }
649:
650: switch (request) {
651: /* Class specific requests. */
652: case InterfaceOutClass | CCID_CONTROL_ABORT:
653: DPRINTF(s, 1, "ccid_control abort UNIMPLEMENTED\n");
654: ret = USB_RET_STALL;
655: break;
656: case InterfaceInClass | CCID_CONTROL_GET_CLOCK_FREQUENCIES:
657: DPRINTF(s, 1, "ccid_control get clock frequencies UNIMPLEMENTED\n");
658: ret = USB_RET_STALL;
659: break;
660: case InterfaceInClass | CCID_CONTROL_GET_DATA_RATES:
661: DPRINTF(s, 1, "ccid_control get data rates UNIMPLEMENTED\n");
662: ret = USB_RET_STALL;
663: break;
664: default:
665: DPRINTF(s, 1, "got unsupported/bogus control %x, value %x\n",
666: request, value);
667: ret = USB_RET_STALL;
668: break;
669: }
670: return ret;
671: }
672:
673: static bool ccid_card_inserted(USBCCIDState *s)
674: {
675: return s->bmSlotICCState & SLOT_0_STATE_MASK;
676: }
677:
678: static uint8_t ccid_card_status(USBCCIDState *s)
679: {
680: return ccid_card_inserted(s)
681: ? (s->powered ?
682: ICC_STATUS_PRESENT_ACTIVE
683: : ICC_STATUS_PRESENT_INACTIVE
684: )
685: : ICC_STATUS_NOT_PRESENT;
686: }
687:
688: static uint8_t ccid_calc_status(USBCCIDState *s)
689: {
690: /*
691: * page 55, 6.2.6, calculation of bStatus from bmICCStatus and
692: * bmCommandStatus
693: */
694: uint8_t ret = ccid_card_status(s) | (s->bmCommandStatus << 6);
695: DPRINTF(s, D_VERBOSE, "status = %d\n", ret);
696: return ret;
697: }
698:
699: static void ccid_reset_error_status(USBCCIDState *s)
700: {
701: s->bError = ERROR_CMD_NOT_SUPPORTED;
702: s->bmCommandStatus = COMMAND_STATUS_NO_ERROR;
703: }
704:
705: static void ccid_write_slot_status(USBCCIDState *s, CCID_Header *recv)
706: {
707: CCID_SlotStatus *h = ccid_reserve_recv_buf(s, sizeof(CCID_SlotStatus));
708: if (h == NULL) {
709: return;
710: }
711: h->b.hdr.bMessageType = CCID_MESSAGE_TYPE_RDR_to_PC_SlotStatus;
712: h->b.hdr.dwLength = 0;
713: h->b.hdr.bSlot = recv->bSlot;
714: h->b.hdr.bSeq = recv->bSeq;
715: h->b.bStatus = ccid_calc_status(s);
716: h->b.bError = s->bError;
717: h->bClockStatus = CLOCK_STATUS_RUNNING;
718: ccid_reset_error_status(s);
719: }
720:
721: static void ccid_write_parameters(USBCCIDState *s, CCID_Header *recv)
722: {
723: CCID_Parameter *h;
724: uint32_t len = s->ulProtocolDataStructureSize;
725:
726: h = ccid_reserve_recv_buf(s, sizeof(CCID_Parameter) + len);
727: if (h == NULL) {
728: return;
729: }
730: h->b.hdr.bMessageType = CCID_MESSAGE_TYPE_RDR_to_PC_Parameters;
731: h->b.hdr.dwLength = 0;
732: h->b.hdr.bSlot = recv->bSlot;
733: h->b.hdr.bSeq = recv->bSeq;
734: h->b.bStatus = ccid_calc_status(s);
735: h->b.bError = s->bError;
736: h->bProtocolNum = s->bProtocolNum;
737: memcpy(h->abProtocolDataStructure, s->abProtocolDataStructure, len);
738: ccid_reset_error_status(s);
739: }
740:
741: static void ccid_write_data_block(USBCCIDState *s, uint8_t slot, uint8_t seq,
742: const uint8_t *data, uint32_t len)
743: {
744: CCID_DataBlock *p = ccid_reserve_recv_buf(s, sizeof(*p) + len);
745:
746: if (p == NULL) {
747: return;
748: }
749: p->b.hdr.bMessageType = CCID_MESSAGE_TYPE_RDR_to_PC_DataBlock;
750: p->b.hdr.dwLength = cpu_to_le32(len);
751: p->b.hdr.bSlot = slot;
752: p->b.hdr.bSeq = seq;
753: p->b.bStatus = ccid_calc_status(s);
754: p->b.bError = s->bError;
755: if (p->b.bError) {
756: DPRINTF(s, D_VERBOSE, "error %d", p->b.bError);
757: }
758: memcpy(p->abData, data, len);
759: ccid_reset_error_status(s);
760: }
761:
762: static void ccid_write_data_block_answer(USBCCIDState *s,
763: const uint8_t *data, uint32_t len)
764: {
765: uint8_t seq;
766: uint8_t slot;
767:
768: if (!ccid_has_pending_answers(s)) {
769: abort();
770: }
771: ccid_remove_pending_answer(s, &slot, &seq);
772: ccid_write_data_block(s, slot, seq, data, len);
773: }
774:
775: static void ccid_write_data_block_atr(USBCCIDState *s, CCID_Header *recv)
776: {
777: const uint8_t *atr = NULL;
778: uint32_t len = 0;
779:
780: if (s->card) {
781: atr = ccid_card_get_atr(s->card, &len);
782: }
783: ccid_write_data_block(s, recv->bSlot, recv->bSeq, atr, len);
784: }
785:
786: static void ccid_set_parameters(USBCCIDState *s, CCID_Header *recv)
787: {
788: CCID_SetParameters *ph = (CCID_SetParameters *) recv;
789: uint32_t len = 0;
790: if ((ph->bProtocolNum & 3) == 0) {
791: len = 5;
792: }
793: if ((ph->bProtocolNum & 3) == 1) {
794: len = 7;
795: }
796: if (len == 0) {
797: s->bmCommandStatus = COMMAND_STATUS_FAILED;
798: s->bError = 7; /* Protocol invalid or not supported */
799: return;
800: }
801: s->bProtocolNum = ph->bProtocolNum;
802: memcpy(s->abProtocolDataStructure, ph->abProtocolDataStructure, len);
803: s->ulProtocolDataStructureSize = len;
804: DPRINTF(s, 1, "%s: using len %d\n", __func__, len);
805: }
806:
807: /*
808: * must be 5 bytes for T=0, 7 bytes for T=1
809: * See page 52
810: */
811: static const uint8_t abDefaultProtocolDataStructure[7] = {
812: 0x77, 0x00, 0x00, 0x00, 0x00, 0xfe /*IFSC*/, 0x00 /*NAD*/ };
813:
814: static void ccid_reset_parameters(USBCCIDState *s)
815: {
816: uint32_t len = sizeof(abDefaultProtocolDataStructure);
817:
818: s->bProtocolNum = 1; /* T=1 */
819: s->ulProtocolDataStructureSize = len;
820: memcpy(s->abProtocolDataStructure, abDefaultProtocolDataStructure, len);
821: }
822:
823: static void ccid_report_error_failed(USBCCIDState *s, uint8_t error)
824: {
825: s->bmCommandStatus = COMMAND_STATUS_FAILED;
826: s->bError = error;
827: }
828:
829: /* NOTE: only a single slot is supported (SLOT_0) */
830: static void ccid_on_slot_change(USBCCIDState *s, bool full)
831: {
832: /* RDR_to_PC_NotifySlotChange, 6.3.1 page 56 */
833: uint8_t current = s->bmSlotICCState;
834: if (full) {
835: s->bmSlotICCState |= SLOT_0_STATE_MASK;
836: } else {
837: s->bmSlotICCState &= ~SLOT_0_STATE_MASK;
838: }
839: if (current != s->bmSlotICCState) {
840: s->bmSlotICCState |= SLOT_0_CHANGED_MASK;
841: }
842: s->notify_slot_change = true;
843: usb_wakeup(s->intr);
844: }
845:
846: static void ccid_write_data_block_error(
847: USBCCIDState *s, uint8_t slot, uint8_t seq)
848: {
849: ccid_write_data_block(s, slot, seq, NULL, 0);
850: }
851:
852: static void ccid_on_apdu_from_guest(USBCCIDState *s, CCID_XferBlock *recv)
853: {
854: uint32_t len;
855:
856: if (ccid_card_status(s) != ICC_STATUS_PRESENT_ACTIVE) {
857: DPRINTF(s, 1,
858: "usb-ccid: not sending apdu to client, no card connected\n");
859: ccid_write_data_block_error(s, recv->hdr.bSlot, recv->hdr.bSeq);
860: return;
861: }
862: len = le32_to_cpu(recv->hdr.dwLength);
863: DPRINTF(s, 1, "%s: seq %d, len %d\n", __func__,
864: recv->hdr.bSeq, len);
865: ccid_add_pending_answer(s, (CCID_Header *)recv);
866: if (s->card) {
867: ccid_card_apdu_from_guest(s->card, recv->abData, len);
868: } else {
869: DPRINTF(s, D_WARN, "warning: discarded apdu\n");
870: }
871: }
872:
873: /*
874: * Handle a single USB_TOKEN_OUT, return value returned to guest.
875: * Return value:
876: * 0 - all ok
877: * USB_RET_STALL - failed to handle packet
878: */
879: static int ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
880: {
881: CCID_Header *ccid_header;
882:
883: if (p->iov.size + s->bulk_out_pos > BULK_OUT_DATA_SIZE) {
884: return USB_RET_STALL;
885: }
886: ccid_header = (CCID_Header *)s->bulk_out_data;
887: usb_packet_copy(p, s->bulk_out_data + s->bulk_out_pos, p->iov.size);
888: s->bulk_out_pos += p->iov.size;
889: if (p->iov.size == CCID_MAX_PACKET_SIZE) {
890: DPRINTF(s, D_VERBOSE,
891: "usb-ccid: bulk_in: expecting more packets (%zd/%d)\n",
892: p->iov.size, ccid_header->dwLength);
893: return 0;
894: }
895: if (s->bulk_out_pos < 10) {
896: DPRINTF(s, 1,
897: "%s: bad USB_TOKEN_OUT length, should be at least 10 bytes\n",
898: __func__);
899: } else {
900: DPRINTF(s, D_MORE_INFO, "%s %x\n", __func__, ccid_header->bMessageType);
901: switch (ccid_header->bMessageType) {
902: case CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus:
903: ccid_write_slot_status(s, ccid_header);
904: break;
905: case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOn:
906: DPRINTF(s, 1, "PowerOn: %d\n",
907: ((CCID_IccPowerOn *)(ccid_header))->bPowerSelect);
908: s->powered = true;
909: if (!ccid_card_inserted(s)) {
910: ccid_report_error_failed(s, ERROR_ICC_MUTE);
911: }
912: /* atr is written regardless of error. */
913: ccid_write_data_block_atr(s, ccid_header);
914: break;
915: case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOff:
916: DPRINTF(s, 1, "PowerOff\n");
917: ccid_reset_error_status(s);
918: s->powered = false;
919: ccid_write_slot_status(s, ccid_header);
920: break;
921: case CCID_MESSAGE_TYPE_PC_to_RDR_XfrBlock:
922: ccid_on_apdu_from_guest(s, (CCID_XferBlock *)s->bulk_out_data);
923: break;
924: case CCID_MESSAGE_TYPE_PC_to_RDR_SetParameters:
925: ccid_reset_error_status(s);
926: ccid_set_parameters(s, ccid_header);
927: ccid_write_parameters(s, ccid_header);
928: break;
929: case CCID_MESSAGE_TYPE_PC_to_RDR_ResetParameters:
930: ccid_reset_error_status(s);
931: ccid_reset_parameters(s);
932: ccid_write_parameters(s, ccid_header);
933: break;
934: case CCID_MESSAGE_TYPE_PC_to_RDR_GetParameters:
935: ccid_reset_error_status(s);
936: ccid_write_parameters(s, ccid_header);
937: break;
938: default:
939: DPRINTF(s, 1,
940: "handle_data: ERROR: unhandled message type %Xh\n",
941: ccid_header->bMessageType);
942: /*
943: * The caller is expecting the device to respond, tell it we
944: * don't support the operation.
945: */
946: ccid_report_error_failed(s, ERROR_CMD_NOT_SUPPORTED);
947: ccid_write_slot_status(s, ccid_header);
948: break;
949: }
950: }
951: s->bulk_out_pos = 0;
952: return 0;
953: }
954:
955: static int ccid_bulk_in_copy_to_guest(USBCCIDState *s, USBPacket *p)
956: {
957: int ret = 0;
958:
959: assert(p->iov.size > 0);
960: ccid_bulk_in_get(s);
961: if (s->current_bulk_in != NULL) {
962: ret = MIN(s->current_bulk_in->len - s->current_bulk_in->pos,
963: p->iov.size);
964: usb_packet_copy(p, s->current_bulk_in->data +
965: s->current_bulk_in->pos, ret);
966: s->current_bulk_in->pos += ret;
967: if (s->current_bulk_in->pos == s->current_bulk_in->len) {
968: ccid_bulk_in_release(s);
969: }
970: } else {
971: /* return when device has no data - usb 2.0 spec Table 8-4 */
972: ret = USB_RET_NAK;
973: }
974: if (ret > 0) {
975: DPRINTF(s, D_MORE_INFO,
976: "%s: %zd/%d req/act to guest (BULK_IN)\n",
977: __func__, p->iov.size, ret);
978: }
979: if (ret != USB_RET_NAK && ret < p->iov.size) {
980: DPRINTF(s, 1,
981: "%s: returning short (EREMOTEIO) %d < %zd\n",
982: __func__, ret, p->iov.size);
983: }
984: return ret;
985: }
986:
987: static int ccid_handle_data(USBDevice *dev, USBPacket *p)
988: {
989: USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
990: int ret = 0;
991: uint8_t buf[2];
992:
993: switch (p->pid) {
994: case USB_TOKEN_OUT:
995: ret = ccid_handle_bulk_out(s, p);
996: break;
997:
998: case USB_TOKEN_IN:
999: switch (p->ep->nr) {
1000: case CCID_BULK_IN_EP:
1001: if (!p->iov.size) {
1002: ret = USB_RET_NAK;
1003: } else {
1004: ret = ccid_bulk_in_copy_to_guest(s, p);
1005: }
1006: break;
1007: case CCID_INT_IN_EP:
1008: if (s->notify_slot_change) {
1009: /* page 56, RDR_to_PC_NotifySlotChange */
1010: buf[0] = CCID_MESSAGE_TYPE_RDR_to_PC_NotifySlotChange;
1011: buf[1] = s->bmSlotICCState;
1012: usb_packet_copy(p, buf, 2);
1013: ret = 2;
1014: s->notify_slot_change = false;
1015: s->bmSlotICCState &= ~SLOT_0_CHANGED_MASK;
1016: DPRINTF(s, D_INFO,
1017: "handle_data: int_in: notify_slot_change %X, "
1018: "requested len %zd\n",
1019: s->bmSlotICCState, p->iov.size);
1020: }
1021: break;
1022: default:
1023: DPRINTF(s, 1, "Bad endpoint\n");
1024: ret = USB_RET_STALL;
1025: break;
1026: }
1027: break;
1028: default:
1029: DPRINTF(s, 1, "Bad token\n");
1030: ret = USB_RET_STALL;
1031: break;
1032: }
1033:
1034: return ret;
1035: }
1036:
1037: static void ccid_handle_destroy(USBDevice *dev)
1038: {
1039: USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
1040:
1041: ccid_bulk_in_clear(s);
1042: }
1043:
1044: static void ccid_flush_pending_answers(USBCCIDState *s)
1045: {
1046: while (ccid_has_pending_answers(s)) {
1047: ccid_write_data_block_answer(s, NULL, 0);
1048: }
1049: }
1050:
1051: static Answer *ccid_peek_next_answer(USBCCIDState *s)
1052: {
1053: return s->pending_answers_num == 0
1054: ? NULL
1055: : &s->pending_answers[s->pending_answers_start % PENDING_ANSWERS_NUM];
1056: }
1057:
1058: static struct BusInfo ccid_bus_info = {
1059: .name = "ccid-bus",
1060: .size = sizeof(CCIDBus),
1061: .props = (Property[]) {
1062: DEFINE_PROP_UINT32("slot", struct CCIDCardState, slot, 0),
1063: DEFINE_PROP_END_OF_LIST(),
1064: }
1065: };
1066:
1067: void ccid_card_send_apdu_to_guest(CCIDCardState *card,
1068: uint8_t *apdu, uint32_t len)
1069: {
1070: USBCCIDState *s = DO_UPCAST(USBCCIDState, dev.qdev,
1071: card->qdev.parent_bus->parent);
1072: Answer *answer;
1073:
1074: if (!ccid_has_pending_answers(s)) {
1075: DPRINTF(s, 1, "CCID ERROR: got an APDU without pending answers\n");
1076: return;
1077: }
1078: s->bmCommandStatus = COMMAND_STATUS_NO_ERROR;
1079: answer = ccid_peek_next_answer(s);
1080: if (answer == NULL) {
1081: abort();
1082: }
1083: DPRINTF(s, 1, "APDU returned to guest %d (answer seq %d, slot %d)\n",
1084: len, answer->seq, answer->slot);
1085: ccid_write_data_block_answer(s, apdu, len);
1086: }
1087:
1088: void ccid_card_card_removed(CCIDCardState *card)
1089: {
1090: USBCCIDState *s =
1091: DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
1092:
1093: ccid_on_slot_change(s, false);
1094: ccid_flush_pending_answers(s);
1095: ccid_reset(s);
1096: }
1097:
1098: int ccid_card_ccid_attach(CCIDCardState *card)
1099: {
1100: USBCCIDState *s =
1101: DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
1102:
1103: DPRINTF(s, 1, "CCID Attach\n");
1104: if (s->migration_state == MIGRATION_MIGRATED) {
1105: s->migration_state = MIGRATION_NONE;
1106: }
1107: return 0;
1108: }
1109:
1110: void ccid_card_ccid_detach(CCIDCardState *card)
1111: {
1112: USBCCIDState *s =
1113: DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
1114:
1115: DPRINTF(s, 1, "CCID Detach\n");
1116: if (ccid_card_inserted(s)) {
1117: ccid_on_slot_change(s, false);
1118: }
1119: ccid_detach(s);
1120: }
1121:
1122: void ccid_card_card_error(CCIDCardState *card, uint64_t error)
1123: {
1124: USBCCIDState *s =
1125: DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
1126:
1127: s->bmCommandStatus = COMMAND_STATUS_FAILED;
1128: s->last_answer_error = error;
1129: DPRINTF(s, 1, "VSC_Error: %" PRIX64 "\n", s->last_answer_error);
1130: /* TODO: these errors should be more verbose and propagated to the guest.*/
1131: /*
1132: * We flush all pending answers on CardRemove message in ccid-card-passthru,
1133: * so check that first to not trigger abort
1134: */
1135: if (ccid_has_pending_answers(s)) {
1136: ccid_write_data_block_answer(s, NULL, 0);
1137: }
1138: }
1139:
1140: void ccid_card_card_inserted(CCIDCardState *card)
1141: {
1142: USBCCIDState *s =
1143: DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
1144:
1145: s->bmCommandStatus = COMMAND_STATUS_NO_ERROR;
1146: ccid_flush_pending_answers(s);
1147: ccid_on_slot_change(s, true);
1148: }
1149:
1150: static int ccid_card_exit(DeviceState *qdev)
1151: {
1152: int ret = 0;
1153: CCIDCardState *card = CCID_CARD(qdev);
1154: USBCCIDState *s =
1155: DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
1156:
1157: if (ccid_card_inserted(s)) {
1158: ccid_card_card_removed(card);
1159: }
1160: ret = ccid_card_exitfn(card);
1161: s->card = NULL;
1162: return ret;
1163: }
1164:
1165: static int ccid_card_init(DeviceState *qdev)
1166: {
1167: CCIDCardState *card = CCID_CARD(qdev);
1168: USBCCIDState *s =
1169: DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
1170: int ret = 0;
1171:
1172: if (card->slot != 0) {
1173: error_report("Warning: usb-ccid supports one slot, can't add %d",
1174: card->slot);
1175: return -1;
1176: }
1177: if (s->card != NULL) {
1178: error_report("Warning: usb-ccid card already full, not adding");
1179: return -1;
1180: }
1181: ret = ccid_card_initfn(card);
1182: if (ret == 0) {
1183: s->card = card;
1184: }
1185: return ret;
1186: }
1187:
1188: static int ccid_initfn(USBDevice *dev)
1189: {
1190: USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
1191:
1192: usb_desc_create_serial(dev);
1193: usb_desc_init(dev);
1194: qbus_create_inplace(&s->bus.qbus, &ccid_bus_info, &dev->qdev, NULL);
1195: s->intr = usb_ep_get(dev, USB_TOKEN_IN, CCID_INT_IN_EP);
1196: s->bus.qbus.allow_hotplug = 1;
1197: s->card = NULL;
1198: s->migration_state = MIGRATION_NONE;
1199: s->migration_target_ip = 0;
1200: s->migration_target_port = 0;
1201: s->dev.speed = USB_SPEED_FULL;
1202: s->dev.speedmask = USB_SPEED_MASK_FULL;
1203: s->notify_slot_change = false;
1204: s->powered = true;
1205: s->pending_answers_num = 0;
1206: s->last_answer_error = 0;
1207: s->bulk_in_pending_start = 0;
1208: s->bulk_in_pending_end = 0;
1209: s->current_bulk_in = NULL;
1210: ccid_reset_error_status(s);
1211: s->bulk_out_pos = 0;
1212: ccid_reset_parameters(s);
1213: ccid_reset(s);
1214: return 0;
1215: }
1216:
1217: static int ccid_post_load(void *opaque, int version_id)
1218: {
1219: USBCCIDState *s = opaque;
1220:
1221: /*
1222: * This must be done after usb_device_attach, which sets state to ATTACHED,
1223: * while it must be DEFAULT in order to accept packets (like it is after
1224: * reset, but reset will reset our addr and call our reset handler which
1225: * may change state, and we don't want to do that when migrating).
1226: */
1227: s->dev.state = s->state_vmstate;
1228: return 0;
1229: }
1230:
1231: static void ccid_pre_save(void *opaque)
1232: {
1233: USBCCIDState *s = opaque;
1234:
1235: s->state_vmstate = s->dev.state;
1236: if (s->dev.attached) {
1237: /*
1238: * Migrating an open device, ignore reconnection CHR_EVENT to avoid an
1239: * erroneous detach.
1240: */
1241: s->migration_state = MIGRATION_MIGRATED;
1242: }
1243: }
1244:
1245: static VMStateDescription bulk_in_vmstate = {
1246: .name = "CCID BulkIn state",
1247: .version_id = 1,
1248: .minimum_version_id = 1,
1249: .fields = (VMStateField[]) {
1250: VMSTATE_BUFFER(data, BulkIn),
1251: VMSTATE_UINT32(len, BulkIn),
1252: VMSTATE_UINT32(pos, BulkIn),
1253: VMSTATE_END_OF_LIST()
1254: }
1255: };
1256:
1257: static VMStateDescription answer_vmstate = {
1258: .name = "CCID Answer state",
1259: .version_id = 1,
1260: .minimum_version_id = 1,
1261: .fields = (VMStateField[]) {
1262: VMSTATE_UINT8(slot, Answer),
1263: VMSTATE_UINT8(seq, Answer),
1264: VMSTATE_END_OF_LIST()
1265: }
1266: };
1267:
1268: static VMStateDescription usb_device_vmstate = {
1269: .name = "usb_device",
1270: .version_id = 1,
1271: .minimum_version_id = 1,
1272: .fields = (VMStateField[]) {
1273: VMSTATE_UINT8(addr, USBDevice),
1274: VMSTATE_BUFFER(setup_buf, USBDevice),
1275: VMSTATE_BUFFER(data_buf, USBDevice),
1276: VMSTATE_END_OF_LIST()
1277: }
1278: };
1279:
1280: static VMStateDescription ccid_vmstate = {
1281: .name = CCID_DEV_NAME,
1282: .version_id = 1,
1283: .minimum_version_id = 1,
1284: .post_load = ccid_post_load,
1285: .pre_save = ccid_pre_save,
1286: .fields = (VMStateField[]) {
1287: VMSTATE_STRUCT(dev, USBCCIDState, 1, usb_device_vmstate, USBDevice),
1288: VMSTATE_UINT8(debug, USBCCIDState),
1289: VMSTATE_BUFFER(bulk_out_data, USBCCIDState),
1290: VMSTATE_UINT32(bulk_out_pos, USBCCIDState),
1291: VMSTATE_UINT8(bmSlotICCState, USBCCIDState),
1292: VMSTATE_UINT8(powered, USBCCIDState),
1293: VMSTATE_UINT8(notify_slot_change, USBCCIDState),
1294: VMSTATE_UINT64(last_answer_error, USBCCIDState),
1295: VMSTATE_UINT8(bError, USBCCIDState),
1296: VMSTATE_UINT8(bmCommandStatus, USBCCIDState),
1297: VMSTATE_UINT8(bProtocolNum, USBCCIDState),
1298: VMSTATE_BUFFER(abProtocolDataStructure, USBCCIDState),
1299: VMSTATE_UINT32(ulProtocolDataStructureSize, USBCCIDState),
1300: VMSTATE_STRUCT_ARRAY(bulk_in_pending, USBCCIDState,
1301: BULK_IN_PENDING_NUM, 1, bulk_in_vmstate, BulkIn),
1302: VMSTATE_UINT32(bulk_in_pending_start, USBCCIDState),
1303: VMSTATE_UINT32(bulk_in_pending_end, USBCCIDState),
1304: VMSTATE_STRUCT_ARRAY(pending_answers, USBCCIDState,
1305: PENDING_ANSWERS_NUM, 1, answer_vmstate, Answer),
1306: VMSTATE_UINT32(pending_answers_num, USBCCIDState),
1307: VMSTATE_UINT8(migration_state, USBCCIDState),
1308: VMSTATE_UINT32(state_vmstate, USBCCIDState),
1309: VMSTATE_END_OF_LIST()
1310: }
1311: };
1312:
1313: static Property ccid_properties[] = {
1314: DEFINE_PROP_UINT8("debug", USBCCIDState, debug, 0),
1315: DEFINE_PROP_END_OF_LIST(),
1316: };
1317:
1318: static void ccid_class_initfn(ObjectClass *klass, void *data)
1319: {
1320: DeviceClass *dc = DEVICE_CLASS(klass);
1321: USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
1322:
1323: uc->init = ccid_initfn;
1324: uc->product_desc = "QEMU USB CCID";
1325: uc->usb_desc = &desc_ccid;
1326: uc->handle_reset = ccid_handle_reset;
1327: uc->handle_control = ccid_handle_control;
1328: uc->handle_data = ccid_handle_data;
1329: uc->handle_destroy = ccid_handle_destroy;
1330: dc->desc = "CCID Rev 1.1 smartcard reader";
1331: dc->vmsd = &ccid_vmstate;
1332: dc->props = ccid_properties;
1333: }
1334:
1335: static TypeInfo ccid_info = {
1336: .name = CCID_DEV_NAME,
1337: .parent = TYPE_USB_DEVICE,
1338: .instance_size = sizeof(USBCCIDState),
1339: .class_init = ccid_class_initfn,
1340: };
1341:
1342: static void ccid_card_class_init(ObjectClass *klass, void *data)
1343: {
1344: DeviceClass *k = DEVICE_CLASS(klass);
1345: k->bus_info = &ccid_bus_info;
1346: k->init = ccid_card_init;
1347: k->exit = ccid_card_exit;
1348: }
1349:
1350: static TypeInfo ccid_card_type_info = {
1351: .name = TYPE_CCID_CARD,
1352: .parent = TYPE_DEVICE,
1353: .instance_size = sizeof(CCIDCardState),
1354: .abstract = true,
1355: .class_size = sizeof(CCIDCardClass),
1356: .class_init = ccid_card_class_init,
1357: };
1358:
1359: static void ccid_register_types(void)
1360: {
1361: type_register_static(&ccid_card_type_info);
1362: type_register_static(&ccid_info);
1363: usb_legacy_register(CCID_DEV_NAME, "ccid", NULL);
1364: }
1365:
1366: type_init(ccid_register_types)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.