From a877ffb6265ea3a18f1c95f61fdddc8b57c518cc Mon Sep 17 00:00:00 2001
From: Filipe Rodrigues <filipepazrodrigues@gmail.com>
Date: Sun, 8 Jul 2018 20:18:27 -0700
Subject: [PATCH] CCID: Initial support for GetParameters and SetParameters

---
 Demos/Device/ClassDriver/CCID/CCID.c          |  54 +++++++-
 Demos/Device/LowLevel/CCID/CCID.c             | 129 +++++++++++++++++-
 .../HostTestApp/test_generic_ccid_libusb.js   |  54 +++++++-
 .../USB/Class/Common/CCIDClassCommon.h        |   3 +
 .../USB/Class/Device/CCIDClassDevice.c        |  69 ++++++++++
 .../USB/Class/Device/CCIDClassDevice.h        |  33 +++++
 6 files changed, 332 insertions(+), 10 deletions(-)

diff --git a/Demos/Device/ClassDriver/CCID/CCID.c b/Demos/Device/ClassDriver/CCID/CCID.c
index bb4c11c45..15d2852e4 100644
--- a/Demos/Device/ClassDriver/CCID/CCID.c
+++ b/Demos/Device/ClassDriver/CCID/CCID.c
@@ -193,7 +193,7 @@ uint8_t CALLBACK_CCID_IccPowerOff(USB_ClassInfo_CCID_Device_t* const CCIDInterfa
 	}
 }
 
-/** Event handler for the CCID_PC_to_RDR_GetSlotStatus. THis message is sent to the device
+/** Event handler for the CCID_PC_to_RDR_GetSlotStatus. This message is sent to the device
  *  whenever an application at the host wants to the get the current slot status
  *
  */
@@ -213,6 +213,58 @@ uint8_t CALLBACK_CCID_GetSlotStatus(USB_ClassInfo_CCID_Device_t* const CCIDInter
 	}
 }
 
+/** Event handler for the CCID_PC_to_RDR_SetParameters when T=0. This message is sent to
+ *  the device whenever an application at the host wants to set the
+ *  parameters for a given slot.
+ */
+uint8_t CALLBACK_CCID_SetParameters_T0(USB_ClassInfo_CCID_Device_t* const CCIDInterfaceInfo,
+									   uint8_t slot,
+									   uint8_t* const error,
+									   USB_CCID_ProtocolData_T0_t* const t0)
+{
+	if (slot == 0)
+	{
+		//set parameters
+		memcpy(&CCIDInterfaceInfo->ProtocolData, t0, sizeof(USB_CCID_ProtocolData_T0_t));
+		
+		*error = CCID_ERROR_NO_ERROR;
+		return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_PRESENTANDACTIVE;
+	}
+	else
+	{
+		*error = CCID_ERROR_SLOT_NOT_FOUND;
+		return CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_NOICCPRESENT;
+	}
+}
+
+/** Event handler for the CCID_PC_to_RDR_GetParameters when T=0. This message is sent to
+ *  the device whenever an application at the host wants to get the current
+ *  parameters for a given slot.
+ */
+uint8_t CALLBACK_CCID_GetParameters_T0(USB_ClassInfo_CCID_Device_t* const CCIDInterfaceInfo,
+									   uint8_t slot,
+									   uint8_t* const error,
+									   uint8_t* const ProtocolNum,
+									   USB_CCID_ProtocolData_T0_t* const t0)
+{
+	if (slot == 0)
+	{
+
+		*ProtocolNum = CCID_PROTOCOLNUM_T0;
+		memcpy(t0, &CCIDInterfaceInfo->ProtocolData, sizeof(USB_CCID_ProtocolData_T0_t));
+		
+		*ProtocolNum = CCID_PROTOCOLNUM_T0;
+
+		*error = CCID_ERROR_NO_ERROR;
+		return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_PRESENTANDACTIVE;
+	}
+	else
+	{
+		*error = CCID_ERROR_SLOT_NOT_FOUND;
+		return CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_NOICCPRESENT;
+	}
+}
+
 /** 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
diff --git a/Demos/Device/LowLevel/CCID/CCID.c b/Demos/Device/LowLevel/CCID/CCID.c
index 24849dc12..e55651373 100644
--- a/Demos/Device/LowLevel/CCID/CCID.c
+++ b/Demos/Device/LowLevel/CCID/CCID.c
@@ -52,6 +52,8 @@
 
 static bool    Aborted;
 static uint8_t AbortedSeq;
+static USB_CCID_ProtocolData_T0_t ProtocolData;
+
 
 
 /** Main program entry point. This routine configures the hardware required by the application, then
@@ -59,6 +61,12 @@ static uint8_t AbortedSeq;
  */
 int main(void)
 {
+	ProtocolData.FindexDindex = 0x11;
+	ProtocolData.TCCKST0 = 0x00;
+	ProtocolData.GuardTimeT0 = 0x00;
+	ProtocolData.WaitingIntegerT0 = 0x0A;
+	ProtocolData.ClockStop = 0x00;
+
 	SetupHardware();
 
 	LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
@@ -234,7 +242,7 @@ uint8_t CCID_IccPowerOff(uint8_t slot,
 }
 
 /** Event handler for the CCID_PC_to_RDR_GetSlotStatus. THis message is sent to
- *  the device whenever an application at the host wants to the get the current
+ *  the device whenever an application at the host wants to get the current
  *  slot status.
  */
 uint8_t CCID_GetSlotStatus(uint8_t slot,
@@ -251,6 +259,54 @@ uint8_t CCID_GetSlotStatus(uint8_t slot,
 		return CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_NOICCPRESENT;
 	}
 }
+/** Event handler for the CCID_PC_to_RDR_SetParameters when T=0. This message is sent to
+ *  the device whenever an application at the host wants to set the
+ *  parameters for a given slot.
+ */
+uint8_t CCID_SetParameters_T0(uint8_t slot,
+                           uint8_t* const error,
+                           USB_CCID_ProtocolData_T0_t* const t0)
+{
+	if (slot == 0)
+	{
+		//set parameters
+		memcpy(&ProtocolData, t0, sizeof(USB_CCID_ProtocolData_T0_t));
+		
+		*error = CCID_ERROR_NO_ERROR;
+		return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_PRESENTANDACTIVE;
+	}
+	else
+	{
+		*error = CCID_ERROR_SLOT_NOT_FOUND;
+		return CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_NOICCPRESENT;
+	}
+}
+/** Event handler for the CCID_PC_to_RDR_GetParameters when T=0. This message is sent to
+ *  the device whenever an application at the host wants to get the current
+ *  parameters for a given slot.
+ */
+uint8_t CCID_GetParameters_T0(uint8_t slot,
+                           uint8_t* const error,
+                           uint8_t* ProtocolNum,
+                           USB_CCID_ProtocolData_T0_t* const t0)
+{
+	if (slot == 0)
+	{
+
+		*ProtocolNum = CCID_PROTOCOLNUM_T0;
+		memcpy(t0, &ProtocolData, sizeof(USB_CCID_ProtocolData_T0_t));
+		
+		*ProtocolNum = CCID_PROTOCOLNUM_T0;
+
+		*error = CCID_ERROR_NO_ERROR;
+		return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_PRESENTANDACTIVE;
+	}
+	else
+	{
+		*error = CCID_ERROR_SLOT_NOT_FOUND;
+		return CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_NOICCPRESENT;
+	}
+}
 
 /** 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
@@ -421,7 +477,76 @@ void CCID_Task(void)
 				Endpoint_ClearIN();
 				break;
 			}
+			case CCID_PC_to_RDR_SetParameters:
+			{
+				uint8_t ProtocolNum = Endpoint_Read_8();
+				uint8_t RFU = Endpoint_Read_16_LE();
+
+				(void)RFU;
+
+				USB_CCID_RDR_to_PC_Parameters_t* ResponseParametersStatus = (USB_CCID_RDR_to_PC_Parameters_t*)&ResponseBuffer;
+				ResponseParametersStatus->CCIDHeader.MessageType = CCID_RDR_to_PC_Parameters;
+				ResponseParametersStatus->CCIDHeader.Length      = 0;
+				ResponseParametersStatus->CCIDHeader.Slot        = CCIDHeader.Slot;
+				ResponseParametersStatus->CCIDHeader.Seq         = CCIDHeader.Seq;
+
+				if(ProtocolNum == CCID_PROTOCOLNUM_T0)
+				{
+					if(CCIDHeader.Length * sizeof(uint8_t) == sizeof(USB_CCID_ProtocolData_T0_t))
+					{
+						
+						Endpoint_Read_Stream_LE(RequestBuffer, CCIDHeader.Length * sizeof(uint8_t), NULL);
+						Status = CCID_SetParameters_T0(CCIDHeader.Slot, &Error, (USB_CCID_ProtocolData_T0_t*) RequestBuffer);
+						if(CCID_CheckStatusNoError(Status))
+						{
+							ResponseParametersStatus->CCIDHeader.Length = CCIDHeader.Length;
+							Status = CCID_GetParameters_T0(CCIDHeader.Slot, &Error, &ResponseParametersStatus->ProtocolNum, (USB_CCID_ProtocolData_T0_t*) &ResponseParametersStatus->ProtocolData);
+						}
+					}
+					else
+					{
+						//unexpected length
+						Status = CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_PRESENTANDACTIVE;
+					}
+				}
+				else
+				{
+					ResponseParametersStatus->ProtocolNum = CCID_PROTOCOLNUM_T0;
+					//for now, we don't support T=1 protocol
+					Error = CCID_ERROR_PARAMETERS_PROTOCOL_NOT_SUPPORTED; 
+					Status = CCID_COMMANDSTATUS_ERROR | CCID_ICCSTATUS_PRESENTANDACTIVE;
+				}
+
+				ResponseParametersStatus->Status = Status;
+				ResponseParametersStatus->Error  = Error;
+
+				Endpoint_ClearOUT();
+
+				Endpoint_SelectEndpoint(CCID_IN_EPADDR);
+				Endpoint_Write_Stream_LE(ResponseParametersStatus, sizeof(USB_CCID_BulkMessage_Header_t) + 3 + ResponseParametersStatus->CCIDHeader.Length , NULL);
+				Endpoint_ClearIN();
+				break;
+			}
+			case CCID_PC_to_RDR_GetParameters:
+			{
+				USB_CCID_RDR_to_PC_Parameters_t* ResponseParametersStatus = (USB_CCID_RDR_to_PC_Parameters_t*)&ResponseBuffer;
+				ResponseParametersStatus->CCIDHeader.MessageType = CCID_RDR_to_PC_Parameters;
+				ResponseParametersStatus->CCIDHeader.Length      = sizeof(USB_CCID_ProtocolData_T0_t);
+				ResponseParametersStatus->CCIDHeader.Slot        = CCIDHeader.Slot;
+				ResponseParametersStatus->CCIDHeader.Seq         = CCIDHeader.Seq;
+
+				Status = CCID_GetParameters_T0(CCIDHeader.Slot, &Error, &ResponseParametersStatus->ProtocolNum, (USB_CCID_ProtocolData_T0_t*) &ResponseParametersStatus->ProtocolData);
 
+				ResponseParametersStatus->Status = Status;
+				ResponseParametersStatus->Error  = Error;
+
+				Endpoint_ClearOUT();
+
+				Endpoint_SelectEndpoint(CCID_IN_EPADDR);
+				Endpoint_Write_Stream_LE(ResponseParametersStatus, sizeof(USB_CCID_BulkMessage_Header_t) + 3 + ResponseParametersStatus->CCIDHeader.Length , NULL);
+				Endpoint_ClearIN();
+				break;
+			}
 			case CCID_PC_to_RDR_XfrBlock:
 			{
 				uint8_t  Bwi            = Endpoint_Read_8();
@@ -441,7 +566,7 @@ void CCID_Task(void)
 
 				ResponseBlock->ChainParam = 0;
 
-				Status = CCID_XfrBlock(CCIDHeader.Slot, RequestBuffer, CCIDHeader.Length, &ResponseBlock->Data, &ResponseDataLength, &Error);
+				Status = CCID_XfrBlock(CCIDHeader.Slot, RequestBuffer, CCIDHeader.Length, (uint8_t*) &ResponseBlock->Data, &ResponseDataLength, &Error);
 
 				if (CCID_CheckStatusNoError(Status) && !Aborted)
 				{
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 e521cdb5a..69cd1c28d 100644
--- a/Demos/Device/LowLevel/CCID/HostTestApp/test_generic_ccid_libusb.js
+++ b/Demos/Device/LowLevel/CCID/HostTestApp/test_generic_ccid_libusb.js
@@ -23,10 +23,12 @@ var sprintf = require('sprintf');
 var deviceVid = 0x03EB;
 var devicePid = 0x206E;
 
+var CCID_PC_to_RDR_SetParameters        = 0x61;
+var CCID_PC_to_RDR_GetParameters        = 0x6C;
 var CCID_PC_to_RDR_IccPowerOn           = 0x62;
 var CCID_PC_to_RDR_IccPowerOff          = 0x63;
 var CCID_PC_to_RDR_GetSlotStatus        = 0x65;
-var CCID_PC_to_RDR_XfrBlock         = 0x6f;
+var CCID_PC_to_RDR_XfrBlock             = 0x6f;
 
 function getAndInitCcidDeviceAndInterface()
 {
@@ -72,6 +74,30 @@ function write(ccidInterface, message, callback)
 
 //CCID functions
 
+function GetParametersMessage(slot, seq, protocolNum, t0Params)
+{
+    return [
+        CCID_PC_to_RDR_GetParameters, //message type
+        0, 0, 0, 0, //length
+        slot,
+        seq,
+        0, 0, 0 //RFU
+    ];
+}
+
+function SetParametersMessage(slot, seq, protocolNum, t0Params)
+{
+    return [
+        CCID_PC_to_RDR_SetParameters, //message type
+        t0Params.length, 0, 0, 0, //length
+        slot,
+        seq,
+        protocolNum,
+        0, 0 //RFU
+    ].concat(t0Params);
+}
+
+
 function IccPowerOnMessage(slot, seq)
 {
     return [
@@ -119,9 +145,9 @@ function XfrBlockMessage(slot, seq, apdu)
 
 }
 
-function startTest()
+function testCcidMessages()
 {
-    async.series([
+    return [
         function(callback) {
             write(ccidInterface, new Buffer(IccPowerOnMessage(0, 1)), callback);
         },
@@ -141,12 +167,26 @@ function startTest()
             read(ccidInterface, 10, callback);
         },
         function(callback) {
-            write(ccidInterface, new Buffer(XfrBlockMessage(0, 4, [0x0, 0xFD, 0x0, 0x0, 0x0])), callback);
+            write(ccidInterface, new Buffer(SetParametersMessage(0, 4, 0, [0x11, 0x00, 0x00, 0x0a, 0x00])), callback);
         },
         function(callback) {
-            read(ccidInterface, 10 + 2, callback);
-        }
-        ]);
+            //must return 82 05 00 00 00 00 04 00 80 00 11 00 00 0a 00
+            read(ccidInterface, 30, callback);
+        },
+        function(callback) {
+            write(ccidInterface, new Buffer(GetParametersMessage(0, 5, 0)), callback);
+        },
+        function(callback) {
+            //must return 82 05 00 00 00 00 04 00 80 00 11 00 00 0a 00
+            read(ccidInterface, 30, callback);
+        }];
+}
+
+function startTest()
+{
+    async.series([]
+        .concat(testCcidMessages())
+    );
 }
 
 var ccidDeviceAndInterface = getAndInitCcidDeviceAndInterface();
diff --git a/LUFA/Drivers/USB/Class/Common/CCIDClassCommon.h b/LUFA/Drivers/USB/Class/Common/CCIDClassCommon.h
index cf8fdbae0..da92381f6 100644
--- a/LUFA/Drivers/USB/Class/Common/CCIDClassCommon.h
+++ b/LUFA/Drivers/USB/Class/Common/CCIDClassCommon.h
@@ -81,6 +81,7 @@
 		#define CCID_ICCSTATUS_NOICCPRESENT                 (1 << 1)
 
 		#define CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR    0
+		#define CCID_COMMANDSTATUS_ERROR    				1
 		#define CCID_COMMANDSTATUS_FAILED                   (1 << 6)
 		#define CCID_COMMANDSTATUS_TIMEEXTENSIONREQUESTED   (2 << 6)
 		#define CCID_COMMANDSTATUS_RFU                      (3 << 6)
@@ -91,6 +92,8 @@
 		#define CCID_ERROR_CMD_ABORTED                      0xFF
 		#define CCID_ERROR_CMD_NOT_ABORTED                  0xFF
 
+		#define CCID_ERROR_PARAMETERS_PROTOCOL_NOT_SUPPORTED	0x7
+
 		#define CCID_ERROR_SLOT_NOT_FOUND                   5
 
 		#define CCID_DESCRIPTOR_CLOCK_KHZ(khz)              (khz)
diff --git a/LUFA/Drivers/USB/Class/Device/CCIDClassDevice.c b/LUFA/Drivers/USB/Class/Device/CCIDClassDevice.c
index 450ed9d9c..34f03c2c1 100644
--- a/LUFA/Drivers/USB/Class/Device/CCIDClassDevice.c
+++ b/LUFA/Drivers/USB/Class/Device/CCIDClassDevice.c
@@ -231,7 +231,76 @@ void CCID_Device_USBTask(USB_ClassInfo_CCID_Device_t* const CCIDInterfaceInfo)
 				Endpoint_ClearIN();
 				break;
 			}
+			case CCID_PC_to_RDR_SetParameters:
+			{
+				uint8_t ProtocolNum = Endpoint_Read_8();
+				uint8_t RFU = Endpoint_Read_16_LE();
+
+				(void)RFU;
+
+				USB_CCID_RDR_to_PC_Parameters_t* ResponseParametersStatus = (USB_CCID_RDR_to_PC_Parameters_t*)&ResponseBuffer;
+				ResponseParametersStatus->CCIDHeader.MessageType = CCID_RDR_to_PC_Parameters;
+				ResponseParametersStatus->CCIDHeader.Length      = 0;
+				ResponseParametersStatus->CCIDHeader.Slot        = CCIDHeader.Slot;
+				ResponseParametersStatus->CCIDHeader.Seq         = CCIDHeader.Seq;
+
+				if(ProtocolNum == CCID_PROTOCOLNUM_T0)
+				{
+					if(CCIDHeader.Length * sizeof(uint8_t) == sizeof(USB_CCID_ProtocolData_T0_t))
+					{
+						
+						Endpoint_Read_Stream_LE(RequestBuffer, CCIDHeader.Length * sizeof(uint8_t), NULL);
+						Status = CALLBACK_CCID_SetParameters_T0(CCIDInterfaceInfo, CCIDHeader.Slot, &Error, (USB_CCID_ProtocolData_T0_t*) RequestBuffer);
+						if(CCID_CheckStatusNoError(Status))
+						{
+							ResponseParametersStatus->CCIDHeader.Length = CCIDHeader.Length;
+							Status = CALLBACK_CCID_GetParameters_T0(CCIDInterfaceInfo, CCIDHeader.Slot, &Error, &ResponseParametersStatus->ProtocolNum, (USB_CCID_ProtocolData_T0_t*) &ResponseParametersStatus->ProtocolData);
+						}
+					}
+					else
+					{
+						//unexpected length
+						Status = CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_PRESENTANDACTIVE;
+					}
+				}
+				else
+				{
+					ResponseParametersStatus->ProtocolNum = CCID_PROTOCOLNUM_T0;
+					//for now, we don't support T=1 protocol
+					Error = CCID_ERROR_PARAMETERS_PROTOCOL_NOT_SUPPORTED; 
+					Status = CCID_COMMANDSTATUS_ERROR | CCID_ICCSTATUS_PRESENTANDACTIVE;
+				}
+
+				ResponseParametersStatus->Status = Status;
+				ResponseParametersStatus->Error  = Error;
+
+				Endpoint_ClearOUT();
+
+				Endpoint_SelectEndpoint(CCIDInterfaceInfo->Config.DataINEndpoint.Address);
+				Endpoint_Write_Stream_LE(ResponseParametersStatus, sizeof(USB_CCID_BulkMessage_Header_t) + 3 + ResponseParametersStatus->CCIDHeader.Length , NULL);
+				Endpoint_ClearIN();
+				break;
+			}
+			case CCID_PC_to_RDR_GetParameters:
+			{
+				USB_CCID_RDR_to_PC_Parameters_t* ResponseParametersStatus = (USB_CCID_RDR_to_PC_Parameters_t*)&ResponseBuffer;
+				ResponseParametersStatus->CCIDHeader.MessageType = CCID_RDR_to_PC_Parameters;
+				ResponseParametersStatus->CCIDHeader.Length      = sizeof(USB_CCID_ProtocolData_T0_t);
+				ResponseParametersStatus->CCIDHeader.Slot        = CCIDHeader.Slot;
+				ResponseParametersStatus->CCIDHeader.Seq         = CCIDHeader.Seq;
+
+				Status = CALLBACK_CCID_GetParameters_T0(CCIDInterfaceInfo, CCIDHeader.Slot, &Error, &ResponseParametersStatus->ProtocolNum, (USB_CCID_ProtocolData_T0_t*) &ResponseParametersStatus->ProtocolData);
+
+				ResponseParametersStatus->Status = Status;
+				ResponseParametersStatus->Error  = Error;
 
+				Endpoint_ClearOUT();
+
+				Endpoint_SelectEndpoint(CCIDInterfaceInfo->Config.DataINEndpoint.Address);
+				Endpoint_Write_Stream_LE(ResponseParametersStatus, sizeof(USB_CCID_BulkMessage_Header_t) + 3 + ResponseParametersStatus->CCIDHeader.Length , NULL);
+				Endpoint_ClearIN();
+				break;
+			}
 			case CCID_PC_to_RDR_XfrBlock:
 			{
 				uint8_t  Bwi            = Endpoint_Read_8();
diff --git a/LUFA/Drivers/USB/Class/Device/CCIDClassDevice.h b/LUFA/Drivers/USB/Class/Device/CCIDClassDevice.h
index d101723c3..e6b774fda 100644
--- a/LUFA/Drivers/USB/Class/Device/CCIDClassDevice.h
+++ b/LUFA/Drivers/USB/Class/Device/CCIDClassDevice.h
@@ -84,6 +84,7 @@
 				} State; /**< State data for the USB class interface within the device. All elements in this section
 				          *   are reset to their defaults when the interface is enumerated.
 				          */
+				USB_CCID_ProtocolData_T0_t ProtocolData;
 			} USB_ClassInfo_CCID_Device_t;
 
 	/* Function Prototypes: */
@@ -155,6 +156,38 @@
 			                                    uint8_t slot,
 			                                    uint8_t* const error) ATTR_NON_NULL_PTR_ARG(1);
 
+
+			/** CCID class driver callback for PC_TO_RDR_SetParameters CCID message for T=0
+			 *  Sets the current parameters of a given slot
+			 *
+			 *  \param[in,out] CCIDInterfaceInfo	Pointer to a structure containing a CCID Class configuration, state and protocol data.
+			 *  \param[in]     slot 				The slot ID from which we want to retrieve the status.
+			 *  \param[out]    error				The result of the operation, or error.
+			 *  \param[out]    t0 					Pointer to a buffer containing the new parameters
+			 *
+			 *  \return	The command result code.
+			 */
+			uint8_t CALLBACK_CCID_SetParameters_T0(USB_ClassInfo_CCID_Device_t* const CCIDInterfaceInfo,
+												   uint8_t slot,
+												   uint8_t* const error,
+												   USB_CCID_ProtocolData_T0_t* const t0);
+
+			/** CCID class driver callback for PC_TO_RDR_SetParameters CCID message for T=0
+			 *  Retrieves the current parameters of a given slot
+			 *
+			 *  \param[in,out] CCIDInterfaceInfo	Pointer to a structure containing a CCID Class configuration, state and protocol data.
+			 *  \param[in]     slot 				The slot ID from which we want to retrieve the status.
+			 *  \param[out]    error				The result of the operation, or error.
+			 *  \param[out]    t0 					Pointer to a buffer where the parameters will be returned
+			 *
+			 *  \return	The command result code.
+			 */
+			uint8_t CALLBACK_CCID_GetParameters_T0(USB_ClassInfo_CCID_Device_t* const CCIDInterfaceInfo,
+												   uint8_t slot,
+												   uint8_t* const error,
+												   uint8_t* const ProtocolNum,
+												   USB_CCID_ProtocolData_T0_t* const t0);
+
 			/** 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
-- 
GitLab