RF Card
>w## Notice
> * please include the header file "bwsdk_api.h" when you need to use RF Card
`#include "bwsdk_api.h"`
>i## data structure
```
#define PICC_APDU_LEN_MIN 4 ///< Minimum bytes of C-APDU
#define PICC_APDU_LEN_MAX 260 ///< Maximum bytes of C-APDU
#define PICC_SW_SIZE 2 ///< Bytes of Status-Word
/**
* @brief TAG enum for PICC transparent transfer command.
*/
typedef enum {
PICC_TAG_BDR_PCD = 0x61, ///< 0x61, Baudrate of PCD->PICC, n*106000
PICC_TAG_BDR_PICC, ///< 0x62, Baudrate of PICC->PCD, n*106000
PICC_TAG_TYPE, ///< 0x63, Type of PICC
PICC_TAG_DATA_SND, ///< 0x64, Data to send
PICC_TAG_DATA_RCV, ///< 0x65, Data of receive
PICC_TAG_FRAME, ///< 0x66, Frame type
PICC_TAG_FWT, ///< 0x67, Frame wait time
PICC_TAG_FSGT, ///< 0x68, Frame guard time
PICC_TAG_FSC, ///< 0x69, Frame size
PICC_TAG_CRC_EN, ///< 0x6A, CRC by RF-chip
} TagPicc_t;
///< tag & cmd definition
#define TAG_CMD_AUTH 'A' ///< Authenticate
#define TAG_CMD_RAED 'R' ///< Read block
#define TAG_CMD_WRITE 'W' ///< Write block
#define TAG_CMD_PAGE 'P' ///< Write page
#define TAG_CMD_INC '+' ///< Value increment
#define TAG_CMD_DEC '-' ///< Value decrement
#define TAG_CMD_RESTORE '>' ///< Value restore
#define TAG_IDX_AUTH_KEYA 'A' ///< M1 KeyA
#define TAG_IDX_AUTH_KEYB 'B' ///< M1 KeyB
#define TAG_IDX_TRANSPARENT_MODE 0x90 ///< For define transparent mode
#define TAG_PSEUDO_APDU_CLS TAG_IDX_TRANSPARENT_MODE ///<
#define TAG_M1_KEY_LEN 6 ///< Key length of M1
#define TAG_M1_BLOCK_LEN 0x10 ///< Block length of M1
#define TAG_M1_VALUE_LEN 4 ///< Value length of M1
#define MIFARE_OPT_BUF_LEN 128 ///< PICC TAG card buffer size
/**
* @brief PICC TAG card command and response structure
*/
typedef struct ST_TAG_OPT {
unsigned char ucOptCmd; ///< Operation command: 'R', 'W', 'P', 'A', '+', '-', '>', ...
unsigned char ucOptIdx; ///< Operation index: 'A', 'B' for M1 authenticate, 0x90 for transparent APDU mode.
unsigned char ucOptSrc; ///< Operation block source: For Authen, read, write, write page, '+', '-', '>'.
unsigned char ucOptDest; ///< Operation block destination: For '+', '-', '>'.
unsigned char ucOptValLen; ///< Operation Length: Bytes to read or in optVal.
unsigned char aucOptVal[MIFARE_OPT_BUF_LEN]; ///< Operation data.
} TagOptType;
/**
* @brief PICC card information
*/
typedef struct PICC_INFO_ST {
unsigned char ucPiccCardType; ///< Type of PICC
unsigned char ucPiccSlot; ///< PICC logical channel number
unsigned char ucPiccSnLen; ///< Length of PICC serial number
unsigned char ucPiccInfoLen; ///< Length of PICC information
unsigned char aucPiccSN[12]; ///< PICC serial number
unsigned char aucPiccInfo[128]; ///< PICC information
} PiccInfo_T;
```
>i## PiccOpen
### Prototype
`int PiccOpen(void);`
### Function
* Open PICC module
### Parameter
|Name|Type|description|
|-|-|-|
|none|||
### Retval
|Value|Type|Description|
|-|-|-|
|=0|int|success|
|<0|int|fail|
>i## PiccDetect
### Prototype
`int PiccDetect(unsigned char ucMode, PiccInfo_T *pstPiccInfo);`
### Function
* Detect PICC
### Parameter
|Name|Type|description|
|-|-|-|
|ucMode|unsigned char|[in] ucMode: 0x01: EMV mode, 'A': TypeA CPU mode, 'B': TypeB CPU mode, 'M': Mifare mode|
|pstPiccInfo|PiccInfo_T *|[out] pstPiccInfo: PICC card information|
### Retval
|Value|Type|Description|
|-|-|-|
|=0|int|success|
|<0|int|fail|
>i## PiccApduExchange
### Prototype
`int PiccApduExchange(unsigned char *pucCmd, unsigned int uiCmdLen, unsigned char *pucRsp, unsigned char *pucSW);`
### Function
* PICC APDU exchange
### Parameter
|Name|Type|description|
|-|-|-|
|pucCmd|unsigned char *|C-APDU|
|uiCmdLen|unsigned int|Length of C-APDU|
|pucRsp|unsigned char *|R-APDU|
|pucSW|unsigned char *|Status-Word (2 bytes)|
### Retval
|Value|Type|Description|
|-|-|-|
|>=0|int|success(Length of R-APDU)|
|<0|int|fail|
>i## PiccRemove
### Prototype
`int PiccRemove(unsigned char ucMode, unsigned char ucSlot);`
### Function
* Remove PICC
### Parameter
|Name|Type|description|
|-|-|-|
|ucMode|unsigned char|[in] ucMode: 'E': EMV mode, 'S': Stop mode, 'H': Halt mode|
|ucSlot|unsigned char|card slot number, see PiccInfo_T|
### Retval
|Value|Type|Description|
|-|-|-|
|=0|int|success|
|<0|int|fail|
>i## PiccClose
### Prototype
`int PiccClose(void);`
### Function
* Close PICC module
### Parameter
|Name|Type|description|
|-|-|-|
|none|||
### Retval
|Value|Type|Description|
|-|-|-|
|=0|int|success|
|<0|int|fail|
>i## PiccSidTransceiveRev
### Prototype
`int PiccSidTransceiveRev(unsigned char* pucCmd, unsigned int uiCmdLen, unsigned char *pucRsp, unsigned int *puiRspLen);`
### Function
* PICC transparent transfer interface
### Parameter
|Name|Type|description|
|-|-|-|
|pucCmd|unsigned char *|Data to send|
|uiCmdLen|unsigned int|Length of Data to send|
|pucRsp|unsigned char *|Data received|
|puiRspLen|unsigned int *|Length of Data received|
### Retval
|Value|Type|Description|
|-|-|-|
|=0|int|success|
|<0|int|fail|
>i## Picc_Tag_Iso14443_TransparentMode
### Prototype
`int Picc_Tag_Iso14443_TransparentMode(unsigned char *pucCmd, unsigned int uiCmdLen, unsigned char *pucResp);`
### Function
* RF TAG card transparent transfer interface
### Parameter
|Name|Type|description|
|-|-|-|
|pucCmd|unsigned char *|TAG command|
|uiCmdLen|unsigned int|Length of TAG command|
|pucResp|unsigned char *|TAG response|
### Retval
|Value|Type|Description|
|-|-|-|
|>=0|int|success(Length of response)|
|<0|int|fail|
>i## Picc_Tag_Iso14443_PseudoAPDU
### Prototype
`int Picc_Tag_Iso14443_PseudoAPDU(unsigned char *pucCapdu, unsigned int uiCapduLen, unsigned char *pucRapdu, unsigned char *pucSW);`
### Function
* RF TAG card transparent transfer interface in APDU format
### Parameter
|Name|Type|description|
|-|-|-|
|pucCapdu|unsigned char *|[in] pucCapdu: C-APDU: CLA: 0x90, INS: TagCmd, P1: Ignored, P2: Ignored, P3: Lc|
|uiCapduLen|unsigned int|Length of C-APDU|
|pucRapdu|unsigned char *|R-APDU|
|pucSW|unsigned char *|Status-Word(2 bytes)|
### Retval
|Value|Type|Description|
|-|-|-|
|>=0|int|success(Length of response)|
|<0|int|fail|
>i## Picc_M1_KeyAuth_With_SN_Rev
### Prototype
`int Picc_M1_KeyAuth_With_SN_Rev(unsigned int keyType, unsigned int blockNo, unsigned int keyLen, unsigned char *pKey, int seriNoLen, unsigned char *pSeriNo);
;`
### Function
* M1 Authication with SN checked
### Parameter
|Name|Type|description|
|-|-|-|
|keyType|unsigned int|One of TAG_IDX_AUTH_KEYA and TAG_IDX_AUTH_KEYB|
|blockNo|unsigned int|Block number to authenticate|
|keyLen|unsigned int|Length of KEY|
|pKey|unsigned char *|KEY for authenticate|
|seriNoLen|int|Length of SN|
|pSeriNo|unsigned char *|SN of M1|
### Retval
|Value|Type|Description|
|-|-|-|
|=0|int|success|
|<0|int|fail|
>i## Picc_M1_KeyAuthRev
### Prototype
`int Picc_M1_KeyAuthRev(unsigned int keyType, unsigned int blockNo, unsigned int keyLen, unsigned char *pKey);`
### Function
* M1 Authication
### Parameter
|Name|Type|description|
|-|-|-|
|keyType|unsigned int|One of TAG_IDX_AUTH_KEYA and TAG_IDX_AUTH_KEYB|
|blockNo|unsigned int|Block number to authenticate|
|keyLen|unsigned int|Length of KEY|
|pKey|unsigned char *|KEY for authenticate|
### Retval
|Value|Type|Description|
|-|-|-|
|=0|int|success|
|<0|int|fail|
>i## Picc_M1_ReadBlockRev
### Prototype
`int Picc_M1_ReadBlockRev(unsigned int blockNo, unsigned char *pDataRead);`
### Function
* Read a block data from M1
### Parameter
|Name|Type|description|
|-|-|-|
|blockNo|unsigned int|Block to read|
|pDataRead|unsigned char *|Block data|
### Retval
|Value|Type|Description|
|-|-|-|
|>=0|int|success, Length of Data(will be TAG_M1_BLOCK_LEN)|
|<0|int|fail|
>i## Picc_M1_ReadValueRev
### Prototype
`int Picc_M1_ReadValueRev(unsigned int blkNo, int *piCents);`
### Function
* Read value of M1 block
### Parameter
|Name|Type|description|
|-|-|-|
|blkNo|unsigned int|Value block|
|piCents|int *|Value(unit: cent)|
### Retval
|Value|Type|Description|
|-|-|-|
|=0|int|success|
|<0|int|fail|
>i## Picc_M1_WriteBlockRev
### Prototype
`int Picc_M1_WriteBlockRev(unsigned int blkNo, unsigned int iDataWriteLen, unsigned char *pDataWrite);`
### Function
* Write a block data to M1
### Parameter
|Name|Type|description|
|-|-|-|
|blkNo|unsigned int|Block to write|
|iDataWriteLen|unsigned int|Length of data to write(Should be TAG_M1_BLOCK_LEN)|
|pDataWrite|unsigned char *|Data to write|
### Retval
|Value|Type|Description|
|-|-|-|
|=0|int|success|
|<0|int|fail|
>i## Picc_M1_InitValueRev
### Prototype
`int Picc_M1_InitValueRev(unsigned int blkNo, int iCents, unsigned char ucAdr);`
### Function
* Initial a value to block
### Parameter
|Name|Type|description|
|-|-|-|
|blkNo|unsigned int|Block to initial a value|
|iCents|int|Value(unit: cent)|
|ucAdr|unsigned char|A check byte of value block(Generally, it's the block number the value in)|
### Retval
|Value|Type|Description|
|-|-|-|
|=0|int|success|
|<0|int|fail|
>i## Picc_M1_IncrementRev
### Prototype
`int Picc_M1_IncrementRev(unsigned int blkNoSrc, unsigned int blkNoDst, unsigned int uiCentsInc);`
### Function
* Increase value to M1
### Parameter
|Name|Type|description|
|-|-|-|
|blkNoSrc|unsigned int|The source value block|
|blkNoDst|unsigned int|The destination value block|
|uiCentsInc|unsigned int|Cents to increase|
### Retval
|Value|Type|Description|
|-|-|-|
|=0|int|success|
|<0|int|fail|
>i## Picc_M1_DecrementRev
### Prototype
`int Picc_M1_DecrementRev(unsigned int blkNoSrc, unsigned int blkNoDst, unsigned int uiCentsDec);`
### Function
* Decrease value to M1
### Parameter
|Name|Type|description|
|-|-|-|
|blkNoSrc|unsigned int|The source value block|
|blkNoDst|unsigned int|The destination value block|
|uiCentsDec|unsigned int|Cents to decrease|
### Retval
|Value|Type|Description|
|-|-|-|
|=0|int|success|
|<0|int|fail|
>i## Picc_M1_RestoreRev
### Prototype
`int Picc_M1_RestoreRev(unsigned int blkNoSrc, unsigned int blkNoDst);`
### Function
* Restore a value block
### Parameter
|Name|Type|description|
|-|-|-|
|blkNoSrc|unsigned int|The source value block|
|blkNoDst|unsigned int|The destination value block|
### Retval
|Value|Type|Description|
|-|-|-|
|=0|int|success|
|<0|int|fail|
>s## Example
```
/**
* @brief test M1 card
* @param result [out] test result string
* @param judge_style [out] result notice type,for example:BWUI_SMT_JUDGE_STYLE_PASS_ENTER
*/
void bwui_smt_test_mifare_classic_fun(char *result, char *judge_style)
{
char type;
int iRet;
unsigned int uiStrLen;
int iBlkNoSrc;
int iBlkNoDst;
int iKeyLen;
int iCents;
unsigned char aucKey[6];
char acSN[24];
char acInfo[100];
char acValue[20];
T_SOFTTIMER tm;
PiccInfo_T stPiccInfo;
iRet = PiccOpen();
if(iRet != 0){
snprintf(result, MAX_RESULT_STR_LEN, "picc open fail");
*judge_style = BWUI_SMT_JUDGE_STYLE_FAIL_ENTER;
return ;
}
// Detect
s_TimerSet(&tm, 5000);
while (s_TimerCheck(&tm)) {
iRet = PiccDetect('M', &stPiccInfo);
if (iRet == 0) {
break;
}
Sleep(100);
}
if (iRet != 0) {
snprintf(result, MAX_RESULT_STR_LEN, "read card fail\n");
*judge_style = BWUI_SMT_JUDGE_STYLE_FAIL_ENTER;
PiccClose();
return;
}
type = stPiccInfo.ucPiccCardType;
uiStrLen = (2*stPiccInfo.ucPiccSnLen + 1);
BytesToHexString((const char*)stPiccInfo.aucPiccSN, stPiccInfo.ucPiccSnLen, acSN, &uiStrLen);
uiStrLen = (2*stPiccInfo.ucPiccInfoLen + 1);
BytesToHexString((const char*)stPiccInfo.aucPiccInfo, stPiccInfo.ucPiccInfoLen, acInfo, &uiStrLen);
// Authenticate
iBlkNoSrc = 0x04;
iKeyLen = TAG_M1_KEY_LEN;
memset(aucKey, 0xFF, iKeyLen);
iRet = Picc_M1_KeyAuthRev(TAG_IDX_AUTH_KEYA, iBlkNoSrc, iKeyLen, aucKey);
//LOGD("Picc_M1_KeyAuth, iRet=%d", iRet);
if (iRet != 0) {
snprintf(result, MAX_RESULT_STR_LEN, "auth pwd fail\n");
*judge_style = BWUI_SMT_JUDGE_STYLE_FAIL_ENTER;
PiccClose();
return;
}
// Init Value Blk=4
iBlkNoSrc = 0x04;
// Write 12345.67
iRet = Picc_M1_InitValueRev(iBlkNoSrc, 1234567, iBlkNoSrc);
//LOGD("Picc_M1_InitValue, iRet=%d, blk=%d ", iRet, iBlkNoSrc);
if (iRet != 0) {
snprintf(result, MAX_RESULT_STR_LEN, "init amount fail\n");
*judge_style = BWUI_SMT_JUDGE_STYLE_FAIL_ENTER;
PiccClose();
return;
}
// Read Value Blk=4
iBlkNoSrc = 0x04;
iRet = Picc_M1_ReadValueRev(iBlkNoSrc, &iCents);
//LOGD("Picc_M1_ReadValue, iRet=%d, blk=%d, iCents=%d ", iRet, iBlkNoSrc, iCents);
if (iRet != 0) {
snprintf(result, MAX_RESULT_STR_LEN, "read amount fail\n");
*judge_style = BWUI_SMT_JUDGE_STYLE_FAIL_ENTER;
PiccClose();
return;
}
// Increment Blk= 4->5
iBlkNoSrc = 0x04;
iBlkNoDst = 0x05;
iRet = Picc_M1_IncrementRev(iBlkNoSrc, iBlkNoDst, 1);
//LOGD("Picc_M1_Increment, iRet=%d, src=%d, dst=%d ", iRet, iBlkNoSrc, iBlkNoDst);
if (iRet != 0) {
snprintf(result, MAX_RESULT_STR_LEN, "read data fail\n");
*judge_style = BWUI_SMT_JUDGE_STYLE_FAIL_ENTER;
PiccClose();
return;
}
// Read Value Blk=5
iBlkNoSrc = 0x05;
iRet = Picc_M1_ReadValueRev(iBlkNoSrc, &iCents);
//LOGD("Picc_M1_ReadValue, iRet=%d, blk=%d, iCents=%d ", iRet, iBlkNoSrc, iCents);
if (iRet != 0) {
snprintf(result, MAX_RESULT_STR_LEN, "read amount fail\n");
*judge_style = BWUI_SMT_JUDGE_STYLE_FAIL_ENTER;
PiccClose();
return;
}
// Decrement Blk= 4->6
iBlkNoSrc = 0x04;
iBlkNoDst = 0x06;
iRet = Picc_M1_DecrementRev(iBlkNoSrc, iBlkNoDst, 1);
//LOGD("Picc_M1_Decrement, iRet=%d, src=%d, dst=%d ", iRet, iBlkNoSrc, iBlkNoDst);
if (iRet != 0) {
snprintf(result, MAX_RESULT_STR_LEN, "read data fail\n");
*judge_style = BWUI_SMT_JUDGE_STYLE_FAIL_ENTER;
PiccClose();
return;
}
// Read Value Blk=6
iBlkNoSrc = 0x06;
iRet = Picc_M1_ReadValueRev(iBlkNoSrc, &iCents);
//LOGD("Picc_M1_ReadValue, iRet=%d, blk=%d, iCents=%d ", iRet, iBlkNoSrc, iCents);
if (iRet != 0) {
snprintf(result, MAX_RESULT_STR_LEN, "read amount fail\n");
*judge_style = BWUI_SMT_JUDGE_STYLE_FAIL_ENTER;
PiccClose();
return;
}
// Restore Blk= 4->4
iBlkNoSrc = 0x04;
iBlkNoDst = 0x04;
iRet = Picc_M1_RestoreRev(iBlkNoSrc, iBlkNoDst);
//LOGD("Picc_M1_Restore, iRet=%d, src=%d, dst=%d ", iRet, iBlkNoSrc, iBlkNoDst);
if (iRet != 0) {
*judge_style = BWUI_SMT_JUDGE_STYLE_FAIL_ENTER;
PiccClose();
return;
}
// Read Value Blk=4
iBlkNoSrc = 0x04;
iRet = Picc_M1_ReadValueRev(iBlkNoSrc, &iCents);
//LOGD("Picc_M1_ReadValue, iRet=%d, blk=%d, iCents=%d ", iRet, iBlkNoSrc, iCents);
if (iRet != 0) {
snprintf(result, MAX_RESULT_STR_LEN, "read amount fail\n");
*judge_style = BWUI_SMT_JUDGE_STYLE_FAIL_ENTER;
PiccClose();
return;
}
PiccClose();
sprintf(acValue, "%.2f", ((float)iCents)/100);
iRet = 0;
iRet = snprintf(result, MAX_RESULT_STR_LEN-iRet, "read card success\n");
iRet = snprintf(&result[iRet], MAX_RESULT_STR_LEN-iRet,
"Type:%c, SN:%s\nInfo:%s\namount=%s\n", type, acSN, acInfo, acValue);
*judge_style = BWUI_SMT_JUDGE_STYLE_PASS_ENTER;
}
```