/** * CT-BCS Request ICC command * * @param ctx Reader context * @param lc Length of command * @param cmd Command * @param lr Length of response * @param rsp Response buffer * @return \ref OK, \ref ERR_CT, \ref ERR_MEMORY */ int RequestICC(struct scr *ctx, unsigned int lc, unsigned char *cmd, unsigned int *lr, unsigned char *rsp) { int status, timeout; if ((lc > 4) && (cmd[4] == 1)) { timeout = cmd[5]; } else { timeout = 0; } status = PC_to_RDR_GetSlotStatus(ctx); if (status < 0) { rsp[0] = HIGH(NOT_SUCCESSFUL); rsp[1] = LOW(NOT_SUCCESSFUL); *lr = 2; return ERR_CT; } timeout *= 4; do { status = PC_to_RDR_GetSlotStatus(ctx); if (status < 0) { rsp[0] = HIGH(NOT_SUCCESSFUL); rsp[1] = LOW(NOT_SUCCESSFUL); *lr = 2; return ERR_CT; } if ((status == ICC_PRESENT_AND_INACTIVE) || !timeout) { break; } usleep(250000); timeout--; } while (timeout); if (!timeout && (status == NO_ICC_PRESENT)) { rsp[0] = HIGH(W_NO_CARD_PRESENTED); rsp[1] = LOW(W_NO_CARD_PRESENTED); *lr = 2; return OK; } if ((status = ResetCard(ctx, lc, cmd, lr, rsp)) < 0) { return status; } return OK; }
/** * Get ICC status * * @param ctx Reader context * @param lr Length of response * @param rsp Response buffer * @return \ref OK, \ref ERR_CT, \ref ERR_MEMORY */ int GetICCStatus(struct scr *ctx, unsigned int *lr, unsigned char *rsp) { int status; status = PC_to_RDR_GetSlotStatus(ctx); if (status < 0) { rsp[0] = HIGH(NOT_SUCCESSFUL); rsp[1] = LOW(NOT_SUCCESSFUL); *lr = 2; return ERR_CT; } if (*lr < 5) { return ERR_MEMORY; } rsp[0] = 0x80; rsp[1] = 0x01; rsp[2] = 0x00; /* Set ICC Status DO - default is no ICC present */ if (status == ICC_PRESENT_AND_INACTIVE) { rsp[2] |= 0x03; /* card in, no CVCC */ } if (status == ICC_PRESENT_AND_ACTIVE) { rsp[2] |= 0x05; /* card in, CVCC on */ } rsp[3] = HIGH(SMARTCARD_SUCCESS); rsp[4] = LOW(SMARTCARD_SUCCESS); *lr = 5; return OK; }
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; } }
/** * CT-BCS Eject ICC command * * @param ctx Reader context * @param lc Length of command * @param cmd Command * @param lr Length of response * @param rsp Response buffer * @return \ref OK, \ref ERR_CT */ int EjectICC(struct scr *ctx, unsigned int lc, unsigned char *cmd, unsigned int *lr, unsigned char *rsp) { int status; unsigned char save_timeout; unsigned char timeout; /* Reader has no display or other goodies, so check for correct P2 parameter */ /* Unmask bit 3, because we can always keep the card in the slot */ if ((cmd[3] & 0xFB) != 0x00) { rsp[0] = HIGH(WRONG_PARAMETERS_P1_P2); rsp[1] = LOW(WRONG_PARAMETERS_P1_P2); *lr = 2; return OK; } if ((lc > 4) && (cmd[4] > 0)) { timeout = cmd[5]; } else { timeout = 0; } save_timeout = timeout; status = PC_to_RDR_IccPowerOff(ctx); if (status < 0) { rsp[0] = HIGH(NOT_SUCCESSFUL); rsp[1] = LOW(NOT_SUCCESSFUL); *lr = 2; return ERR_CT; } ctx->CTModFunc = NULL; ctx->LenOfATR = 0; ctx->NumOfHB = 0; save_timeout *= 4; if (save_timeout > 0) { do { status = PC_to_RDR_GetSlotStatus(ctx); if (status < 0) { rsp[0] = HIGH(NOT_SUCCESSFUL); rsp[1] = LOW(NOT_SUCCESSFUL); *lr = 2; return ERR_CT; } if (status == ICC_PRESENT_AND_INACTIVE || status == NO_ICC_PRESENT) { break; } usleep(250000); } while (--save_timeout); } else { /* Command OK,no timeout specified */ rsp[0] = HIGH(SMARTCARD_SUCCESS); rsp[1] = LOW(SMARTCARD_SUCCESS); *lr = 2; return OK; } if (save_timeout) { /* Command OK, card removed */ rsp[0] = HIGH(SMARTCARD_SUCCESS); rsp[1] = LOW(SMARTCARD_SUCCESS); *lr = 2; return OK; } if ((!save_timeout) && (timeout > 0)) { /* warning: card not removed */ rsp[0] = HIGH(W_NO_CARD_PRESENTED); rsp[1] = LOW(W_NO_CARD_PRESENTED); *lr = 2; } return OK; }
/** * @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); } }