|
|
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 it's 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 "usb.h"
1.1.1.2 ! root 40: #include "usb-desc.h"
1.1 root 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:
1.1.1.2 ! root 180: typedef struct QEMU_PACKED CCID_Header {
1.1 root 181: uint8_t bMessageType;
182: uint32_t dwLength;
183: uint8_t bSlot;
184: uint8_t bSeq;
185: } CCID_Header;
186:
1.1.1.2 ! root 187: typedef struct QEMU_PACKED CCID_BULK_IN {
1.1 root 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:
1.1.1.2 ! root 193: typedef struct QEMU_PACKED CCID_SlotStatus {
1.1 root 194: CCID_BULK_IN b;
195: uint8_t bClockStatus;
196: } CCID_SlotStatus;
197:
1.1.1.2 ! root 198: typedef struct QEMU_PACKED CCID_Parameter {
1.1 root 199: CCID_BULK_IN b;
200: uint8_t bProtocolNum;
201: uint8_t abProtocolDataStructure[0];
202: } CCID_Parameter;
203:
1.1.1.2 ! root 204: typedef struct QEMU_PACKED CCID_DataBlock {
1.1 root 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 */
1.1.1.2 ! root 211: typedef struct QEMU_PACKED CCID_XferBlock {
1.1 root 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:
1.1.1.2 ! root 218: typedef struct QEMU_PACKED CCID_IccPowerOn {
1.1 root 219: CCID_Header hdr;
220: uint8_t bPowerSelect;
221: uint16_t abRFU;
222: } CCID_IccPowerOn;
223:
1.1.1.2 ! root 224: typedef struct QEMU_PACKED CCID_IccPowerOff {
1.1 root 225: CCID_Header hdr;
226: uint16_t abRFU;
227: } CCID_IccPowerOff;
228:
1.1.1.2 ! root 229: typedef struct QEMU_PACKED CCID_SetParameters {
1.1 root 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: CCIDBus bus;
271: CCIDCardState *card;
272: CCIDCardInfo *cardinfo; /* caching the info pointer */
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:
1.1.1.2 ! root 310: static const uint8_t qemu_ccid_descriptor[] = {
1.1 root 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; */
1.1.1.2 ! root 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: };
1.1 root 441:
1.1.1.2 ! root 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 = 0xa0,
! 451: .bMaxPower = 50,
! 452: .nif = 1,
! 453: .ifs = &desc_iface0,
! 454: },
! 455: },
! 456: };
1.1 root 457:
1.1.1.2 ! root 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,
1.1 root 469: };
470:
471: static bool ccid_has_pending_answers(USBCCIDState *s)
472: {
473: return s->pending_answers_num > 0;
474: }
475:
476: static void ccid_clear_pending_answers(USBCCIDState *s)
477: {
478: s->pending_answers_num = 0;
479: s->pending_answers_start = 0;
480: s->pending_answers_end = 0;
481: }
482:
483: static void ccid_print_pending_answers(USBCCIDState *s)
484: {
485: Answer *answer;
486: int i, count;
487:
488: DPRINTF(s, D_VERBOSE, "usb-ccid: pending answers:");
489: if (!ccid_has_pending_answers(s)) {
490: DPRINTF(s, D_VERBOSE, " empty\n");
491: return;
492: }
493: for (i = s->pending_answers_start, count = s->pending_answers_num ;
494: count > 0; count--, i++) {
495: answer = &s->pending_answers[i % PENDING_ANSWERS_NUM];
496: if (count == 1) {
497: DPRINTF(s, D_VERBOSE, "%d:%d\n", answer->slot, answer->seq);
498: } else {
499: DPRINTF(s, D_VERBOSE, "%d:%d,", answer->slot, answer->seq);
500: }
501: }
502: }
503:
504: static void ccid_add_pending_answer(USBCCIDState *s, CCID_Header *hdr)
505: {
506: Answer *answer;
507:
508: assert(s->pending_answers_num < PENDING_ANSWERS_NUM);
509: s->pending_answers_num++;
510: answer =
511: &s->pending_answers[(s->pending_answers_end++) % PENDING_ANSWERS_NUM];
512: answer->slot = hdr->bSlot;
513: answer->seq = hdr->bSeq;
514: ccid_print_pending_answers(s);
515: }
516:
517: static void ccid_remove_pending_answer(USBCCIDState *s,
518: uint8_t *slot, uint8_t *seq)
519: {
520: Answer *answer;
521:
522: assert(s->pending_answers_num > 0);
523: s->pending_answers_num--;
524: answer =
525: &s->pending_answers[(s->pending_answers_start++) % PENDING_ANSWERS_NUM];
526: *slot = answer->slot;
527: *seq = answer->seq;
528: ccid_print_pending_answers(s);
529: }
530:
531: static void ccid_bulk_in_clear(USBCCIDState *s)
532: {
533: s->bulk_in_pending_start = 0;
534: s->bulk_in_pending_end = 0;
535: s->bulk_in_pending_num = 0;
536: }
537:
538: static void ccid_bulk_in_release(USBCCIDState *s)
539: {
540: assert(s->current_bulk_in != NULL);
541: s->current_bulk_in->pos = 0;
542: s->current_bulk_in = NULL;
543: }
544:
545: static void ccid_bulk_in_get(USBCCIDState *s)
546: {
547: if (s->current_bulk_in != NULL || s->bulk_in_pending_num == 0) {
548: return;
549: }
550: assert(s->bulk_in_pending_num > 0);
551: s->bulk_in_pending_num--;
552: s->current_bulk_in =
553: &s->bulk_in_pending[(s->bulk_in_pending_start++) % BULK_IN_PENDING_NUM];
554: }
555:
556: static void *ccid_reserve_recv_buf(USBCCIDState *s, uint16_t len)
557: {
558: BulkIn *bulk_in;
559:
560: DPRINTF(s, D_VERBOSE, "%s: QUEUE: reserve %d bytes\n", __func__, len);
561:
562: /* look for an existing element */
563: if (len > BULK_IN_BUF_SIZE) {
564: DPRINTF(s, D_WARN, "usb-ccid.c: %s: len larger then max (%d>%d). "
565: "discarding message.\n",
566: __func__, len, BULK_IN_BUF_SIZE);
567: return NULL;
568: }
569: if (s->bulk_in_pending_num >= BULK_IN_PENDING_NUM) {
570: DPRINTF(s, D_WARN, "usb-ccid.c: %s: No free bulk_in buffers. "
571: "discarding message.\n", __func__);
572: return NULL;
573: }
574: bulk_in =
575: &s->bulk_in_pending[(s->bulk_in_pending_end++) % BULK_IN_PENDING_NUM];
576: s->bulk_in_pending_num++;
577: bulk_in->len = len;
578: return bulk_in->data;
579: }
580:
581: static void ccid_reset(USBCCIDState *s)
582: {
583: ccid_bulk_in_clear(s);
584: ccid_clear_pending_answers(s);
585: }
586:
587: static void ccid_detach(USBCCIDState *s)
588: {
589: ccid_reset(s);
590: }
591:
592: static void ccid_handle_reset(USBDevice *dev)
593: {
594: USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
595:
596: DPRINTF(s, 1, "Reset\n");
597:
598: ccid_reset(s);
599: }
600:
601: static int ccid_handle_control(USBDevice *dev, USBPacket *p, int request,
602: int value, int index, int length, uint8_t *data)
603: {
604: USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
605: int ret = 0;
606:
607: DPRINTF(s, 1, "got control %x, value %x\n", request, value);
1.1.1.2 ! root 608: ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
! 609: if (ret >= 0) {
! 610: return ret;
! 611: }
! 612:
1.1 root 613: switch (request) {
614: case DeviceRequest | USB_REQ_GET_INTERFACE:
615: data[0] = 0;
616: ret = 1;
617: break;
618: case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
619: ret = 0;
620: break;
621:
622: /* Class specific requests. */
623: case InterfaceOutClass | CCID_CONTROL_ABORT:
624: DPRINTF(s, 1, "ccid_control abort UNIMPLEMENTED\n");
625: ret = USB_RET_STALL;
626: break;
627: case InterfaceInClass | CCID_CONTROL_GET_CLOCK_FREQUENCIES:
628: DPRINTF(s, 1, "ccid_control get clock frequencies UNIMPLEMENTED\n");
629: ret = USB_RET_STALL;
630: break;
631: case InterfaceInClass | CCID_CONTROL_GET_DATA_RATES:
632: DPRINTF(s, 1, "ccid_control get data rates UNIMPLEMENTED\n");
633: ret = USB_RET_STALL;
634: break;
635: default:
636: DPRINTF(s, 1, "got unsupported/bogus control %x, value %x\n",
637: request, value);
638: ret = USB_RET_STALL;
639: break;
640: }
641: return ret;
642: }
643:
644: static bool ccid_card_inserted(USBCCIDState *s)
645: {
646: return s->bmSlotICCState & SLOT_0_STATE_MASK;
647: }
648:
649: static uint8_t ccid_card_status(USBCCIDState *s)
650: {
651: return ccid_card_inserted(s)
652: ? (s->powered ?
653: ICC_STATUS_PRESENT_ACTIVE
654: : ICC_STATUS_PRESENT_INACTIVE
655: )
656: : ICC_STATUS_NOT_PRESENT;
657: }
658:
659: static uint8_t ccid_calc_status(USBCCIDState *s)
660: {
661: /*
662: * page 55, 6.2.6, calculation of bStatus from bmICCStatus and
663: * bmCommandStatus
664: */
665: uint8_t ret = ccid_card_status(s) | (s->bmCommandStatus << 6);
666: DPRINTF(s, D_VERBOSE, "status = %d\n", ret);
667: return ret;
668: }
669:
670: static void ccid_reset_error_status(USBCCIDState *s)
671: {
672: s->bError = ERROR_CMD_NOT_SUPPORTED;
673: s->bmCommandStatus = COMMAND_STATUS_NO_ERROR;
674: }
675:
676: static void ccid_write_slot_status(USBCCIDState *s, CCID_Header *recv)
677: {
678: CCID_SlotStatus *h = ccid_reserve_recv_buf(s, sizeof(CCID_SlotStatus));
679: if (h == NULL) {
680: return;
681: }
682: h->b.hdr.bMessageType = CCID_MESSAGE_TYPE_RDR_to_PC_SlotStatus;
683: h->b.hdr.dwLength = 0;
684: h->b.hdr.bSlot = recv->bSlot;
685: h->b.hdr.bSeq = recv->bSeq;
686: h->b.bStatus = ccid_calc_status(s);
687: h->b.bError = s->bError;
688: h->bClockStatus = CLOCK_STATUS_RUNNING;
689: ccid_reset_error_status(s);
690: }
691:
692: static void ccid_write_parameters(USBCCIDState *s, CCID_Header *recv)
693: {
694: CCID_Parameter *h;
695: uint32_t len = s->ulProtocolDataStructureSize;
696:
697: h = ccid_reserve_recv_buf(s, sizeof(CCID_Parameter) + len);
698: if (h == NULL) {
699: return;
700: }
701: h->b.hdr.bMessageType = CCID_MESSAGE_TYPE_RDR_to_PC_Parameters;
702: h->b.hdr.dwLength = 0;
703: h->b.hdr.bSlot = recv->bSlot;
704: h->b.hdr.bSeq = recv->bSeq;
705: h->b.bStatus = ccid_calc_status(s);
706: h->b.bError = s->bError;
707: h->bProtocolNum = s->bProtocolNum;
708: memcpy(h->abProtocolDataStructure, s->abProtocolDataStructure, len);
709: ccid_reset_error_status(s);
710: }
711:
712: static void ccid_write_data_block(USBCCIDState *s, uint8_t slot, uint8_t seq,
713: const uint8_t *data, uint32_t len)
714: {
715: CCID_DataBlock *p = ccid_reserve_recv_buf(s, sizeof(*p) + len);
716:
717: if (p == NULL) {
718: return;
719: }
720: p->b.hdr.bMessageType = CCID_MESSAGE_TYPE_RDR_to_PC_DataBlock;
721: p->b.hdr.dwLength = cpu_to_le32(len);
722: p->b.hdr.bSlot = slot;
723: p->b.hdr.bSeq = seq;
724: p->b.bStatus = ccid_calc_status(s);
725: p->b.bError = s->bError;
726: if (p->b.bError) {
727: DPRINTF(s, D_VERBOSE, "error %d", p->b.bError);
728: }
729: memcpy(p->abData, data, len);
730: ccid_reset_error_status(s);
731: }
732:
733: static void ccid_write_data_block_answer(USBCCIDState *s,
734: const uint8_t *data, uint32_t len)
735: {
736: uint8_t seq;
737: uint8_t slot;
738:
739: if (!ccid_has_pending_answers(s)) {
740: abort();
741: }
742: ccid_remove_pending_answer(s, &slot, &seq);
743: ccid_write_data_block(s, slot, seq, data, len);
744: }
745:
746: static void ccid_write_data_block_atr(USBCCIDState *s, CCID_Header *recv)
747: {
748: const uint8_t *atr = NULL;
749: uint32_t len = 0;
750:
751: if (s->card) {
752: atr = s->cardinfo->get_atr(s->card, &len);
753: }
754: ccid_write_data_block(s, recv->bSlot, recv->bSeq, atr, len);
755: }
756:
757: static void ccid_set_parameters(USBCCIDState *s, CCID_Header *recv)
758: {
759: CCID_SetParameters *ph = (CCID_SetParameters *) recv;
760: uint32_t len = 0;
761: if ((ph->bProtocolNum & 3) == 0) {
762: len = 5;
763: }
764: if ((ph->bProtocolNum & 3) == 1) {
765: len = 7;
766: }
767: if (len == 0) {
768: s->bmCommandStatus = COMMAND_STATUS_FAILED;
769: s->bError = 7; /* Protocol invalid or not supported */
770: return;
771: }
772: s->bProtocolNum = ph->bProtocolNum;
773: memcpy(s->abProtocolDataStructure, ph->abProtocolDataStructure, len);
774: s->ulProtocolDataStructureSize = len;
775: DPRINTF(s, 1, "%s: using len %d\n", __func__, len);
776: }
777:
778: /*
779: * must be 5 bytes for T=0, 7 bytes for T=1
780: * See page 52
781: */
782: static const uint8_t abDefaultProtocolDataStructure[7] = {
783: 0x77, 0x00, 0x00, 0x00, 0x00, 0xfe /*IFSC*/, 0x00 /*NAD*/ };
784:
785: static void ccid_reset_parameters(USBCCIDState *s)
786: {
787: uint32_t len = sizeof(abDefaultProtocolDataStructure);
788:
789: s->bProtocolNum = 1; /* T=1 */
790: s->ulProtocolDataStructureSize = len;
791: memcpy(s->abProtocolDataStructure, abDefaultProtocolDataStructure, len);
792: }
793:
794: static void ccid_report_error_failed(USBCCIDState *s, uint8_t error)
795: {
796: s->bmCommandStatus = COMMAND_STATUS_FAILED;
797: s->bError = error;
798: }
799:
800: /* NOTE: only a single slot is supported (SLOT_0) */
801: static void ccid_on_slot_change(USBCCIDState *s, bool full)
802: {
803: /* RDR_to_PC_NotifySlotChange, 6.3.1 page 56 */
804: uint8_t current = s->bmSlotICCState;
805: if (full) {
806: s->bmSlotICCState |= SLOT_0_STATE_MASK;
807: } else {
808: s->bmSlotICCState &= ~SLOT_0_STATE_MASK;
809: }
810: if (current != s->bmSlotICCState) {
811: s->bmSlotICCState |= SLOT_0_CHANGED_MASK;
812: }
813: s->notify_slot_change = true;
1.1.1.2 ! root 814: usb_wakeup(&s->dev);
1.1 root 815: }
816:
817: static void ccid_write_data_block_error(
818: USBCCIDState *s, uint8_t slot, uint8_t seq)
819: {
820: ccid_write_data_block(s, slot, seq, NULL, 0);
821: }
822:
823: static void ccid_on_apdu_from_guest(USBCCIDState *s, CCID_XferBlock *recv)
824: {
825: uint32_t len;
826:
827: if (ccid_card_status(s) != ICC_STATUS_PRESENT_ACTIVE) {
828: DPRINTF(s, 1,
829: "usb-ccid: not sending apdu to client, no card connected\n");
830: ccid_write_data_block_error(s, recv->hdr.bSlot, recv->hdr.bSeq);
831: return;
832: }
833: len = le32_to_cpu(recv->hdr.dwLength);
834: DPRINTF(s, 1, "%s: seq %d, len %d\n", __func__,
835: recv->hdr.bSeq, len);
836: ccid_add_pending_answer(s, (CCID_Header *)recv);
837: if (s->card) {
838: s->cardinfo->apdu_from_guest(s->card, recv->abData, len);
839: } else {
840: DPRINTF(s, D_WARN, "warning: discarded apdu\n");
841: }
842: }
843:
844: /*
845: * Handle a single USB_TOKEN_OUT, return value returned to guest.
846: * Return value:
847: * 0 - all ok
848: * USB_RET_STALL - failed to handle packet
849: */
850: static int ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
851: {
852: CCID_Header *ccid_header;
853:
1.1.1.2 ! root 854: if (p->iov.size + s->bulk_out_pos > BULK_OUT_DATA_SIZE) {
1.1 root 855: return USB_RET_STALL;
856: }
857: ccid_header = (CCID_Header *)s->bulk_out_data;
1.1.1.2 ! root 858: usb_packet_copy(p, s->bulk_out_data + s->bulk_out_pos, p->iov.size);
! 859: s->bulk_out_pos += p->iov.size;
! 860: if (p->iov.size == CCID_MAX_PACKET_SIZE) {
1.1 root 861: DPRINTF(s, D_VERBOSE,
1.1.1.2 ! root 862: "usb-ccid: bulk_in: expecting more packets (%zd/%d)\n",
! 863: p->iov.size, ccid_header->dwLength);
1.1 root 864: return 0;
865: }
866: if (s->bulk_out_pos < 10) {
867: DPRINTF(s, 1,
868: "%s: bad USB_TOKEN_OUT length, should be at least 10 bytes\n",
869: __func__);
870: } else {
871: DPRINTF(s, D_MORE_INFO, "%s %x\n", __func__, ccid_header->bMessageType);
872: switch (ccid_header->bMessageType) {
873: case CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus:
874: ccid_write_slot_status(s, ccid_header);
875: break;
876: case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOn:
877: DPRINTF(s, 1, "PowerOn: %d\n",
878: ((CCID_IccPowerOn *)(ccid_header))->bPowerSelect);
879: s->powered = true;
880: if (!ccid_card_inserted(s)) {
881: ccid_report_error_failed(s, ERROR_ICC_MUTE);
882: }
883: /* atr is written regardless of error. */
884: ccid_write_data_block_atr(s, ccid_header);
885: break;
886: case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOff:
887: DPRINTF(s, 1, "PowerOff\n");
888: ccid_reset_error_status(s);
889: s->powered = false;
890: ccid_write_slot_status(s, ccid_header);
891: break;
892: case CCID_MESSAGE_TYPE_PC_to_RDR_XfrBlock:
893: ccid_on_apdu_from_guest(s, (CCID_XferBlock *)s->bulk_out_data);
894: break;
895: case CCID_MESSAGE_TYPE_PC_to_RDR_SetParameters:
896: ccid_reset_error_status(s);
897: ccid_set_parameters(s, ccid_header);
898: ccid_write_parameters(s, ccid_header);
899: break;
900: case CCID_MESSAGE_TYPE_PC_to_RDR_ResetParameters:
901: ccid_reset_error_status(s);
902: ccid_reset_parameters(s);
903: ccid_write_parameters(s, ccid_header);
904: break;
905: case CCID_MESSAGE_TYPE_PC_to_RDR_GetParameters:
906: ccid_reset_error_status(s);
907: ccid_write_parameters(s, ccid_header);
908: break;
909: default:
910: DPRINTF(s, 1,
911: "handle_data: ERROR: unhandled message type %Xh\n",
912: ccid_header->bMessageType);
913: /*
914: * The caller is expecting the device to respond, tell it we
915: * don't support the operation.
916: */
917: ccid_report_error_failed(s, ERROR_CMD_NOT_SUPPORTED);
918: ccid_write_slot_status(s, ccid_header);
919: break;
920: }
921: }
922: s->bulk_out_pos = 0;
923: return 0;
924: }
925:
1.1.1.2 ! root 926: static int ccid_bulk_in_copy_to_guest(USBCCIDState *s, USBPacket *p)
1.1 root 927: {
928: int ret = 0;
929:
1.1.1.2 ! root 930: assert(p->iov.size > 0);
1.1 root 931: ccid_bulk_in_get(s);
932: if (s->current_bulk_in != NULL) {
1.1.1.2 ! root 933: ret = MIN(s->current_bulk_in->len - s->current_bulk_in->pos,
! 934: p->iov.size);
! 935: usb_packet_copy(p, s->current_bulk_in->data +
! 936: s->current_bulk_in->pos, ret);
1.1 root 937: s->current_bulk_in->pos += ret;
938: if (s->current_bulk_in->pos == s->current_bulk_in->len) {
939: ccid_bulk_in_release(s);
940: }
941: } else {
942: /* return when device has no data - usb 2.0 spec Table 8-4 */
943: ret = USB_RET_NAK;
944: }
945: if (ret > 0) {
946: DPRINTF(s, D_MORE_INFO,
1.1.1.2 ! root 947: "%s: %zd/%d req/act to guest (BULK_IN)\n",
! 948: __func__, p->iov.size, ret);
1.1 root 949: }
1.1.1.2 ! root 950: if (ret != USB_RET_NAK && ret < p->iov.size) {
1.1 root 951: DPRINTF(s, 1,
1.1.1.2 ! root 952: "%s: returning short (EREMOTEIO) %d < %zd\n",
! 953: __func__, ret, p->iov.size);
1.1 root 954: }
955: return ret;
956: }
957:
958: static int ccid_handle_data(USBDevice *dev, USBPacket *p)
959: {
960: USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
961: int ret = 0;
1.1.1.2 ! root 962: uint8_t buf[2];
1.1 root 963:
964: switch (p->pid) {
965: case USB_TOKEN_OUT:
966: ret = ccid_handle_bulk_out(s, p);
967: break;
968:
969: case USB_TOKEN_IN:
970: switch (p->devep & 0xf) {
971: case CCID_BULK_IN_EP:
1.1.1.2 ! root 972: if (!p->iov.size) {
1.1 root 973: ret = USB_RET_NAK;
974: } else {
1.1.1.2 ! root 975: ret = ccid_bulk_in_copy_to_guest(s, p);
1.1 root 976: }
977: break;
978: case CCID_INT_IN_EP:
979: if (s->notify_slot_change) {
980: /* page 56, RDR_to_PC_NotifySlotChange */
1.1.1.2 ! root 981: buf[0] = CCID_MESSAGE_TYPE_RDR_to_PC_NotifySlotChange;
! 982: buf[1] = s->bmSlotICCState;
! 983: usb_packet_copy(p, buf, 2);
1.1 root 984: ret = 2;
985: s->notify_slot_change = false;
986: s->bmSlotICCState &= ~SLOT_0_CHANGED_MASK;
987: DPRINTF(s, D_INFO,
988: "handle_data: int_in: notify_slot_change %X, "
1.1.1.2 ! root 989: "requested len %zd\n",
! 990: s->bmSlotICCState, p->iov.size);
1.1 root 991: }
992: break;
993: default:
994: DPRINTF(s, 1, "Bad endpoint\n");
1.1.1.2 ! root 995: ret = USB_RET_STALL;
1.1 root 996: break;
997: }
998: break;
999: default:
1000: DPRINTF(s, 1, "Bad token\n");
1001: ret = USB_RET_STALL;
1002: break;
1003: }
1004:
1005: return ret;
1006: }
1007:
1008: static void ccid_handle_destroy(USBDevice *dev)
1009: {
1010: USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
1011:
1012: ccid_bulk_in_clear(s);
1013: }
1014:
1015: static void ccid_flush_pending_answers(USBCCIDState *s)
1016: {
1017: while (ccid_has_pending_answers(s)) {
1018: ccid_write_data_block_answer(s, NULL, 0);
1019: }
1020: }
1021:
1022: static Answer *ccid_peek_next_answer(USBCCIDState *s)
1023: {
1024: return s->pending_answers_num == 0
1025: ? NULL
1026: : &s->pending_answers[s->pending_answers_start % PENDING_ANSWERS_NUM];
1027: }
1028:
1029: static struct BusInfo ccid_bus_info = {
1030: .name = "ccid-bus",
1031: .size = sizeof(CCIDBus),
1032: .props = (Property[]) {
1033: DEFINE_PROP_UINT32("slot", struct CCIDCardState, slot, 0),
1034: DEFINE_PROP_END_OF_LIST(),
1035: }
1036: };
1037:
1038: void ccid_card_send_apdu_to_guest(CCIDCardState *card,
1039: uint8_t *apdu, uint32_t len)
1040: {
1041: USBCCIDState *s = DO_UPCAST(USBCCIDState, dev.qdev,
1042: card->qdev.parent_bus->parent);
1043: Answer *answer;
1044:
1045: if (!ccid_has_pending_answers(s)) {
1046: DPRINTF(s, 1, "CCID ERROR: got an APDU without pending answers\n");
1047: return;
1048: }
1049: s->bmCommandStatus = COMMAND_STATUS_NO_ERROR;
1050: answer = ccid_peek_next_answer(s);
1051: if (answer == NULL) {
1052: abort();
1053: }
1054: DPRINTF(s, 1, "APDU returned to guest %d (answer seq %d, slot %d)\n",
1055: len, answer->seq, answer->slot);
1056: ccid_write_data_block_answer(s, apdu, len);
1057: }
1058:
1059: void ccid_card_card_removed(CCIDCardState *card)
1060: {
1061: USBCCIDState *s =
1062: DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
1063:
1064: ccid_on_slot_change(s, false);
1065: ccid_flush_pending_answers(s);
1066: ccid_reset(s);
1067: }
1068:
1069: int ccid_card_ccid_attach(CCIDCardState *card)
1070: {
1071: USBCCIDState *s =
1072: DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
1073:
1074: DPRINTF(s, 1, "CCID Attach\n");
1075: if (s->migration_state == MIGRATION_MIGRATED) {
1076: s->migration_state = MIGRATION_NONE;
1077: }
1078: return 0;
1079: }
1080:
1081: void ccid_card_ccid_detach(CCIDCardState *card)
1082: {
1083: USBCCIDState *s =
1084: DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
1085:
1086: DPRINTF(s, 1, "CCID Detach\n");
1087: if (ccid_card_inserted(s)) {
1088: ccid_on_slot_change(s, false);
1089: }
1090: ccid_detach(s);
1091: }
1092:
1093: void ccid_card_card_error(CCIDCardState *card, uint64_t error)
1094: {
1095: USBCCIDState *s =
1096: DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
1097:
1098: s->bmCommandStatus = COMMAND_STATUS_FAILED;
1099: s->last_answer_error = error;
1100: DPRINTF(s, 1, "VSC_Error: %" PRIX64 "\n", s->last_answer_error);
1101: /* TODO: these errors should be more verbose and propagated to the guest.*/
1102: /*
1103: * We flush all pending answers on CardRemove message in ccid-card-passthru,
1104: * so check that first to not trigger abort
1105: */
1106: if (ccid_has_pending_answers(s)) {
1107: ccid_write_data_block_answer(s, NULL, 0);
1108: }
1109: }
1110:
1111: void ccid_card_card_inserted(CCIDCardState *card)
1112: {
1113: USBCCIDState *s =
1114: DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
1115:
1116: s->bmCommandStatus = COMMAND_STATUS_NO_ERROR;
1117: ccid_flush_pending_answers(s);
1118: ccid_on_slot_change(s, true);
1119: }
1120:
1121: static int ccid_card_exit(DeviceState *qdev)
1122: {
1123: int ret = 0;
1124: CCIDCardState *card = DO_UPCAST(CCIDCardState, qdev, qdev);
1125: CCIDCardInfo *info = DO_UPCAST(CCIDCardInfo, qdev, qdev->info);
1126: USBCCIDState *s =
1127: DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
1128:
1129: if (ccid_card_inserted(s)) {
1130: ccid_card_card_removed(card);
1131: }
1132: if (info->exitfn) {
1133: ret = info->exitfn(card);
1134: }
1135: s->card = NULL;
1136: s->cardinfo = NULL;
1137: return ret;
1138: }
1139:
1140: static int ccid_card_init(DeviceState *qdev, DeviceInfo *base)
1141: {
1142: CCIDCardState *card = DO_UPCAST(CCIDCardState, qdev, qdev);
1143: CCIDCardInfo *info = DO_UPCAST(CCIDCardInfo, qdev, base);
1144: USBCCIDState *s =
1145: DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent);
1146: int ret = 0;
1147:
1148: if (card->slot != 0) {
1149: error_report("Warning: usb-ccid supports one slot, can't add %d",
1150: card->slot);
1151: return -1;
1152: }
1153: if (s->card != NULL) {
1154: error_report("Warning: usb-ccid card already full, not adding");
1155: return -1;
1156: }
1157: ret = info->initfn ? info->initfn(card) : ret;
1158: if (ret == 0) {
1159: s->card = card;
1160: s->cardinfo = info;
1161: }
1162: return ret;
1163: }
1164:
1165: void ccid_card_qdev_register(CCIDCardInfo *card)
1166: {
1167: card->qdev.bus_info = &ccid_bus_info;
1168: card->qdev.init = ccid_card_init;
1169: card->qdev.exit = ccid_card_exit;
1170: qdev_register(&card->qdev);
1171: }
1172:
1173: static int ccid_initfn(USBDevice *dev)
1174: {
1175: USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev);
1176:
1.1.1.2 ! root 1177: usb_desc_init(dev);
1.1 root 1178: qbus_create_inplace(&s->bus.qbus, &ccid_bus_info, &dev->qdev, NULL);
1179: s->bus.qbus.allow_hotplug = 1;
1180: s->card = NULL;
1181: s->cardinfo = NULL;
1182: s->migration_state = MIGRATION_NONE;
1183: s->migration_target_ip = 0;
1184: s->migration_target_port = 0;
1185: s->dev.speed = USB_SPEED_FULL;
1186: s->dev.speedmask = USB_SPEED_MASK_FULL;
1187: s->notify_slot_change = false;
1188: s->powered = true;
1189: s->pending_answers_num = 0;
1190: s->last_answer_error = 0;
1191: s->bulk_in_pending_start = 0;
1192: s->bulk_in_pending_end = 0;
1193: s->current_bulk_in = NULL;
1194: ccid_reset_error_status(s);
1195: s->bulk_out_pos = 0;
1196: ccid_reset_parameters(s);
1197: ccid_reset(s);
1198: return 0;
1199: }
1200:
1201: static int ccid_post_load(void *opaque, int version_id)
1202: {
1203: USBCCIDState *s = opaque;
1204:
1205: /*
1206: * This must be done after usb_device_attach, which sets state to ATTACHED,
1207: * while it must be DEFAULT in order to accept packets (like it is after
1208: * reset, but reset will reset our addr and call our reset handler which
1209: * may change state, and we don't want to do that when migrating).
1210: */
1211: s->dev.state = s->state_vmstate;
1212: return 0;
1213: }
1214:
1215: static void ccid_pre_save(void *opaque)
1216: {
1217: USBCCIDState *s = opaque;
1218:
1219: s->state_vmstate = s->dev.state;
1220: if (s->dev.attached) {
1221: /*
1222: * Migrating an open device, ignore reconnection CHR_EVENT to avoid an
1223: * erroneous detach.
1224: */
1225: s->migration_state = MIGRATION_MIGRATED;
1226: }
1227: }
1228:
1229: static VMStateDescription bulk_in_vmstate = {
1230: .name = "CCID BulkIn state",
1231: .version_id = 1,
1232: .minimum_version_id = 1,
1233: .fields = (VMStateField[]) {
1234: VMSTATE_BUFFER(data, BulkIn),
1235: VMSTATE_UINT32(len, BulkIn),
1236: VMSTATE_UINT32(pos, BulkIn),
1237: VMSTATE_END_OF_LIST()
1238: }
1239: };
1240:
1241: static VMStateDescription answer_vmstate = {
1242: .name = "CCID Answer state",
1243: .version_id = 1,
1244: .minimum_version_id = 1,
1245: .fields = (VMStateField[]) {
1246: VMSTATE_UINT8(slot, Answer),
1247: VMSTATE_UINT8(seq, Answer),
1248: VMSTATE_END_OF_LIST()
1249: }
1250: };
1251:
1252: static VMStateDescription usb_device_vmstate = {
1253: .name = "usb_device",
1254: .version_id = 1,
1255: .minimum_version_id = 1,
1256: .fields = (VMStateField[]) {
1257: VMSTATE_UINT8(addr, USBDevice),
1258: VMSTATE_BUFFER(setup_buf, USBDevice),
1259: VMSTATE_BUFFER(data_buf, USBDevice),
1260: VMSTATE_END_OF_LIST()
1261: }
1262: };
1263:
1264: static VMStateDescription ccid_vmstate = {
1265: .name = CCID_DEV_NAME,
1266: .version_id = 1,
1267: .minimum_version_id = 1,
1268: .post_load = ccid_post_load,
1269: .pre_save = ccid_pre_save,
1270: .fields = (VMStateField[]) {
1271: VMSTATE_STRUCT(dev, USBCCIDState, 1, usb_device_vmstate, USBDevice),
1272: VMSTATE_UINT8(debug, USBCCIDState),
1273: VMSTATE_BUFFER(bulk_out_data, USBCCIDState),
1274: VMSTATE_UINT32(bulk_out_pos, USBCCIDState),
1275: VMSTATE_UINT8(bmSlotICCState, USBCCIDState),
1276: VMSTATE_UINT8(powered, USBCCIDState),
1277: VMSTATE_UINT8(notify_slot_change, USBCCIDState),
1278: VMSTATE_UINT64(last_answer_error, USBCCIDState),
1279: VMSTATE_UINT8(bError, USBCCIDState),
1280: VMSTATE_UINT8(bmCommandStatus, USBCCIDState),
1281: VMSTATE_UINT8(bProtocolNum, USBCCIDState),
1282: VMSTATE_BUFFER(abProtocolDataStructure, USBCCIDState),
1283: VMSTATE_UINT32(ulProtocolDataStructureSize, USBCCIDState),
1284: VMSTATE_STRUCT_ARRAY(bulk_in_pending, USBCCIDState,
1285: BULK_IN_PENDING_NUM, 1, bulk_in_vmstate, BulkIn),
1286: VMSTATE_UINT32(bulk_in_pending_start, USBCCIDState),
1287: VMSTATE_UINT32(bulk_in_pending_end, USBCCIDState),
1288: VMSTATE_STRUCT_ARRAY(pending_answers, USBCCIDState,
1289: PENDING_ANSWERS_NUM, 1, answer_vmstate, Answer),
1290: VMSTATE_UINT32(pending_answers_num, USBCCIDState),
1291: VMSTATE_UINT8(migration_state, USBCCIDState),
1292: VMSTATE_UINT32(state_vmstate, USBCCIDState),
1293: VMSTATE_END_OF_LIST()
1294: }
1295: };
1296:
1297: static struct USBDeviceInfo ccid_info = {
1298: .product_desc = "QEMU USB CCID",
1299: .qdev.name = CCID_DEV_NAME,
1300: .qdev.desc = "CCID Rev 1.1 smartcard reader",
1301: .qdev.size = sizeof(USBCCIDState),
1302: .init = ccid_initfn,
1.1.1.2 ! root 1303: .usb_desc = &desc_ccid,
1.1 root 1304: .handle_packet = usb_generic_handle_packet,
1305: .handle_reset = ccid_handle_reset,
1306: .handle_control = ccid_handle_control,
1307: .handle_data = ccid_handle_data,
1308: .handle_destroy = ccid_handle_destroy,
1309: .usbdevice_name = "ccid",
1310: .qdev.props = (Property[]) {
1311: DEFINE_PROP_UINT8("debug", USBCCIDState, debug, 0),
1312: DEFINE_PROP_END_OF_LIST(),
1313: },
1314: .qdev.vmsd = &ccid_vmstate,
1315: };
1316:
1317: static void ccid_register_devices(void)
1318: {
1319: usb_qdev_register(&ccid_info);
1320: }
1321: device_init(ccid_register_devices)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.