void CCID_DispatchMessage(void) { uint8_t ErrorCode; if(gu8IsBulkOutReady) { switch(UsbMessageBuffer[OFFSET_BMESSAGETYPE]) { case PC_TO_RDR_ICCPOWERON: ErrorCode = PC_to_RDR_IccPowerOn(); RDR_to_PC_DataBlock(ErrorCode); break; case PC_TO_RDR_ICCPOWEROFF: ErrorCode = PC_to_RDR_IccPowerOff(); RDR_to_PC_SlotStatus(ErrorCode); break; case PC_TO_RDR_GETSLOTSTATUS: ErrorCode = PC_to_RDR_GetSlotStatus(); RDR_to_PC_SlotStatus(ErrorCode); break; case PC_TO_RDR_XFRBLOCK: ErrorCode = PC_to_RDR_XfrBlock(); RDR_to_PC_DataBlock(ErrorCode); break; case PC_TO_RDR_GETPARAMETERS: ErrorCode = PC_to_RDR_GetParameters(); RDR_to_PC_Parameters(ErrorCode); break; case PC_TO_RDR_RESETPARAMETERS: ErrorCode = PC_to_RDR_ResetParameters(); RDR_to_PC_Parameters(ErrorCode); break; case PC_TO_RDR_SETPARAMETERS: ErrorCode = PC_to_RDR_SetParameters(); RDR_to_PC_Parameters(ErrorCode); break; case PC_TO_RDR_ESCAPE: ErrorCode = PC_to_RDR_Escape(); RDR_to_PC_Escape(ErrorCode); break; case PC_TO_RDR_ICCCLOCK: ErrorCode = PC_to_RDR_IccClock(); RDR_to_PC_SlotStatus(ErrorCode); break; case PC_TO_RDR_ABORT: ErrorCode = PC_to_RDR_Abort(); RDR_to_PC_SlotStatus(ErrorCode); break; case PC_TO_RDR_SETDATARATEANDCLOCKFREQUENCY: case PC_TO_RDR_SECURE: case PC_TO_RDR_T0APDU: case PC_TO_RDR_MECHANICAL: default: CmdNotSupported(); break; } CCID_BulkInMessage(); gu8IsBulkOutReady = 0; } }
/** * Process a APDU using the CCID APDU transfer mode * * @param ctx Reader context * @param lc Length of command APDU * @param cmd Command APDU * @param lr Length of response APDU * @param rsp Response APDU * @return 0 on success, -1 on error */ static int ccidAPDUProcess (struct scr *ctx, unsigned int lc, unsigned char *cmd, unsigned int *lr, unsigned char *rsp) { int rc,r,maxlr; unsigned int len; unsigned char buf[BUFFMAX],*po,status,error,chain; unsigned short level = 0; maxlr = *lr; *lr = 0; po = cmd; while (lc > 0) { len = lc; if (lc > BUFFMAX) { if (level) level = 3; // Intermediate extended command else level = 1; // First extended command len = BUFFMAX; } else { if (level) level = 2; // Final extended command } rc = PC_to_RDR_XfrBlock(ctx, len, po, (unsigned char)level); if (rc < 0) return -1; lc -= len; po += len; len = BUFFMAX; rc = RDR_to_PC_DataBlock(ctx, &len, buf, &status, &error, &chain); if (rc < 0) return -1; } r = 0; while (1) { if (len > maxlr) { len = maxlr; r = ERR_MEMORY; } memcpy(rsp, buf, len); rsp += len; maxlr -= len; *lr += len; if ((chain == 1) || (chain == 3)) { rc = PC_to_RDR_XfrBlock(ctx, 0, NULL, 0x10); if (rc < 0) return -1; len = BUFFMAX; rc = RDR_to_PC_DataBlock(ctx, &len, buf, &status, &error, &chain); if (rc < 0) return -1; continue; } break; } return r; }
/** * @brief CCID_CmdDecode * Parse the commands and Proccess command * @param pdev: device instance * @retval None */ void CCID_CmdDecode(USB_CORE_HANDLE *pdev) { uint8_t errorCode; switch (Ccid_bulkout_data.bMessageType) { case PC_TO_RDR_ICCPOWERON: errorCode = PC_to_RDR_IccPowerOn(); RDR_to_PC_DataBlock(errorCode); break; case PC_TO_RDR_ICCPOWEROFF: errorCode = PC_to_RDR_IccPowerOff(); RDR_to_PC_SlotStatus(errorCode); break; case PC_TO_RDR_GETSLOTSTATUS: errorCode = PC_to_RDR_GetSlotStatus(); RDR_to_PC_SlotStatus(errorCode); break; case PC_TO_RDR_XFRBLOCK: errorCode = PC_to_RDR_XfrBlock(); RDR_to_PC_DataBlock(errorCode); break; case PC_TO_RDR_GETPARAMETERS: errorCode = PC_to_RDR_GetParameters(); RDR_to_PC_Parameters(errorCode); break; case PC_TO_RDR_RESETPARAMETERS: errorCode = PC_to_RDR_ResetParameters(); RDR_to_PC_Parameters(errorCode); break; case PC_TO_RDR_SETPARAMETERS: errorCode = PC_to_RDR_SetParameters(); RDR_to_PC_Parameters(errorCode); break; case PC_TO_RDR_ESCAPE: errorCode = PC_to_RDR_Escape(); RDR_to_PC_Escape(errorCode); break; case PC_TO_RDR_ICCCLOCK: errorCode = PC_to_RDR_IccClock(); RDR_to_PC_SlotStatus(errorCode); break; case PC_TO_RDR_ABORT: errorCode = PC_to_RDR_Abort(); RDR_to_PC_SlotStatus(errorCode); break; case PC_TO_RDR_T0APDU: errorCode = PC_TO_RDR_T0Apdu(); RDR_to_PC_SlotStatus(errorCode); break; case PC_TO_RDR_MECHANICAL: errorCode = PC_TO_RDR_Mechanical(); RDR_to_PC_SlotStatus(errorCode); break; case PC_TO_RDR_SETDATARATEANDCLOCKFREQUENCY: errorCode = PC_TO_RDR_SetDataRateAndClockFrequency(); RDR_to_PC_DataRateAndClockFrequency(errorCode); break; case PC_TO_RDR_SECURE: errorCode = PC_TO_RDR_Secure(); RDR_to_PC_DataBlock(errorCode); break; default: RDR_to_PC_SlotStatus(SLOTERROR_CMD_NOT_SUPPORTED); break; } /********** Decide for all commands ***************/ if (Ccid_BulkState == CCID_STATE_SEND_RESP) { CCID_Response_SendData(pdev, (uint8_t*)&Ccid_bulkin_data, Ccid_bulkin_data.u16SizeToSend); } }