3 Copyright (C) Dean Camera, 2018.
5 dean [at] fourwalledcubicle [dot] com
10 Copyright 2018 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11 Copyright 2018 Filipe Rodrigues (filipepazrodrigues [at] gmail [dot] com)
13 Permission to use, copy, modify, distribute, and sell this
14 software and its documentation for any purpose is hereby granted
15 without fee, provided that the above copyright notice appear in
16 all copies and that both that the copyright notice and this
17 permission notice and warranty disclaimer appear in supporting
18 documentation, and that the name of the author not be used in
19 advertising or publicity pertaining to distribution of the
20 software without specific, written prior permission.
22 The author disclaims all warranties with regard to this
23 software, including all implied warranties of merchantability
24 and fitness. In no event shall the author be liable for any
25 special, indirect or consequential damages or any damages
26 whatsoever resulting from loss of use, data or profits, whether
27 in an action of contract, negligence or other tortious action,
28 arising out of or in connection with the use or performance of
34 * Main source file for the CCID demo. This file contains the main tasks of the demo and
35 * is responsible for the initial application hardware configuration.
38 * LUFA is not a secure USB stack, and has not undergone, not is it expected to pass, any
39 * form of security audit. The CCID class here is presented as-is and is intended for
40 * research purposes only, and *should not* be used in a security critical application
41 * under any circumstances.
44 * This code is not production ready and should not by any means be considered safe.
45 * If you plan to integrate it into your application, you should seriously consider strong
46 * encryption algorithms or a secure microprocessor. Since Atmel AVR microprocessors do not
47 * have any security requirement (therefore they don't offer any known protection against
48 * side channel attacks or fault injection) a secure microprocessor is the best option.
54 static uint8_t AbortedSeq
;
55 static USB_CCID_ProtocolData_T0_t ProtocolData
;
59 /** Main program entry point. This routine configures the hardware required by the application, then
60 * enters a loop to run the application tasks in sequence.
64 ProtocolData
.FindexDindex
= 0x11;
65 ProtocolData
.TCCKST0
= 0x00;
66 ProtocolData
.GuardTimeT0
= 0x00;
67 ProtocolData
.WaitingIntegerT0
= 0x0A;
68 ProtocolData
.ClockStop
= 0x00;
72 LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY
);
73 GlobalInterruptEnable();
82 /** Configures the board hardware and chip peripherals for the demo's functionality. */
83 void SetupHardware(void)
85 #if (ARCH == ARCH_AVR8)
86 /* Disable watchdog if enabled by bootloader/fuses */
87 MCUSR
&= ~(1 << WDRF
);
90 /* Disable clock division */
91 clock_prescale_set(clock_div_1
);
92 #elif (ARCH == ARCH_XMEGA)
93 /* Start the PLL to multiply the 2MHz RC oscillator to 32MHz and switch the CPU core to run from it */
94 XMEGACLK_StartPLL(CLOCK_SRC_INT_RC2MHZ
, 2000000, F_CPU
);
95 XMEGACLK_SetCPUClockSource(CLOCK_SRC_PLL
);
97 /* Start the 32MHz internal RC oscillator and start the DFLL to increase it to 48MHz using the USB SOF as a reference */
98 XMEGACLK_StartInternalOscillator(CLOCK_SRC_INT_RC32MHZ
);
99 XMEGACLK_StartDFLL(CLOCK_SRC_INT_RC32MHZ
, DFLL_REF_INT_USBSOF
, F_USB
);
101 PMIC
.CTRL
= PMIC_LOLVLEN_bm
| PMIC_MEDLVLEN_bm
| PMIC_HILVLEN_bm
;
104 /* Hardware Initialization */
109 /** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs. */
110 void EVENT_USB_Device_Connect(void)
112 /* Indicate USB enumerating */
113 LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING
);
116 /** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
119 void EVENT_USB_Device_Disconnect(void)
121 /* Indicate USB not ready */
122 LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY
);
125 /** Event handler for the USB_ConfigurationChanged event. This is fired when the host set the current configuration
126 * of the USB device after enumeration - the device endpoints are configured.
128 void EVENT_USB_Device_ConfigurationChanged(void)
130 bool ConfigSuccess
= true;
132 /* Setup CCID Data Endpoints */
133 ConfigSuccess
&= Endpoint_ConfigureEndpoint(CCID_IN_EPADDR
, EP_TYPE_BULK
, CCID_EPSIZE
, 1);
134 ConfigSuccess
&= Endpoint_ConfigureEndpoint(CCID_OUT_EPADDR
, EP_TYPE_BULK
, CCID_EPSIZE
, 1);
136 /* Indicate endpoint configuration success or failure */
137 LEDs_SetAllLEDs(ConfigSuccess ? LEDMASK_USB_READY
: LEDMASK_USB_ERROR
);
140 /** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent to
141 * the device from the USB host before passing along unhandled control requests to the library for processing
144 void EVENT_USB_Device_ControlRequest(void)
146 switch (USB_ControlRequest
.bRequest
)
150 // Initiates the abort process
151 // The host should send 2 messages in the following order:
152 // - CCID_ABORT control request
153 // - CCID_PC_t_PCo_RDR_Abort command
155 // If the device is still processing a message, it should fail it until receiving a CCIRPC_to_RDR_Abort
158 // When the device receives the CCIRPC_to_RDR_Abort message, it replies with RDR_to_PC_SlotStatus
159 // and the abort process ends
161 // The wValue field contains the slot number (bSlot) in the low byte and the sequence number (bSeq) in
163 uint8_t Slot
= USB_ControlRequest
.wValue
& 0xFF;
164 uint8_t Seq
= USB_ControlRequest
.wValue
>> 8;
166 if (USB_ControlRequest
.bmRequestType
== (REQDIR_DEVICETOHOST
| REQTYPE_CLASS
| REQREC_INTERFACE
) && Slot
== 0)
168 Endpoint_ClearSETUP();
178 case CCID_GET_CLOCK_FREQUENCIES
:
180 if (USB_ControlRequest
.bmRequestType
== (REQDIR_DEVICETOHOST
| REQTYPE_CLASS
| REQREC_INTERFACE
))
182 Endpoint_ClearSETUP();
183 Endpoint_Write_8(0); // Not supported
189 case CCID_GET_DATA_RATES
:
191 if (USB_ControlRequest
.bmRequestType
== (REQDIR_DEVICETOHOST
| REQTYPE_CLASS
| REQREC_INTERFACE
))
193 Endpoint_ClearSETUP();
194 Endpoint_Write_8(0); // Not supported
203 /** Event handler for the CCID_PC_to_RDR_IccPowerOn message. This message is sent to the device
204 * whenever an application at the host wants to send a power off signal to a slot.
205 * THe slot must reply back with a recognizable ATR (answer to reset)
207 uint8_t CCID_IccPowerOn(uint8_t slot
,
209 uint8_t* const atrLength
,
210 uint8_t* const error
)
214 Iso7816_CreateSimpleAtr(atr
, atrLength
);
216 *error
= CCID_ERROR_NO_ERROR
;
217 return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR
| CCID_ICCSTATUS_PRESENTANDACTIVE
;
221 *error
= CCID_ERROR_SLOT_NOT_FOUND
;
222 return CCID_COMMANDSTATUS_FAILED
| CCID_ICCSTATUS_NOICCPRESENT
;
226 /** Event handler for the CCID_PC_to_RDR_IccPowerOff message. This message is sent to the device
227 * whenever an application at the host wants to send a power off signal to a slot.
229 uint8_t CCID_IccPowerOff(uint8_t slot
,
230 uint8_t* const error
)
234 *error
= CCID_ERROR_NO_ERROR
;
235 return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR
| CCID_ICCSTATUS_NOICCPRESENT
;
239 *error
= CCID_ERROR_SLOT_NOT_FOUND
;
240 return CCID_COMMANDSTATUS_FAILED
| CCID_ICCSTATUS_NOICCPRESENT
;
244 /** Event handler for the CCID_PC_to_RDR_GetSlotStatus. THis message is sent to
245 * the device whenever an application at the host wants to get the current
248 uint8_t CCID_GetSlotStatus(uint8_t slot
,
249 uint8_t* const error
)
253 *error
= CCID_ERROR_NO_ERROR
;
254 return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR
| CCID_ICCSTATUS_PRESENTANDACTIVE
;
258 *error
= CCID_ERROR_SLOT_NOT_FOUND
;
259 return CCID_COMMANDSTATUS_FAILED
| CCID_ICCSTATUS_NOICCPRESENT
;
262 /** Event handler for the CCID_PC_to_RDR_SetParameters when T=0. This message is sent to
263 * the device whenever an application at the host wants to set the
264 * parameters for a given slot.
266 uint8_t CCID_SetParameters_T0(uint8_t slot
,
267 uint8_t* const error
,
268 USB_CCID_ProtocolData_T0_t
* const t0
)
273 memcpy(&ProtocolData
, t0
, sizeof(USB_CCID_ProtocolData_T0_t
));
275 *error
= CCID_ERROR_NO_ERROR
;
276 return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR
| CCID_ICCSTATUS_PRESENTANDACTIVE
;
280 *error
= CCID_ERROR_SLOT_NOT_FOUND
;
281 return CCID_COMMANDSTATUS_FAILED
| CCID_ICCSTATUS_NOICCPRESENT
;
284 /** Event handler for the CCID_PC_to_RDR_GetParameters when T=0. This message is sent to
285 * the device whenever an application at the host wants to get the current
286 * parameters for a given slot.
288 uint8_t CCID_GetParameters_T0(uint8_t slot
,
289 uint8_t* const error
,
290 uint8_t* ProtocolNum
,
291 USB_CCID_ProtocolData_T0_t
* const t0
)
296 *ProtocolNum
= CCID_PROTOCOLNUM_T0
;
297 memcpy(t0
, &ProtocolData
, sizeof(USB_CCID_ProtocolData_T0_t
));
299 *ProtocolNum
= CCID_PROTOCOLNUM_T0
;
301 *error
= CCID_ERROR_NO_ERROR
;
302 return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR
| CCID_ICCSTATUS_PRESENTANDACTIVE
;
306 *error
= CCID_ERROR_SLOT_NOT_FOUND
;
307 return CCID_COMMANDSTATUS_FAILED
| CCID_ICCSTATUS_NOICCPRESENT
;
311 /** Event handler for the CCID_PC_to_RDR_XfrBlock. This message is sent to the device
312 * whenever an application at the host wants to send a block of bytes to the device
313 * THe device reply back with an array of bytes
315 uint8_t CCID_XfrBlock(uint8_t slot
,
316 uint8_t* const receivedBuffer
,
317 uint8_t receivedBufferSize
,
318 uint8_t* const sendBuffer
,
319 uint8_t* const sentBufferSize
,
320 uint8_t* const error
)
324 uint8_t okResponse
[2] = {0x90, 0x00};
325 memcpy(sendBuffer
, okResponse
, sizeof(okResponse
));
326 *sentBufferSize
= sizeof(okResponse
);
328 *error
= CCID_ERROR_NO_ERROR
;
329 return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR
| CCID_ICCSTATUS_NOICCPRESENT
;
333 *error
= CCID_ERROR_SLOT_NOT_FOUND
;
334 return CCID_COMMANDSTATUS_FAILED
| CCID_ICCSTATUS_NOICCPRESENT
;
338 /** Event handler for the CCID_PC_to_RDR_ABort message. This message is sent to the device
339 * whenever an application wants to abort the current operation. A previous CCID_ABORT
340 * control message has to be sent before this one in order to start the abort operation.
342 uint8_t CCID_Abort(uint8_t slot
,
344 uint8_t* const error
)
346 if (Aborted
&& slot
== 0 && AbortedSeq
== seq
)
350 *error
= CCID_ERROR_NO_ERROR
;
351 return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR
| CCID_ICCSTATUS_PRESENTANDACTIVE
;
355 *error
= CCID_ERROR_CMD_NOT_ABORTED
;
356 return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR
| CCID_ICCSTATUS_PRESENTANDACTIVE
;
360 *error
= CCID_ERROR_SLOT_NOT_FOUND
;
361 return CCID_COMMANDSTATUS_FAILED
| CCID_ICCSTATUS_NOICCPRESENT
;
364 *error
= CCID_ERROR_NOT_SUPPORTED
;
365 return CCID_COMMANDSTATUS_FAILED
| CCID_ICCSTATUS_NOICCPRESENT
;
368 /** Gets and status and verifies whether an error occurred. */
369 bool CCID_CheckStatusNoError(uint8_t status
)
371 return (status
& 0xC0) == 0x0;
374 /** Function to manage CCID request parsing and responses back to the host. */
377 Endpoint_SelectEndpoint(CCID_OUT_EPADDR
);
379 uint8_t RequestBuffer
[CCID_EPSIZE
- sizeof(USB_CCID_BulkMessage_Header_t
)];
380 uint8_t ResponseBuffer
[CCID_EPSIZE
];
384 if (Endpoint_IsOUTReceived())
386 USB_CCID_BulkMessage_Header_t CCIDHeader
;
387 CCIDHeader
.MessageType
= Endpoint_Read_8();
388 CCIDHeader
.Length
= Endpoint_Read_32_LE();
389 CCIDHeader
.Slot
= Endpoint_Read_8();
390 CCIDHeader
.Seq
= Endpoint_Read_8();
393 uint8_t Error
= CCID_ERROR_NO_ERROR
;
395 switch (CCIDHeader
.MessageType
)
397 case CCID_PC_to_RDR_IccPowerOn
:
400 USB_CCID_RDR_to_PC_DataBlock_t
* ResponseATR
= (USB_CCID_RDR_to_PC_DataBlock_t
*)&ResponseBuffer
;
402 ResponseATR
->CCIDHeader
.MessageType
= CCID_RDR_to_PC_DataBlock
;
403 ResponseATR
->CCIDHeader
.Slot
= CCIDHeader
.Slot
;
404 ResponseATR
->CCIDHeader
.Seq
= CCIDHeader
.Seq
;
405 ResponseATR
->ChainParam
= 0;
407 Status
= CCID_IccPowerOn(ResponseATR
->CCIDHeader
.Slot
, (uint8_t* )ResponseATR
->Data
, &AtrLength
, &Error
);
409 if (CCID_CheckStatusNoError(Status
) && !Aborted
)
411 ResponseATR
->CCIDHeader
.Length
= AtrLength
;
415 Status
= CCID_COMMANDSTATUS_FAILED
| CCID_ICCSTATUS_PRESENTANDACTIVE
;
416 Error
= CCID_ERROR_CMD_ABORTED
;
424 ResponseATR
->Status
= Status
;
425 ResponseATR
->Error
= Error
;
429 Endpoint_SelectEndpoint(CCID_IN_EPADDR
);
430 Endpoint_Write_Stream_LE(ResponseATR
, sizeof(USB_CCID_RDR_to_PC_DataBlock_t
) + AtrLength
, NULL
);
435 case CCID_PC_to_RDR_IccPowerOff
:
437 USB_CCID_RDR_to_PC_SlotStatus_t
* ResponsePowerOff
= (USB_CCID_RDR_to_PC_SlotStatus_t
*)&ResponseBuffer
;
438 ResponsePowerOff
->CCIDHeader
.MessageType
= CCID_RDR_to_PC_SlotStatus
;
439 ResponsePowerOff
->CCIDHeader
.Length
= 0;
440 ResponsePowerOff
->CCIDHeader
.Slot
= CCIDHeader
.Slot
;
441 ResponsePowerOff
->CCIDHeader
.Seq
= CCIDHeader
.Seq
;
443 ResponsePowerOff
->ClockStatus
= 0;
445 Status
= CCID_IccPowerOff(CCIDHeader
.Slot
, &Error
);
447 ResponsePowerOff
->Status
= Status
;
448 ResponsePowerOff
->Error
= Error
;
452 Endpoint_SelectEndpoint(CCID_IN_EPADDR
);
453 Endpoint_Write_Stream_LE(ResponsePowerOff
, sizeof(USB_CCID_RDR_to_PC_SlotStatus_t
), NULL
);
458 case CCID_PC_to_RDR_GetSlotStatus
:
460 USB_CCID_RDR_to_PC_SlotStatus_t
* ResponseSlotStatus
= (USB_CCID_RDR_to_PC_SlotStatus_t
*)&ResponseBuffer
;
461 ResponseSlotStatus
->CCIDHeader
.MessageType
= CCID_RDR_to_PC_SlotStatus
;
462 ResponseSlotStatus
->CCIDHeader
.Length
= 0;
463 ResponseSlotStatus
->CCIDHeader
.Slot
= CCIDHeader
.Slot
;
464 ResponseSlotStatus
->CCIDHeader
.Seq
= CCIDHeader
.Seq
;
466 ResponseSlotStatus
->ClockStatus
= 0;
468 Status
= CCID_GetSlotStatus(CCIDHeader
.Slot
, &Error
);
470 ResponseSlotStatus
->Status
= Status
;
471 ResponseSlotStatus
->Error
= Error
;
475 Endpoint_SelectEndpoint(CCID_IN_EPADDR
);
476 Endpoint_Write_Stream_LE(ResponseSlotStatus
, sizeof(USB_CCID_RDR_to_PC_SlotStatus_t
), NULL
);
480 case CCID_PC_to_RDR_SetParameters
:
482 uint8_t ProtocolNum
= Endpoint_Read_8();
483 uint8_t RFU
= Endpoint_Read_16_LE();
487 USB_CCID_RDR_to_PC_Parameters_t
* ResponseParametersStatus
= (USB_CCID_RDR_to_PC_Parameters_t
*)&ResponseBuffer
;
488 ResponseParametersStatus
->CCIDHeader
.MessageType
= CCID_RDR_to_PC_Parameters
;
489 ResponseParametersStatus
->CCIDHeader
.Length
= 0;
490 ResponseParametersStatus
->CCIDHeader
.Slot
= CCIDHeader
.Slot
;
491 ResponseParametersStatus
->CCIDHeader
.Seq
= CCIDHeader
.Seq
;
493 if(ProtocolNum
== CCID_PROTOCOLNUM_T0
)
495 if(CCIDHeader
.Length
* sizeof(uint8_t) == sizeof(USB_CCID_ProtocolData_T0_t
))
498 Endpoint_Read_Stream_LE(RequestBuffer
, CCIDHeader
.Length
* sizeof(uint8_t), NULL
);
499 Status
= CCID_SetParameters_T0(CCIDHeader
.Slot
, &Error
, (USB_CCID_ProtocolData_T0_t
*) RequestBuffer
);
500 if(CCID_CheckStatusNoError(Status
))
502 ResponseParametersStatus
->CCIDHeader
.Length
= CCIDHeader
.Length
;
503 Status
= CCID_GetParameters_T0(CCIDHeader
.Slot
, &Error
, &ResponseParametersStatus
->ProtocolNum
, (USB_CCID_ProtocolData_T0_t
*) &ResponseParametersStatus
->ProtocolData
);
509 Status
= CCID_COMMANDSTATUS_FAILED
| CCID_ICCSTATUS_PRESENTANDACTIVE
;
514 ResponseParametersStatus
->ProtocolNum
= CCID_PROTOCOLNUM_T0
;
515 //for now, we don't support T=1 protocol
516 Error
= CCID_ERROR_PARAMETERS_PROTOCOL_NOT_SUPPORTED
;
517 Status
= CCID_COMMANDSTATUS_ERROR
| CCID_ICCSTATUS_PRESENTANDACTIVE
;
520 ResponseParametersStatus
->Status
= Status
;
521 ResponseParametersStatus
->Error
= Error
;
525 Endpoint_SelectEndpoint(CCID_IN_EPADDR
);
526 Endpoint_Write_Stream_LE(ResponseParametersStatus
, sizeof(USB_CCID_BulkMessage_Header_t
) + 3 + ResponseParametersStatus
->CCIDHeader
.Length
, NULL
);
530 case CCID_PC_to_RDR_GetParameters
:
532 USB_CCID_RDR_to_PC_Parameters_t
* ResponseParametersStatus
= (USB_CCID_RDR_to_PC_Parameters_t
*)&ResponseBuffer
;
533 ResponseParametersStatus
->CCIDHeader
.MessageType
= CCID_RDR_to_PC_Parameters
;
534 ResponseParametersStatus
->CCIDHeader
.Length
= sizeof(USB_CCID_ProtocolData_T0_t
);
535 ResponseParametersStatus
->CCIDHeader
.Slot
= CCIDHeader
.Slot
;
536 ResponseParametersStatus
->CCIDHeader
.Seq
= CCIDHeader
.Seq
;
538 Status
= CCID_GetParameters_T0(CCIDHeader
.Slot
, &Error
, &ResponseParametersStatus
->ProtocolNum
, (USB_CCID_ProtocolData_T0_t
*) &ResponseParametersStatus
->ProtocolData
);
540 ResponseParametersStatus
->Status
= Status
;
541 ResponseParametersStatus
->Error
= Error
;
545 Endpoint_SelectEndpoint(CCID_IN_EPADDR
);
546 Endpoint_Write_Stream_LE(ResponseParametersStatus
, sizeof(USB_CCID_BulkMessage_Header_t
) + 3 + ResponseParametersStatus
->CCIDHeader
.Length
, NULL
);
550 case CCID_PC_to_RDR_XfrBlock
:
552 uint8_t Bwi
= Endpoint_Read_8();
553 uint16_t LevelParameter
= Endpoint_Read_16_LE();
556 (void)LevelParameter
;
558 Endpoint_Read_Stream_LE(RequestBuffer
, CCIDHeader
.Length
* sizeof(uint8_t), NULL
);
560 uint8_t ResponseDataLength
= 0;
562 USB_CCID_RDR_to_PC_DataBlock_t
* ResponseBlock
= (USB_CCID_RDR_to_PC_DataBlock_t
*)&ResponseBuffer
;
563 ResponseBlock
->CCIDHeader
.MessageType
= CCID_RDR_to_PC_DataBlock
;
564 ResponseBlock
->CCIDHeader
.Slot
= CCIDHeader
.Slot
;
565 ResponseBlock
->CCIDHeader
.Seq
= CCIDHeader
.Seq
;
567 ResponseBlock
->ChainParam
= 0;
569 Status
= CCID_XfrBlock(CCIDHeader
.Slot
, RequestBuffer
, CCIDHeader
.Length
, (uint8_t*) &ResponseBlock
->Data
, &ResponseDataLength
, &Error
);
571 if (CCID_CheckStatusNoError(Status
) && !Aborted
)
573 ResponseBlock
->CCIDHeader
.Length
= ResponseDataLength
;
577 Status
= CCID_COMMANDSTATUS_FAILED
| CCID_ICCSTATUS_PRESENTANDACTIVE
;
578 Error
= CCID_ERROR_CMD_ABORTED
;
579 ResponseDataLength
= 0;
583 ResponseDataLength
= 0;
586 ResponseBlock
->Status
= Status
;
587 ResponseBlock
->Error
= Error
;
591 Endpoint_SelectEndpoint(CCID_IN_EPADDR
);
592 Endpoint_Write_Stream_LE(ResponseBlock
, sizeof(USB_CCID_RDR_to_PC_DataBlock_t
) + ResponseDataLength
, NULL
);
597 case CCID_PC_to_RDR_Abort
:
599 USB_CCID_RDR_to_PC_SlotStatus_t
* ResponseAbort
= (USB_CCID_RDR_to_PC_SlotStatus_t
*)&ResponseBuffer
;
600 ResponseAbort
->CCIDHeader
.MessageType
= CCID_RDR_to_PC_SlotStatus
;
601 ResponseAbort
->CCIDHeader
.Length
= 0;
602 ResponseAbort
->CCIDHeader
.Slot
= CCIDHeader
.Slot
;
603 ResponseAbort
->CCIDHeader
.Seq
= CCIDHeader
.Seq
;
605 ResponseAbort
->ClockStatus
= 0;
607 Status
= CCID_Abort(CCIDHeader
.Slot
, CCIDHeader
.Seq
, &Error
);
609 ResponseAbort
->Status
= Status
;
610 ResponseAbort
->Error
= Error
;
614 Endpoint_SelectEndpoint(CCID_IN_EPADDR
);
615 Endpoint_Write_Stream_LE(ResponseAbort
, sizeof(USB_CCID_RDR_to_PC_SlotStatus_t
), NULL
);
621 memset(ResponseBuffer
, 0x00, sizeof(ResponseBuffer
));
623 Endpoint_SelectEndpoint(CCID_IN_EPADDR
);
624 Endpoint_Write_Stream_LE(ResponseBuffer
, sizeof(ResponseBuffer
), NULL
);