CCID: Initial support for GetParameters and SetParameters
[pub/USBasp.git] / Demos / Device / LowLevel / CCID / CCID.c
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2018.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.lufa-lib.org
7 */
8
9 /*
10 Copyright 2018 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11 Copyright 2018 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 static USB_CCID_ProtocolData_T0_t ProtocolData;
56
57
58
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.
61 */
62 int main(void)
63 {
64 ProtocolData.FindexDindex = 0x11;
65 ProtocolData.TCCKST0 = 0x00;
66 ProtocolData.GuardTimeT0 = 0x00;
67 ProtocolData.WaitingIntegerT0 = 0x0A;
68 ProtocolData.ClockStop = 0x00;
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 case CCID_GET_CLOCK_FREQUENCIES:
179 {
180 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
181 {
182 Endpoint_ClearSETUP();
183 Endpoint_Write_8(0); // Not supported
184 Endpoint_ClearOUT();
185 }
186
187 break;
188 }
189 case CCID_GET_DATA_RATES:
190 {
191 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
192 {
193 Endpoint_ClearSETUP();
194 Endpoint_Write_8(0); // Not supported
195 Endpoint_ClearOUT();
196 }
197
198 break;
199 }
200 }
201 }
202
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)
206 */
207 uint8_t CCID_IccPowerOn(uint8_t slot,
208 uint8_t* const atr,
209 uint8_t* const atrLength,
210 uint8_t* const error)
211 {
212 if (slot == 0)
213 {
214 Iso7816_CreateSimpleAtr(atr, atrLength);
215
216 *error = CCID_ERROR_NO_ERROR;
217 return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_PRESENTANDACTIVE;
218 }
219 else
220 {
221 *error = CCID_ERROR_SLOT_NOT_FOUND;
222 return CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_NOICCPRESENT;
223 }
224 }
225
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.
228 */
229 uint8_t CCID_IccPowerOff(uint8_t slot,
230 uint8_t* const error)
231 {
232 if (slot == 0)
233 {
234 *error = CCID_ERROR_NO_ERROR;
235 return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_NOICCPRESENT;
236 }
237 else
238 {
239 *error = CCID_ERROR_SLOT_NOT_FOUND;
240 return CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_NOICCPRESENT;
241 }
242 }
243
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
246 * slot status.
247 */
248 uint8_t CCID_GetSlotStatus(uint8_t slot,
249 uint8_t* const error)
250 {
251 if (slot == 0)
252 {
253 *error = CCID_ERROR_NO_ERROR;
254 return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_PRESENTANDACTIVE;
255 }
256 else
257 {
258 *error = CCID_ERROR_SLOT_NOT_FOUND;
259 return CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_NOICCPRESENT;
260 }
261 }
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.
265 */
266 uint8_t CCID_SetParameters_T0(uint8_t slot,
267 uint8_t* const error,
268 USB_CCID_ProtocolData_T0_t* const t0)
269 {
270 if (slot == 0)
271 {
272 //set parameters
273 memcpy(&ProtocolData, t0, sizeof(USB_CCID_ProtocolData_T0_t));
274
275 *error = CCID_ERROR_NO_ERROR;
276 return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_PRESENTANDACTIVE;
277 }
278 else
279 {
280 *error = CCID_ERROR_SLOT_NOT_FOUND;
281 return CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_NOICCPRESENT;
282 }
283 }
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.
287 */
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)
292 {
293 if (slot == 0)
294 {
295
296 *ProtocolNum = CCID_PROTOCOLNUM_T0;
297 memcpy(t0, &ProtocolData, sizeof(USB_CCID_ProtocolData_T0_t));
298
299 *ProtocolNum = CCID_PROTOCOLNUM_T0;
300
301 *error = CCID_ERROR_NO_ERROR;
302 return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_PRESENTANDACTIVE;
303 }
304 else
305 {
306 *error = CCID_ERROR_SLOT_NOT_FOUND;
307 return CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_NOICCPRESENT;
308 }
309 }
310
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
314 */
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)
321 {
322 if (slot == 0)
323 {
324 uint8_t okResponse[2] = {0x90, 0x00};
325 memcpy(sendBuffer, okResponse, sizeof(okResponse));
326 *sentBufferSize = sizeof(okResponse);
327
328 *error = CCID_ERROR_NO_ERROR;
329 return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_NOICCPRESENT;
330 }
331 else
332 {
333 *error = CCID_ERROR_SLOT_NOT_FOUND;
334 return CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_NOICCPRESENT;
335 }
336 }
337
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.
341 */
342 uint8_t CCID_Abort(uint8_t slot,
343 uint8_t seq,
344 uint8_t* const error)
345 {
346 if (Aborted && slot == 0 && AbortedSeq == seq)
347 {
348 Aborted = false;
349 AbortedSeq = -1;
350 *error = CCID_ERROR_NO_ERROR;
351 return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_PRESENTANDACTIVE;
352 }
353 else if (!Aborted)
354 {
355 *error = CCID_ERROR_CMD_NOT_ABORTED;
356 return CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_PRESENTANDACTIVE;
357 }
358 else if (slot != 0)
359 {
360 *error = CCID_ERROR_SLOT_NOT_FOUND;
361 return CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_NOICCPRESENT;
362 }
363
364 *error = CCID_ERROR_NOT_SUPPORTED;
365 return CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_NOICCPRESENT;
366 }
367
368 /** Gets and status and verifies whether an error occurred. */
369 bool CCID_CheckStatusNoError(uint8_t status)
370 {
371 return (status & 0xC0) == 0x0;
372 }
373
374 /** Function to manage CCID request parsing and responses back to the host. */
375 void CCID_Task(void)
376 {
377 Endpoint_SelectEndpoint(CCID_OUT_EPADDR);
378
379 uint8_t RequestBuffer[CCID_EPSIZE - sizeof(USB_CCID_BulkMessage_Header_t)];
380 uint8_t ResponseBuffer[CCID_EPSIZE];
381 Aborted = false;
382 AbortedSeq = -1;
383
384 if (Endpoint_IsOUTReceived())
385 {
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();
391
392 uint8_t Status;
393 uint8_t Error = CCID_ERROR_NO_ERROR;
394
395 switch (CCIDHeader.MessageType)
396 {
397 case CCID_PC_to_RDR_IccPowerOn:
398 {
399 uint8_t AtrLength;
400 USB_CCID_RDR_to_PC_DataBlock_t* ResponseATR = (USB_CCID_RDR_to_PC_DataBlock_t*)&ResponseBuffer;
401
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;
406
407 Status = CCID_IccPowerOn(ResponseATR->CCIDHeader.Slot, (uint8_t* )ResponseATR->Data, &AtrLength, &Error);
408
409 if (CCID_CheckStatusNoError(Status) && !Aborted)
410 {
411 ResponseATR->CCIDHeader.Length = AtrLength;
412 }
413 else if (Aborted)
414 {
415 Status = CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_PRESENTANDACTIVE;
416 Error = CCID_ERROR_CMD_ABORTED;
417 AtrLength = 0;
418 }
419 else
420 {
421 AtrLength = 0;
422 }
423
424 ResponseATR->Status = Status;
425 ResponseATR->Error = Error;
426
427 Endpoint_ClearOUT();
428
429 Endpoint_SelectEndpoint(CCID_IN_EPADDR);
430 Endpoint_Write_Stream_LE(ResponseATR, sizeof(USB_CCID_RDR_to_PC_DataBlock_t) + AtrLength, NULL);
431 Endpoint_ClearIN();
432 break;
433 }
434
435 case CCID_PC_to_RDR_IccPowerOff:
436 {
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;
442
443 ResponsePowerOff->ClockStatus = 0;
444
445 Status = CCID_IccPowerOff(CCIDHeader.Slot, &Error);
446
447 ResponsePowerOff->Status = Status;
448 ResponsePowerOff->Error = Error;
449
450 Endpoint_ClearOUT();
451
452 Endpoint_SelectEndpoint(CCID_IN_EPADDR);
453 Endpoint_Write_Stream_LE(ResponsePowerOff, sizeof(USB_CCID_RDR_to_PC_SlotStatus_t), NULL);
454 Endpoint_ClearIN();
455 break;
456 }
457
458 case CCID_PC_to_RDR_GetSlotStatus:
459 {
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;
465
466 ResponseSlotStatus->ClockStatus = 0;
467
468 Status = CCID_GetSlotStatus(CCIDHeader.Slot, &Error);
469
470 ResponseSlotStatus->Status = Status;
471 ResponseSlotStatus->Error = Error;
472
473 Endpoint_ClearOUT();
474
475 Endpoint_SelectEndpoint(CCID_IN_EPADDR);
476 Endpoint_Write_Stream_LE(ResponseSlotStatus, sizeof(USB_CCID_RDR_to_PC_SlotStatus_t), NULL);
477 Endpoint_ClearIN();
478 break;
479 }
480 case CCID_PC_to_RDR_SetParameters:
481 {
482 uint8_t ProtocolNum = Endpoint_Read_8();
483 uint8_t RFU = Endpoint_Read_16_LE();
484
485 (void)RFU;
486
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;
492
493 if(ProtocolNum == CCID_PROTOCOLNUM_T0)
494 {
495 if(CCIDHeader.Length * sizeof(uint8_t) == sizeof(USB_CCID_ProtocolData_T0_t))
496 {
497
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))
501 {
502 ResponseParametersStatus->CCIDHeader.Length = CCIDHeader.Length;
503 Status = CCID_GetParameters_T0(CCIDHeader.Slot, &Error, &ResponseParametersStatus->ProtocolNum, (USB_CCID_ProtocolData_T0_t*) &ResponseParametersStatus->ProtocolData);
504 }
505 }
506 else
507 {
508 //unexpected length
509 Status = CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_PRESENTANDACTIVE;
510 }
511 }
512 else
513 {
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;
518 }
519
520 ResponseParametersStatus->Status = Status;
521 ResponseParametersStatus->Error = Error;
522
523 Endpoint_ClearOUT();
524
525 Endpoint_SelectEndpoint(CCID_IN_EPADDR);
526 Endpoint_Write_Stream_LE(ResponseParametersStatus, sizeof(USB_CCID_BulkMessage_Header_t) + 3 + ResponseParametersStatus->CCIDHeader.Length , NULL);
527 Endpoint_ClearIN();
528 break;
529 }
530 case CCID_PC_to_RDR_GetParameters:
531 {
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;
537
538 Status = CCID_GetParameters_T0(CCIDHeader.Slot, &Error, &ResponseParametersStatus->ProtocolNum, (USB_CCID_ProtocolData_T0_t*) &ResponseParametersStatus->ProtocolData);
539
540 ResponseParametersStatus->Status = Status;
541 ResponseParametersStatus->Error = Error;
542
543 Endpoint_ClearOUT();
544
545 Endpoint_SelectEndpoint(CCID_IN_EPADDR);
546 Endpoint_Write_Stream_LE(ResponseParametersStatus, sizeof(USB_CCID_BulkMessage_Header_t) + 3 + ResponseParametersStatus->CCIDHeader.Length , NULL);
547 Endpoint_ClearIN();
548 break;
549 }
550 case CCID_PC_to_RDR_XfrBlock:
551 {
552 uint8_t Bwi = Endpoint_Read_8();
553 uint16_t LevelParameter = Endpoint_Read_16_LE();
554
555 (void)Bwi;
556 (void)LevelParameter;
557
558 Endpoint_Read_Stream_LE(RequestBuffer, CCIDHeader.Length * sizeof(uint8_t), NULL);
559
560 uint8_t ResponseDataLength = 0;
561
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;
566
567 ResponseBlock->ChainParam = 0;
568
569 Status = CCID_XfrBlock(CCIDHeader.Slot, RequestBuffer, CCIDHeader.Length, (uint8_t*) &ResponseBlock->Data, &ResponseDataLength, &Error);
570
571 if (CCID_CheckStatusNoError(Status) && !Aborted)
572 {
573 ResponseBlock->CCIDHeader.Length = ResponseDataLength;
574 }
575 else if (Aborted)
576 {
577 Status = CCID_COMMANDSTATUS_FAILED | CCID_ICCSTATUS_PRESENTANDACTIVE;
578 Error = CCID_ERROR_CMD_ABORTED;
579 ResponseDataLength = 0;
580 }
581 else
582 {
583 ResponseDataLength = 0;
584 }
585
586 ResponseBlock->Status = Status;
587 ResponseBlock->Error = Error;
588
589 Endpoint_ClearOUT();
590
591 Endpoint_SelectEndpoint(CCID_IN_EPADDR);
592 Endpoint_Write_Stream_LE(ResponseBlock, sizeof(USB_CCID_RDR_to_PC_DataBlock_t) + ResponseDataLength, NULL);
593 Endpoint_ClearIN();
594 break;
595 }
596
597 case CCID_PC_to_RDR_Abort:
598 {
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;
604
605 ResponseAbort->ClockStatus = 0;
606
607 Status = CCID_Abort(CCIDHeader.Slot, CCIDHeader.Seq, &Error);
608
609 ResponseAbort->Status = Status;
610 ResponseAbort->Error = Error;
611
612 Endpoint_ClearOUT();
613
614 Endpoint_SelectEndpoint(CCID_IN_EPADDR);
615 Endpoint_Write_Stream_LE(ResponseAbort, sizeof(USB_CCID_RDR_to_PC_SlotStatus_t), NULL);
616 Endpoint_ClearIN();
617 break;
618 }
619 default:
620 {
621 memset(ResponseBuffer, 0x00, sizeof(ResponseBuffer));
622
623 Endpoint_SelectEndpoint(CCID_IN_EPADDR);
624 Endpoint_Write_Stream_LE(ResponseBuffer, sizeof(ResponseBuffer), NULL);
625 Endpoint_ClearIN();
626 }
627 }
628 }
629 }