Build: Fix incorrect build target for Ubuntu CI builds.
[pub/USBasp.git] / Demos / Device / LowLevel / CCID / CCID.c
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2019.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.lufa-lib.org
7 */
8
9 /*
10 Copyright 2019 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11 Copyright 2019 Filipe Rodrigues (filipepazrodrigues [at] gmail [dot] com)
12
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.
21
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
29 this software.
30 */
31
32 /** \file
33 *
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.
36 *
37 * \warning
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.
42 *
43 * \warning
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.
49 */
50
51 #include "CCID.h"
52
53 static bool Aborted;
54 static uint8_t AbortedSeq;
55
56 static USB_CCID_ProtocolData_T0_t ProtocolData =
57 {
58 .FindexDindex = 0x11,
59 .TCCKST0 = 0x00,
60 .GuardTimeT0 = 0x00,
61 .WaitingIntegerT0 = 0x0A,
62 .ClockStop = 0x00,
63 };
64
65 /** Main program entry point. This routine configures the hardware required by the application, then
66 * enters a loop to run the application tasks in sequence.
67 */
68 int main(void)
69 {
70 SetupHardware();
71
72 LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
73 GlobalInterruptEnable();
74
75 for (;;)
76 {
77 USB_USBTask();
78 CCID_Task();
79 }
80 }
81
82 /** Configures the board hardware and chip peripherals for the demo's functionality. */
83 void SetupHardware(void)
84 {
85 #if (ARCH == ARCH_AVR8)
86 /* Disable watchdog if enabled by bootloader/fuses */
87 MCUSR &= ~(1 << WDRF);
88 wdt_disable();
89
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);
96
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);
100
101 PMIC.CTRL = PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm;
102 #endif
103
104 /* Hardware Initialization */
105 LEDs_Init();
106 USB_Init();
107 }
108
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)
111 {
112 /* Indicate USB enumerating */
113 LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
114 }
115
116 /** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
117 * the status LEDs.
118 */
119 void EVENT_USB_Device_Disconnect(void)
120 {
121 /* Indicate USB not ready */
122 LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
123 }
124
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.
127 */
128 void EVENT_USB_Device_ConfigurationChanged(void)
129 {
130 bool ConfigSuccess = true;
131
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);
135
136 /* Indicate endpoint configuration success or failure */
137 LEDs_SetAllLEDs(ConfigSuccess ? LEDMASK_USB_READY : LEDMASK_USB_ERROR);
138 }
139
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
142 * internally.
143 */
144 void EVENT_USB_Device_ControlRequest(void)
145 {
146 switch (USB_ControlRequest.bRequest)
147 {
148 case CCID_ABORT:
149 {
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
154 //
155 // If the device is still processing a message, it should fail it until receiving a CCIRPC_to_RDR_Abort
156 // command.
157 //
158 // When the device receives the CCIRPC_to_RDR_Abort message, it replies with RDR_to_PC_SlotStatus
159 // and the abort process ends
160
161 // The wValue field contains the slot number (bSlot) in the low byte and the sequence number (bSeq) in
162 // the high byte
163 uint8_t Slot = USB_ControlRequest.wValue & 0xFF;
164 uint8_t Seq = USB_ControlRequest.wValue >> 8;
165
166 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE) && Slot == 0)
167 {
168 Endpoint_ClearSETUP();
169
170 Aborted = true;
171 AbortedSeq = Seq;
172
173 Endpoint_ClearOUT();
174 }
175
176 break;
177 }
178
179 case CCID_GET_CLOCK_FREQUENCIES:
180 {
181 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
182 {
183 Endpoint_ClearSETUP();
184 Endpoint_Write_8(0); // Not supported
185 Endpoint_ClearOUT();
186 }
187
188 break;
189 }
190
191 case CCID_GET_DATA_RATES:
192 {
193 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
194 {
195 Endpoint_ClearSETUP();
196 Endpoint_Write_8(0); // Not supported
197 Endpoint_ClearOUT();
198 }
199
200 break;
201 }
202 }
203 }
204
205 /** Event handler for the CCID_PC_to_RDR_IccPowerOn message. This message is sent to the device
206 * whenever an application at the host wants to send a power off signal to a slot.
207 * THe slot must reply back with a recognizable ATR (answer to reset)
208 */
209 uint8_t CCID_IccPowerOn(uint8_t Slot,
210 uint8_t* const Atr,
211 uint8_t* const AtrLength,
212 uint8_t* const Error)
213 {
214 if (Slot == 0)
215 {
216 Iso7816_CreateSimpleAtr(Atr, AtrLength);
217
218 *Error = CCID_ERROR_NO_ERROR;
219 return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_PRESENTANDACTIVE;
220 }
221 else
222 {
223 *Error = CCID_ERROR_SLOT_NOT_FOUND;
224 return CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_NOICCPRESENT;
225 }
226 }
227
228 /** Event handler for the CCID_PC_to_RDR_IccPowerOff message. This message is sent to the device
229 * whenever an application at the host wants to send a power off signal to a slot.
230 */
231 uint8_t CCID_IccPowerOff(uint8_t Slot,
232 uint8_t* const Error)
233 {
234 if (Slot == 0)
235 {
236 *Error = CCID_ERROR_NO_ERROR;
237 return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_NOICCPRESENT;
238 }
239 else
240 {
241 *Error = CCID_ERROR_SLOT_NOT_FOUND;
242 return CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_NOICCPRESENT;
243 }
244 }
245
246 /** Event handler for the CCID_PC_to_RDR_GetSlotStatus. THis message is sent to
247 * the device whenever an application at the host wants to get the current
248 * slot status.
249 */
250 uint8_t CCID_GetSlotStatus(uint8_t Slot,
251 uint8_t* const Error)
252 {
253 if (Slot == 0)
254 {
255 *Error = CCID_ERROR_NO_ERROR;
256 return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_PRESENTANDACTIVE;
257 }
258 else
259 {
260 *Error = CCID_ERROR_SLOT_NOT_FOUND;
261 return CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_NOICCPRESENT;
262 }
263 }
264
265 /** Event handler for the CCID_PC_to_RDR_SetParameters when T=0. This message is sent to
266 * the device whenever an application at the host wants to set the
267 * parameters for a given slot.
268 */
269 uint8_t CCID_SetParameters_T0(uint8_t Slot,
270 uint8_t* const Error,
271 USB_CCID_ProtocolData_T0_t* const T0)
272 {
273 if (Slot == 0)
274 {
275 // Set parameters
276 memcpy(&ProtocolData, T0, sizeof(USB_CCID_ProtocolData_T0_t));
277
278 *Error = CCID_ERROR_NO_ERROR;
279 return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_PRESENTANDACTIVE;
280 }
281 else
282 {
283 *Error = CCID_ERROR_SLOT_NOT_FOUND;
284 return CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_NOICCPRESENT;
285 }
286 }
287
288 /** Event handler for the CCID_PC_to_RDR_GetParameters when T=0. This message is sent to
289 * the device whenever an application at the host wants to get the current
290 * parameters for a given slot.
291 */
292 uint8_t CCID_GetParameters_T0(uint8_t Slot,
293 uint8_t* const Error,
294 uint8_t* ProtocolNum,
295 USB_CCID_ProtocolData_T0_t* const T0)
296 {
297 if (Slot == 0)
298 {
299
300 *ProtocolNum = CCID_PROTOCOLNUM_T0;
301 memcpy(T0, &ProtocolData, sizeof(USB_CCID_ProtocolData_T0_t));
302
303 *Error = CCID_ERROR_NO_ERROR;
304 return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_PRESENTANDACTIVE;
305 }
306 else
307 {
308 *Error = CCID_ERROR_SLOT_NOT_FOUND;
309 return CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_NOICCPRESENT;
310 }
311 }
312
313 /** Event handler for the CCID_PC_to_RDR_XfrBlock. This message is sent to the device
314 * whenever an application at the host wants to send a block of bytes to the device
315 * THe device reply back with an array of bytes
316 */
317 uint8_t CCID_XfrBlock(uint8_t Slot,
318 uint8_t* const ReceivedBuffer,
319 uint8_t ReceivedBufferSize,
320 uint8_t* const SendBuffer,
321 uint8_t* const SentBufferSize,
322 uint8_t* const Error)
323 {
324 if (Slot == 0)
325 {
326 uint8_t OkResponse[2] = {0x90, 0x00};
327
328 memcpy(SendBuffer, OkResponse, sizeof(OkResponse));
329 *SentBufferSize = sizeof(OkResponse);
330
331 *Error = CCID_ERROR_NO_ERROR;
332 return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_NOICCPRESENT;
333 }
334 else
335 {
336 *Error = CCID_ERROR_SLOT_NOT_FOUND;
337 return CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_NOICCPRESENT;
338 }
339 }
340
341 /** Event handler for the CCID_PC_to_RDR_ABort message. This message is sent to the device
342 * whenever an application wants to abort the current operation. A previous CCID_ABORT
343 * control message has to be sent before this one in order to start the abort operation.
344 */
345 uint8_t CCID_Abort(uint8_t Slot,
346 uint8_t Seq,
347 uint8_t* const Error)
348 {
349 if (Aborted && Slot == 0 && AbortedSeq == Seq)
350 {
351 Aborted = false;
352 AbortedSeq = -1;
353
354 *Error = CCID_ERROR_NO_ERROR;
355 return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_PRESENTANDACTIVE;
356 }
357 else if (!Aborted)
358 {
359 *Error = CCID_ERROR_CMD_NOT_ABORTED;
360 return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_PRESENTANDACTIVE;
361 }
362 else if (Slot != 0)
363 {
364 *Error = CCID_ERROR_SLOT_NOT_FOUND;
365 return CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_NOICCPRESENT;
366 }
367
368 *Error = CCID_ERROR_NOT_SUPPORTED;
369 return CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_NOICCPRESENT;
370 }
371
372 /** Gets and status and verifies whether an error occurred. */
373 bool CCID_CheckStatusNoError(uint8_t Status)
374 {
375 return (Status & 0xC0) == 0x0;
376 }
377
378 /** Function to manage CCID request parsing and responses back to the host. */
379 void CCID_Task(void)
380 {
381 Endpoint_SelectEndpoint(CCID_OUT_EPADDR);
382
383 uint8_t RequestBuffer[CCID_EPSIZE - sizeof(USB_CCID_BulkMessage_Header_t)];
384 uint8_t ResponseBuffer[CCID_EPSIZE];
385 Aborted = false;
386 AbortedSeq = -1;
387
388 if (Endpoint_IsOUTReceived())
389 {
390 USB_CCID_BulkMessage_Header_t CCIDHeader;
391 CCIDHeader.MessageType = Endpoint_Read_8();
392 CCIDHeader.Length = Endpoint_Read_32_LE();
393 CCIDHeader.Slot = Endpoint_Read_8();
394 CCIDHeader.Seq = Endpoint_Read_8();
395
396 uint8_t Status;
397 uint8_t Error = CCID_ERROR_NO_ERROR;
398
399 switch (CCIDHeader.MessageType)
400 {
401 case CCID_PC_to_RDR_IccPowerOn:
402 {
403 uint8_t AtrLength;
404 USB_CCID_RDR_to_PC_DataBlock_t* ResponseATR = (USB_CCID_RDR_to_PC_DataBlock_t*)&ResponseBuffer;
405
406 ResponseATR->CCIDHeader.MessageType = CCID_RDR_to_PC_DataBlock;
407 ResponseATR->CCIDHeader.Slot = CCIDHeader.Slot;
408 ResponseATR->CCIDHeader.Seq = CCIDHeader.Seq;
409 ResponseATR->ChainParam = 0;
410
411 Status = CCID_IccPowerOn(ResponseATR->CCIDHeader.Slot, (uint8_t* )ResponseATR->Data, &AtrLength, &Error);
412
413 if (CCID_CheckStatusNoError(Status) && !Aborted)
414 {
415 ResponseATR->CCIDHeader.Length = AtrLength;
416 }
417 else if (Aborted)
418 {
419 Status = CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_PRESENTANDACTIVE;
420 Error = CCID_ERROR_CMD_ABORTED;
421 AtrLength = 0;
422 }
423 else
424 {
425 AtrLength = 0;
426 }
427
428 ResponseATR->Status = Status;
429 ResponseATR->Error = Error;
430
431 Endpoint_ClearOUT();
432
433 Endpoint_SelectEndpoint(CCID_IN_EPADDR);
434 Endpoint_Write_Stream_LE(ResponseATR, sizeof(USB_CCID_RDR_to_PC_DataBlock_t) + AtrLength, NULL);
435 Endpoint_ClearIN();
436 break;
437 }
438
439 case CCID_PC_to_RDR_IccPowerOff:
440 {
441 USB_CCID_RDR_to_PC_SlotStatus_t* ResponsePowerOff = (USB_CCID_RDR_to_PC_SlotStatus_t*)&ResponseBuffer;
442 ResponsePowerOff->CCIDHeader.MessageType = CCID_RDR_to_PC_SlotStatus;
443 ResponsePowerOff->CCIDHeader.Length = 0;
444 ResponsePowerOff->CCIDHeader.Slot = CCIDHeader.Slot;
445 ResponsePowerOff->CCIDHeader.Seq = CCIDHeader.Seq;
446
447 ResponsePowerOff->ClockStatus = 0;
448
449 Status = CCID_IccPowerOff(CCIDHeader.Slot, &Error);
450
451 ResponsePowerOff->Status = Status;
452 ResponsePowerOff->Error = Error;
453
454 Endpoint_ClearOUT();
455
456 Endpoint_SelectEndpoint(CCID_IN_EPADDR);
457 Endpoint_Write_Stream_LE(ResponsePowerOff, sizeof(USB_CCID_RDR_to_PC_SlotStatus_t), NULL);
458 Endpoint_ClearIN();
459 break;
460 }
461
462 case CCID_PC_to_RDR_GetSlotStatus:
463 {
464 USB_CCID_RDR_to_PC_SlotStatus_t* ResponseSlotStatus = (USB_CCID_RDR_to_PC_SlotStatus_t*)&ResponseBuffer;
465 ResponseSlotStatus->CCIDHeader.MessageType = CCID_RDR_to_PC_SlotStatus;
466 ResponseSlotStatus->CCIDHeader.Length = 0;
467 ResponseSlotStatus->CCIDHeader.Slot = CCIDHeader.Slot;
468 ResponseSlotStatus->CCIDHeader.Seq = CCIDHeader.Seq;
469
470 ResponseSlotStatus->ClockStatus = 0;
471
472 Status = CCID_GetSlotStatus(CCIDHeader.Slot, &Error);
473
474 ResponseSlotStatus->Status = Status;
475 ResponseSlotStatus->Error = Error;
476
477 Endpoint_ClearOUT();
478
479 Endpoint_SelectEndpoint(CCID_IN_EPADDR);
480 Endpoint_Write_Stream_LE(ResponseSlotStatus, sizeof(USB_CCID_RDR_to_PC_SlotStatus_t), NULL);
481 Endpoint_ClearIN();
482 break;
483 }
484
485 case CCID_PC_to_RDR_SetParameters:
486 {
487 uint8_t ProtocolNum = Endpoint_Read_8();
488 uint8_t RFU = Endpoint_Read_16_LE();
489
490 (void)RFU;
491
492 USB_CCID_RDR_to_PC_Parameters_t* ResponseParametersStatus = (USB_CCID_RDR_to_PC_Parameters_t*)&ResponseBuffer;
493 ResponseParametersStatus->CCIDHeader.MessageType = CCID_RDR_to_PC_Parameters;
494 ResponseParametersStatus->CCIDHeader.Length = 0;
495 ResponseParametersStatus->CCIDHeader.Slot = CCIDHeader.Slot;
496 ResponseParametersStatus->CCIDHeader.Seq = CCIDHeader.Seq;
497
498 if (ProtocolNum == CCID_PROTOCOLNUM_T0)
499 {
500 if ((CCIDHeader.Length * sizeof(uint8_t)) == sizeof(USB_CCID_ProtocolData_T0_t))
501 {
502 Endpoint_Read_Stream_LE(RequestBuffer, CCIDHeader.Length * sizeof(uint8_t), NULL);
503
504 Status = CCID_SetParameters_T0(CCIDHeader.Slot, &Error, (USB_CCID_ProtocolData_T0_t*)RequestBuffer);
505 if (CCID_CheckStatusNoError(Status))
506 {
507 ResponseParametersStatus->CCIDHeader.Length = CCIDHeader.Length;
508 Status = CCID_GetParameters_T0(CCIDHeader.Slot, &Error, &ResponseParametersStatus->ProtocolNum, (USB_CCID_ProtocolData_T0_t*) &ResponseParametersStatus->ProtocolData);
509 }
510 }
511 else
512 {
513 // Unexpected length
514 Status = CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_PRESENTANDACTIVE;
515 }
516 }
517 else
518 {
519 ResponseParametersStatus->ProtocolNum = CCID_PROTOCOLNUM_T0;
520
521 // For now, we don't support T=1 protocol
522 Error = CCID_ERROR_PARAMETERS_PROTOCOL_NOT_SUPPORTED;
523 Status = CCID_COMMANDSTATUS_ERROR | CCID_ICCSTATUS_PRESENTANDACTIVE;
524 }
525
526 ResponseParametersStatus->Status = Status;
527 ResponseParametersStatus->Error = Error;
528
529 Endpoint_ClearOUT();
530
531 Endpoint_SelectEndpoint(CCID_IN_EPADDR);
532 Endpoint_Write_Stream_LE(ResponseParametersStatus, sizeof(USB_CCID_BulkMessage_Header_t) + 3 + ResponseParametersStatus->CCIDHeader.Length, NULL);
533 Endpoint_ClearIN();
534 break;
535 }
536
537 case CCID_PC_to_RDR_GetParameters:
538 {
539 USB_CCID_RDR_to_PC_Parameters_t* ResponseParametersStatus = (USB_CCID_RDR_to_PC_Parameters_t*)&ResponseBuffer;
540 ResponseParametersStatus->CCIDHeader.MessageType = CCID_RDR_to_PC_Parameters;
541 ResponseParametersStatus->CCIDHeader.Length = sizeof(USB_CCID_ProtocolData_T0_t);
542 ResponseParametersStatus->CCIDHeader.Slot = CCIDHeader.Slot;
543 ResponseParametersStatus->CCIDHeader.Seq = CCIDHeader.Seq;
544
545 Status = CCID_GetParameters_T0(CCIDHeader.Slot, &Error, &ResponseParametersStatus->ProtocolNum, (USB_CCID_ProtocolData_T0_t*) &ResponseParametersStatus->ProtocolData);
546
547 ResponseParametersStatus->Status = Status;
548 ResponseParametersStatus->Error = Error;
549
550 Endpoint_ClearOUT();
551
552 Endpoint_SelectEndpoint(CCID_IN_EPADDR);
553 Endpoint_Write_Stream_LE(ResponseParametersStatus, sizeof(USB_CCID_BulkMessage_Header_t) + 3 + ResponseParametersStatus->CCIDHeader.Length, NULL);
554 Endpoint_ClearIN();
555 break;
556 }
557
558 case CCID_PC_to_RDR_XfrBlock:
559 {
560 uint8_t Bwi = Endpoint_Read_8();
561 uint16_t LevelParameter = Endpoint_Read_16_LE();
562
563 (void)Bwi;
564 (void)LevelParameter;
565
566 Endpoint_Read_Stream_LE(RequestBuffer, CCIDHeader.Length * sizeof(uint8_t), NULL);
567
568 uint8_t ResponseDataLength = 0;
569
570 USB_CCID_RDR_to_PC_DataBlock_t* ResponseBlock = (USB_CCID_RDR_to_PC_DataBlock_t*)&ResponseBuffer;
571 ResponseBlock->CCIDHeader.MessageType = CCID_RDR_to_PC_DataBlock;
572 ResponseBlock->CCIDHeader.Slot = CCIDHeader.Slot;
573 ResponseBlock->CCIDHeader.Seq = CCIDHeader.Seq;
574
575 ResponseBlock->ChainParam = 0;
576
577 Status = CCID_XfrBlock(CCIDHeader.Slot, RequestBuffer, CCIDHeader.Length, (uint8_t*) &ResponseBlock->Data, &ResponseDataLength, &Error);
578
579 if (CCID_CheckStatusNoError(Status) && !Aborted)
580 {
581 ResponseBlock->CCIDHeader.Length = ResponseDataLength;
582 }
583 else if (Aborted)
584 {
585 Status = CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_PRESENTANDACTIVE;
586 Error = CCID_ERROR_CMD_ABORTED;
587 ResponseDataLength = 0;
588 }
589 else
590 {
591 ResponseDataLength = 0;
592 }
593
594 ResponseBlock->Status = Status;
595 ResponseBlock->Error = Error;
596
597 Endpoint_ClearOUT();
598
599 Endpoint_SelectEndpoint(CCID_IN_EPADDR);
600 Endpoint_Write_Stream_LE(ResponseBlock, sizeof(USB_CCID_RDR_to_PC_DataBlock_t) + ResponseDataLength, NULL);
601 Endpoint_ClearIN();
602 break;
603 }
604
605 case CCID_PC_to_RDR_Abort:
606 {
607 USB_CCID_RDR_to_PC_SlotStatus_t* ResponseAbort = (USB_CCID_RDR_to_PC_SlotStatus_t*)&ResponseBuffer;
608 ResponseAbort->CCIDHeader.MessageType = CCID_RDR_to_PC_SlotStatus;
609 ResponseAbort->CCIDHeader.Length = 0;
610 ResponseAbort->CCIDHeader.Slot = CCIDHeader.Slot;
611 ResponseAbort->CCIDHeader.Seq = CCIDHeader.Seq;
612
613 ResponseAbort->ClockStatus = 0;
614
615 Status = CCID_Abort(CCIDHeader.Slot, CCIDHeader.Seq, &Error);
616
617 ResponseAbort->Status = Status;
618 ResponseAbort->Error = Error;
619
620 Endpoint_ClearOUT();
621
622 Endpoint_SelectEndpoint(CCID_IN_EPADDR);
623 Endpoint_Write_Stream_LE(ResponseAbort, sizeof(USB_CCID_RDR_to_PC_SlotStatus_t), NULL);
624 Endpoint_ClearIN();
625 break;
626 }
627
628 default:
629 {
630 memset(ResponseBuffer, 0x00, sizeof(ResponseBuffer));
631
632 Endpoint_SelectEndpoint(CCID_IN_EPADDR);
633 Endpoint_Write_Stream_LE(ResponseBuffer, sizeof(ResponseBuffer), NULL);
634 Endpoint_ClearIN();
635 }
636 }
637 }
638 }