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