From 1e9e7bc8b88af32f466f7438a06fb8dc96b3035d Mon Sep 17 00:00:00 2001 From: Filipe Rodrigues Date: Sun, 17 Jun 2018 17:51:09 -0700 Subject: CCID: Add support for PC-to-Reader XfrBlock message --- Demos/Device/ClassDriver/CCID/CCID.c | 28 +++++++ Demos/Device/ClassDriver/CCID/CCID.h | 7 ++ Demos/Device/ClassDriver/CCID/Descriptors.c | 4 +- Demos/Device/ClassDriver/CCID/Descriptors.h | 2 +- Demos/Device/LowLevel/CCID/CCID.c | 89 ++++++++++++++++++++-- Demos/Device/LowLevel/CCID/Descriptors.c | 4 +- .../CCID/HostTestApp/test_generic_ccid_libusb.js | 15 ++-- LUFA/Drivers/USB/Class/Common/CCIDClassCommon.h | 20 +++++ LUFA/Drivers/USB/Class/Device/CCIDClassDevice.c | 64 ++++++++++++++-- LUFA/Drivers/USB/Class/Device/CCIDClassDevice.h | 22 ++++++ 10 files changed, 231 insertions(+), 24 deletions(-) diff --git a/Demos/Device/ClassDriver/CCID/CCID.c b/Demos/Device/ClassDriver/CCID/CCID.c index 9059ad40d..bb4c11c45 100644 --- a/Demos/Device/ClassDriver/CCID/CCID.c +++ b/Demos/Device/ClassDriver/CCID/CCID.c @@ -213,6 +213,34 @@ uint8_t CALLBACK_CCID_GetSlotStatus(USB_ClassInfo_CCID_Device_t* const CCIDInter } } +/** Event handler for the CCID_PC_to_RDR_XfrBlock. This message is sent to the device + * whenever an application at the host wants to send a block of bytes to the device + * THe device reply back with an array of bytes + */ +uint8_t CALLBACK_CCID_XfrBlock(USB_ClassInfo_CCID_Device_t* const CCIDInterfaceInfo, + uint8_t slot, + uint8_t* const receivedBuffer, + uint8_t receivedBufferSize, + uint8_t* const sendBuffer, + uint8_t* const sentBufferSize, + uint8_t* const error) +{ + if (slot < CCID_Interface.Config.TotalSlots) + { + uint8_t okResponse[2] = {0x90, 0x00}; + memcpy(sendBuffer, okResponse, sizeof(okResponse)); + *sentBufferSize = sizeof(okResponse); + + *error = CCID_ERROR_NO_ERROR; + return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_NOICCPRESENT; + } + else + { + *error = CCID_ERROR_SLOT_NOT_FOUND; + return CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_NOICCPRESENT; + } +} + uint8_t CALLBACK_CCID_Abort(USB_ClassInfo_CCID_Device_t* const CCIDInterfaceInfo, uint8_t slot, uint8_t seq, diff --git a/Demos/Device/ClassDriver/CCID/CCID.h b/Demos/Device/ClassDriver/CCID/CCID.h index f6dd4adf5..88c29aef1 100644 --- a/Demos/Device/ClassDriver/CCID/CCID.h +++ b/Demos/Device/ClassDriver/CCID/CCID.h @@ -86,6 +86,13 @@ uint8_t CALLBACK_CCID_GetSlotStatus(USB_ClassInfo_CCID_Device_t* const CCIDInterfaceInfo, uint8_t slot, uint8_t* const error); + uint8_t CALLBACK_CCID_XfrBlock(USB_ClassInfo_CCID_Device_t* const CCIDInterfaceInfo, + uint8_t slot, + uint8_t* const receivedBuffer, + uint8_t receivedBufferSize, + uint8_t* const sendBuffer, + uint8_t* const sentBufferSize, + uint8_t* const error); uint8_t CALLBACK_CCID_Abort(USB_ClassInfo_CCID_Device_t* const CCIDInterfaceInfo, uint8_t slot, uint8_t seq, diff --git a/Demos/Device/ClassDriver/CCID/Descriptors.c b/Demos/Device/ClassDriver/CCID/Descriptors.c index 43a696194..886042668 100644 --- a/Demos/Device/ClassDriver/CCID/Descriptors.c +++ b/Demos/Device/ClassDriver/CCID/Descriptors.c @@ -117,8 +117,8 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = .MaxIFSD = 2038, .SynchProtocols = 0, .Mechanical = 0, - .Features = 0x0400fe, - .MaxCCIDMessageLength = 0x0c00, + .Features = CCID_Features_ExchangeLevel_ShortAPDU | CCID_Features_Auto_ParameterConfiguration| CCID_Features_Auto_ICCActivation | CCID_Features_Auto_VoltageSelection, + .MaxCCIDMessageLength = CCID_EPSIZE, .ClassGetResponse = 0xff, .ClassEnvelope = 0xff, .LcdLayout = 0, diff --git a/Demos/Device/ClassDriver/CCID/Descriptors.h b/Demos/Device/ClassDriver/CCID/Descriptors.h index 239d612ab..63672d1b7 100644 --- a/Demos/Device/ClassDriver/CCID/Descriptors.h +++ b/Demos/Device/ClassDriver/CCID/Descriptors.h @@ -49,7 +49,7 @@ /** Endpoint address of the CCID data OUT endpoint, for host-to-device data transfers. */ #define CCID_OUT_EPADDR (ENDPOINT_DIR_OUT | 1) - /** Endpoint size in bytes of the Audio isochronous streaming data IN and OUT endpoints. */ + /** Endpoint size in bytes of the CCID data being sent between IN and OUT endpoints. */ #define CCID_EPSIZE 64 diff --git a/Demos/Device/LowLevel/CCID/CCID.c b/Demos/Device/LowLevel/CCID/CCID.c index 764392de0..24849dc12 100644 --- a/Demos/Device/LowLevel/CCID/CCID.c +++ b/Demos/Device/LowLevel/CCID/CCID.c @@ -252,6 +252,33 @@ uint8_t CCID_GetSlotStatus(uint8_t slot, } } +/** Event handler for the CCID_PC_to_RDR_XfrBlock. This message is sent to the device + * whenever an application at the host wants to send a block of bytes to the device + * THe device reply back with an array of bytes + */ +uint8_t CCID_XfrBlock(uint8_t slot, + uint8_t* const receivedBuffer, + uint8_t receivedBufferSize, + uint8_t* const sendBuffer, + uint8_t* const sentBufferSize, + uint8_t* const error) +{ + if (slot == 0) + { + uint8_t okResponse[2] = {0x90, 0x00}; + memcpy(sendBuffer, okResponse, sizeof(okResponse)); + *sentBufferSize = sizeof(okResponse); + + *error = CCID_ERROR_NO_ERROR; + return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_NOICCPRESENT; + } + else + { + *error = CCID_ERROR_SLOT_NOT_FOUND; + return CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_NOICCPRESENT; + } +} + /** Event handler for the CCID_PC_to_RDR_ABort message. This message is sent to the device * whenever an application wants to abort the current operation. A previous CCID_ABORT * control message has to be sent before this one in order to start the abort operation. @@ -293,7 +320,8 @@ void CCID_Task(void) { Endpoint_SelectEndpoint(CCID_OUT_EPADDR); - uint8_t BlockBuffer[0x20]; + uint8_t RequestBuffer[CCID_EPSIZE - sizeof(USB_CCID_BulkMessage_Header_t)]; + uint8_t ResponseBuffer[CCID_EPSIZE]; Aborted = false; AbortedSeq = -1; @@ -313,7 +341,7 @@ void CCID_Task(void) case CCID_PC_to_RDR_IccPowerOn: { uint8_t AtrLength; - USB_CCID_RDR_to_PC_DataBlock_t* ResponseATR = (USB_CCID_RDR_to_PC_DataBlock_t*)&BlockBuffer; + USB_CCID_RDR_to_PC_DataBlock_t* ResponseATR = (USB_CCID_RDR_to_PC_DataBlock_t*)&ResponseBuffer; ResponseATR->CCIDHeader.MessageType = CCID_RDR_to_PC_DataBlock; ResponseATR->CCIDHeader.Slot = CCIDHeader.Slot; @@ -350,7 +378,7 @@ void CCID_Task(void) case CCID_PC_to_RDR_IccPowerOff: { - USB_CCID_RDR_to_PC_SlotStatus_t* ResponsePowerOff = (USB_CCID_RDR_to_PC_SlotStatus_t*)&BlockBuffer; + USB_CCID_RDR_to_PC_SlotStatus_t* ResponsePowerOff = (USB_CCID_RDR_to_PC_SlotStatus_t*)&ResponseBuffer; ResponsePowerOff->CCIDHeader.MessageType = CCID_RDR_to_PC_SlotStatus; ResponsePowerOff->CCIDHeader.Length = 0; ResponsePowerOff->CCIDHeader.Slot = CCIDHeader.Slot; @@ -373,7 +401,7 @@ void CCID_Task(void) case CCID_PC_to_RDR_GetSlotStatus: { - USB_CCID_RDR_to_PC_SlotStatus_t* ResponseSlotStatus = (USB_CCID_RDR_to_PC_SlotStatus_t*)&BlockBuffer; + USB_CCID_RDR_to_PC_SlotStatus_t* ResponseSlotStatus = (USB_CCID_RDR_to_PC_SlotStatus_t*)&ResponseBuffer; ResponseSlotStatus->CCIDHeader.MessageType = CCID_RDR_to_PC_SlotStatus; ResponseSlotStatus->CCIDHeader.Length = 0; ResponseSlotStatus->CCIDHeader.Slot = CCIDHeader.Slot; @@ -394,9 +422,56 @@ void CCID_Task(void) break; } + case CCID_PC_to_RDR_XfrBlock: + { + uint8_t Bwi = Endpoint_Read_8(); + uint16_t LevelParameter = Endpoint_Read_16_LE(); + + (void)Bwi; + (void)LevelParameter; + + Endpoint_Read_Stream_LE(RequestBuffer, CCIDHeader.Length * sizeof(uint8_t), NULL); + + uint8_t ResponseDataLength = 0; + + USB_CCID_RDR_to_PC_DataBlock_t* ResponseBlock = (USB_CCID_RDR_to_PC_DataBlock_t*)&ResponseBuffer; + ResponseBlock->CCIDHeader.MessageType = CCID_RDR_to_PC_DataBlock; + ResponseBlock->CCIDHeader.Slot = CCIDHeader.Slot; + ResponseBlock->CCIDHeader.Seq = CCIDHeader.Seq; + + ResponseBlock->ChainParam = 0; + + Status = CCID_XfrBlock(CCIDHeader.Slot, RequestBuffer, CCIDHeader.Length, &ResponseBlock->Data, &ResponseDataLength, &Error); + + if (CCID_CheckStatusNoError(Status) && !Aborted) + { + ResponseBlock->CCIDHeader.Length = ResponseDataLength; + } + else if (Aborted) + { + Status = CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_PRESENTANDACTIVE; + Error = CCID_ERROR_CMD_ABORTED; + ResponseDataLength = 0; + } + else + { + ResponseDataLength = 0; + } + + ResponseBlock->Status = Status; + ResponseBlock->Error = Error; + + Endpoint_ClearOUT(); + + Endpoint_SelectEndpoint(CCID_IN_EPADDR); + Endpoint_Write_Stream_LE(ResponseBlock, sizeof(USB_CCID_RDR_to_PC_DataBlock_t) + ResponseDataLength, NULL); + Endpoint_ClearIN(); + break; + } + case CCID_PC_to_RDR_Abort: { - USB_CCID_RDR_to_PC_SlotStatus_t* ResponseAbort = (USB_CCID_RDR_to_PC_SlotStatus_t*)&BlockBuffer; + USB_CCID_RDR_to_PC_SlotStatus_t* ResponseAbort = (USB_CCID_RDR_to_PC_SlotStatus_t*)&ResponseBuffer; ResponseAbort->CCIDHeader.MessageType = CCID_RDR_to_PC_SlotStatus; ResponseAbort->CCIDHeader.Length = 0; ResponseAbort->CCIDHeader.Slot = CCIDHeader.Slot; @@ -418,10 +493,10 @@ void CCID_Task(void) } default: { - memset(BlockBuffer, 0x00, sizeof(BlockBuffer)); + memset(ResponseBuffer, 0x00, sizeof(ResponseBuffer)); Endpoint_SelectEndpoint(CCID_IN_EPADDR); - Endpoint_Write_Stream_LE(BlockBuffer, sizeof(BlockBuffer), NULL); + Endpoint_Write_Stream_LE(ResponseBuffer, sizeof(ResponseBuffer), NULL); Endpoint_ClearIN(); } } diff --git a/Demos/Device/LowLevel/CCID/Descriptors.c b/Demos/Device/LowLevel/CCID/Descriptors.c index c82216c9b..5e092e2e4 100644 --- a/Demos/Device/LowLevel/CCID/Descriptors.c +++ b/Demos/Device/LowLevel/CCID/Descriptors.c @@ -119,8 +119,8 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = .MaxIFSD = 2038, .SynchProtocols = 0, .Mechanical = 0, - .Features = 0x0400fe, - .MaxCCIDMessageLength = 0x0c00, + .Features = CCID_Features_ExchangeLevel_ShortAPDU | CCID_Features_Auto_ParameterConfiguration| CCID_Features_Auto_ICCActivation | CCID_Features_Auto_VoltageSelection, + .MaxCCIDMessageLength = CCID_EPSIZE, .ClassGetResponse = 0xff, .ClassEnvelope = 0xff, .LcdLayout = 0, diff --git a/Demos/Device/LowLevel/CCID/HostTestApp/test_generic_ccid_libusb.js b/Demos/Device/LowLevel/CCID/HostTestApp/test_generic_ccid_libusb.js index 993c0e550..e521cdb5a 100644 --- a/Demos/Device/LowLevel/CCID/HostTestApp/test_generic_ccid_libusb.js +++ b/Demos/Device/LowLevel/CCID/HostTestApp/test_generic_ccid_libusb.js @@ -106,17 +106,16 @@ function GetSlotStatusMessage(slot, seq) ]; } -function XfrBlockMessage(slot, seq) +function XfrBlockMessage(slot, seq, apdu) { return [ CCID_PC_to_RDR_XfrBlock, //message type - 5, 0, 0, 0, //length (05) + apdu.length, 0, 0, 0, //length: only for < 0xFF slot, seq, 0, //BWI - 0, 0, //level parameter - 0, 0xfd, 0, 0, 0 //message - ]; + 0, 0 //level parameter + ].concat(apdu); } @@ -140,6 +139,12 @@ function startTest() }, function(callback) { read(ccidInterface, 10, callback); + }, + function(callback) { + write(ccidInterface, new Buffer(XfrBlockMessage(0, 4, [0x0, 0xFD, 0x0, 0x0, 0x0])), callback); + }, + function(callback) { + read(ccidInterface, 10 + 2, callback); } ]); } diff --git a/LUFA/Drivers/USB/Class/Common/CCIDClassCommon.h b/LUFA/Drivers/USB/Class/Common/CCIDClassCommon.h index 6cedcad36..cf8fdbae0 100644 --- a/LUFA/Drivers/USB/Class/Common/CCIDClassCommon.h +++ b/LUFA/Drivers/USB/Class/Common/CCIDClassCommon.h @@ -153,6 +153,26 @@ CCID_DTYPE_Functional = 0x21, /**< CCID class specific Interface functional descriptor. */ }; + enum CCID_Features_Auto_t + { + CCID_Features_Auto_None = 0x0, + CCID_Features_Auto_ParameterConfiguration = 0x2, + CCID_Features_Auto_ICCActivation = 0x4, + CCID_Features_Auto_VoltageSelection = 0x8, + + CCID_Features_Auto_ICCClockFrequencyChange = 0x10, + CCID_Features_Auto_ICCBaudRateChange = 0x20, + CCID_Features_Auto_ParameterNegotiation = 0x40, + CCID_Features_Auto_PPS = 0x80, + }; + + enum CCID_Features_ExchangeLevel_t + { + CCID_Features_ExchangeLevel_TPDU = 0x00010000, + CCID_Features_ExchangeLevel_ShortAPDU = 0x00020000, + CCID_Features_ExchangeLevel_ShortExtendedAPDU = 0x00040000 + }; + /* Type Defines: */ typedef struct { diff --git a/LUFA/Drivers/USB/Class/Device/CCIDClassDevice.c b/LUFA/Drivers/USB/Class/Device/CCIDClassDevice.c index 0595e0715..450ed9d9c 100644 --- a/LUFA/Drivers/USB/Class/Device/CCIDClassDevice.c +++ b/LUFA/Drivers/USB/Class/Device/CCIDClassDevice.c @@ -129,7 +129,9 @@ void CCID_Device_USBTask(USB_ClassInfo_CCID_Device_t* const CCIDInterfaceInfo) { Endpoint_SelectEndpoint(CCIDInterfaceInfo->Config.DataOUTEndpoint.Address); - uint8_t BlockBuffer[0x20]; + uint8_t RequestBuffer[0x40 - sizeof(USB_CCID_BulkMessage_Header_t)]; + uint8_t ResponseBuffer[0x40]; + CCIDInterfaceInfo->State.Aborted = false; CCIDInterfaceInfo->State.AbortedSeq = -1; @@ -149,7 +151,7 @@ void CCID_Device_USBTask(USB_ClassInfo_CCID_Device_t* const CCIDInterfaceInfo) case CCID_PC_to_RDR_IccPowerOn: { uint8_t AtrLength; - USB_CCID_RDR_to_PC_DataBlock_t* ResponseATR = (USB_CCID_RDR_to_PC_DataBlock_t*)&BlockBuffer; + USB_CCID_RDR_to_PC_DataBlock_t* ResponseATR = (USB_CCID_RDR_to_PC_DataBlock_t*)&ResponseBuffer; ResponseATR->CCIDHeader.MessageType = CCID_RDR_to_PC_DataBlock; ResponseATR->CCIDHeader.Slot = CCIDHeader.Slot; @@ -186,7 +188,7 @@ void CCID_Device_USBTask(USB_ClassInfo_CCID_Device_t* const CCIDInterfaceInfo) case CCID_PC_to_RDR_IccPowerOff: { - USB_CCID_RDR_to_PC_SlotStatus_t* ResponsePowerOff = (USB_CCID_RDR_to_PC_SlotStatus_t*)&BlockBuffer; + USB_CCID_RDR_to_PC_SlotStatus_t* ResponsePowerOff = (USB_CCID_RDR_to_PC_SlotStatus_t*)&ResponseBuffer; ResponsePowerOff->CCIDHeader.MessageType = CCID_RDR_to_PC_SlotStatus; ResponsePowerOff->CCIDHeader.Length = 0; ResponsePowerOff->CCIDHeader.Slot = CCIDHeader.Slot; @@ -209,7 +211,7 @@ void CCID_Device_USBTask(USB_ClassInfo_CCID_Device_t* const CCIDInterfaceInfo) case CCID_PC_to_RDR_GetSlotStatus: { - USB_CCID_RDR_to_PC_SlotStatus_t* ResponseSlotStatus = (USB_CCID_RDR_to_PC_SlotStatus_t*)&BlockBuffer; + USB_CCID_RDR_to_PC_SlotStatus_t* ResponseSlotStatus = (USB_CCID_RDR_to_PC_SlotStatus_t*)&ResponseBuffer; ResponseSlotStatus->CCIDHeader.MessageType = CCID_RDR_to_PC_SlotStatus; ResponseSlotStatus->CCIDHeader.Length = 0; ResponseSlotStatus->CCIDHeader.Slot = CCIDHeader.Slot; @@ -230,9 +232,57 @@ void CCID_Device_USBTask(USB_ClassInfo_CCID_Device_t* const CCIDInterfaceInfo) break; } + case CCID_PC_to_RDR_XfrBlock: + { + uint8_t Bwi = Endpoint_Read_8(); + uint16_t LevelParameter = Endpoint_Read_16_LE(); + uint8_t ReceivedBuffer[0x4]; + + (void)Bwi; + (void)LevelParameter; + + Endpoint_Read_Stream_LE(ReceivedBuffer, sizeof(ReceivedBuffer), NULL); + + uint8_t ResponseDataLength = 0; + + USB_CCID_RDR_to_PC_DataBlock_t* ResponseBlock = (USB_CCID_RDR_to_PC_DataBlock_t*)&ResponseBuffer; + ResponseBlock->CCIDHeader.MessageType = CCID_RDR_to_PC_DataBlock; + ResponseBlock->CCIDHeader.Slot = CCIDHeader.Slot; + ResponseBlock->CCIDHeader.Seq = CCIDHeader.Seq; + + ResponseBlock->ChainParam = 0; + + Status = CALLBACK_CCID_XfrBlock(CCIDInterfaceInfo, CCIDHeader.Slot, RequestBuffer, CCIDHeader.Length, (uint8_t*) &ResponseBlock->Data, &ResponseDataLength, &Error); + + if (CCID_CheckStatusNoError(Status) && !CCIDInterfaceInfo->State.Aborted) + { + ResponseBlock->CCIDHeader.Length = ResponseDataLength; + } + else if(CCIDInterfaceInfo->State.Aborted) + { + Status = CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_PRESENTANDACTIVE; + Error = CCID_ERROR_CMD_ABORTED; + ResponseDataLength = 0; + } + else + { + ResponseDataLength = 0; + } + + ResponseBlock->Status = Status; + ResponseBlock->Error = Error; + + Endpoint_ClearOUT(); + + Endpoint_SelectEndpoint(CCIDInterfaceInfo->Config.DataINEndpoint.Address); + Endpoint_Write_Stream_LE(ResponseBlock, sizeof(USB_CCID_RDR_to_PC_DataBlock_t) + ResponseDataLength, NULL); + Endpoint_ClearIN(); + break; + } + case CCID_PC_to_RDR_Abort: { - USB_CCID_RDR_to_PC_SlotStatus_t* ResponseAbort = (USB_CCID_RDR_to_PC_SlotStatus_t*)&BlockBuffer; + USB_CCID_RDR_to_PC_SlotStatus_t* ResponseAbort = (USB_CCID_RDR_to_PC_SlotStatus_t*)&ResponseBuffer; ResponseAbort->CCIDHeader.MessageType = CCID_RDR_to_PC_SlotStatus; ResponseAbort->CCIDHeader.Length = 0; ResponseAbort->CCIDHeader.Slot = CCIDHeader.Slot; @@ -255,10 +305,10 @@ void CCID_Device_USBTask(USB_ClassInfo_CCID_Device_t* const CCIDInterfaceInfo) default: { - memset(BlockBuffer, 0x00, sizeof(BlockBuffer)); + memset(ResponseBuffer, 0x00, sizeof(ResponseBuffer)); Endpoint_SelectEndpoint(CCIDInterfaceInfo->Config.DataINEndpoint.Address); - Endpoint_Write_Stream_LE(BlockBuffer, sizeof(BlockBuffer), NULL); + Endpoint_Write_Stream_LE(ResponseBuffer, sizeof(ResponseBuffer), NULL); Endpoint_ClearIN(); } } diff --git a/LUFA/Drivers/USB/Class/Device/CCIDClassDevice.h b/LUFA/Drivers/USB/Class/Device/CCIDClassDevice.h index 245e12665..d101723c3 100644 --- a/LUFA/Drivers/USB/Class/Device/CCIDClassDevice.h +++ b/LUFA/Drivers/USB/Class/Device/CCIDClassDevice.h @@ -155,6 +155,28 @@ uint8_t slot, uint8_t* const error) ATTR_NON_NULL_PTR_ARG(1); + /** CCID class driver callback for PC_TO_RDR_XfrBlock CCID message + * Send a block of bytes from the host to a slot in the device + * and also received a block of bytes as a response + * + * \param[in,out] CCIDInterfaceInfo Pointer to a structure containing a CCID Class configuration and state. + * \param[in] slot The slot ID from which we want to retrieve the status. + * \param[in] receivedBuffer Pointer to an array holding the received block of bytes + * \param[in] receivedBufferSize The size of the received block of bytes + * \param[out] sendBuffer Pointer to a buffer which will hold the bytes being sent back to the host + * \param[out] sentBufferSize The size of the block of bytes being sent back to the host + * \param[out] error The result of the operation, or error. + * + * \return The command result code. + */ + uint8_t CALLBACK_CCID_XfrBlock(USB_ClassInfo_CCID_Device_t* const CCIDInterfaceInfo, + uint8_t slot, + uint8_t* const receivedBuffer, + uint8_t receivedBufferSize, + uint8_t* const sendBuffer, + uint8_t* const sentBufferSize, + uint8_t* const error); + /** CCID class driver callback for CCID_PC_to_RDR_Abort CCID message * Aborts a BULK out message previously sent to a slot * -- cgit v1.2.3