diff --git a/firmware/application/src/app_cmd.c b/firmware/application/src/app_cmd.c index 26793fe8..4c71b21c 100644 --- a/firmware/application/src/app_cmd.c +++ b/firmware/application/src/app_cmd.c @@ -179,129 +179,129 @@ data_frame_tx_t* cmd_processor_detect_mf1_darkside(uint16_t cmd, uint16_t status data_frame_tx_t* cmd_processor_mf1_darkside_acquire(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) { DarksideCore dc; - if (length == 4) { - status = Darkside_Recover_Key(data[1], data[0], data[2], data[3], &dc); - if (status == HF_TAG_OK) { - length = sizeof(DarksideCore); - data = (uint8_t *)(&dc); - } else { - length = 0; - } - } else { - status = STATUS_PAR_ERR; - length = 0; - } + if (length == 4) { + status = Darkside_Recover_Key(data[1], data[0], data[2], data[3], &dc); + if (status == HF_TAG_OK) { + length = sizeof(DarksideCore); + data = (uint8_t *)(&dc); + } else { + length = 0; + } + } else { + status = STATUS_PAR_ERR; + length = 0; + } return data_frame_make(cmd, status, length, data); } data_frame_tx_t* cmd_processor_detect_nested_dist(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) { NestedDist nd; - if (length == 8) { - status = Nested_Distacne_Detect(data[1], data[0], &data[2], &nd); - if (status == HF_TAG_OK) { - length = sizeof(NestedDist); - data = (uint8_t *)(&nd); - } else { - length = 0; - } - } else { - status = STATUS_PAR_ERR; - length = 0; - } + if (length == 8) { + status = Nested_Distacne_Detect(data[1], data[0], &data[2], &nd); + if (status == HF_TAG_OK) { + length = sizeof(NestedDist); + data = (uint8_t *)(&nd); + } else { + length = 0; + } + } else { + status = STATUS_PAR_ERR; + length = 0; + } return data_frame_make(cmd, status, 0, NULL); } data_frame_tx_t* cmd_processor_mf1_nt_distance(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) { NestedDist nd; - if (length == 8) { - status = Nested_Distacne_Detect(data[1], data[0], &data[2], &nd); - if (status == HF_TAG_OK) { - length = sizeof(NestedDist); - data = (uint8_t *)(&nd); - } else { - length = 0; - } - } else { - status = STATUS_PAR_ERR; - length = 0; - } + if (length == 8) { + status = Nested_Distacne_Detect(data[1], data[0], &data[2], &nd); + if (status == HF_TAG_OK) { + length = sizeof(NestedDist); + data = (uint8_t *)(&nd); + } else { + length = 0; + } + } else { + status = STATUS_PAR_ERR; + length = 0; + } return data_frame_make(cmd, status, length, data); } data_frame_tx_t* cmd_processor_mf1_nested_acquire(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) { NestedCore ncs[SETS_NR]; - if (length == 10) { - status = Nested_Recover_Key(bytes_to_num(&data[2], 6), data[1], data[0], data[9], data[8], ncs); - if (status == HF_TAG_OK) { - length = sizeof(ncs); - data = (uint8_t *)(&ncs); - } else { - length = 0; - } - } else { - status = STATUS_PAR_ERR; - length = 0; - } + if (length == 10) { + status = Nested_Recover_Key(bytes_to_num(&data[2], 6), data[1], data[0], data[9], data[8], ncs); + if (status == HF_TAG_OK) { + length = sizeof(ncs); + data = (uint8_t *)(&ncs); + } else { + length = 0; + } + } else { + status = STATUS_PAR_ERR; + length = 0; + } return data_frame_make(cmd, status, length, data); } data_frame_tx_t* cmd_processor_mf1_auth_one_key_block(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) { if (length == 8) { - status = auth_key_use_522_hw(data[1], data[0], &data[2]); + status = auth_key_use_522_hw(data[1], data[0], &data[2]); pcd_14a_reader_mf1_unauth(); - } else { - status = STATUS_PAR_ERR; - } + } else { + status = STATUS_PAR_ERR; + } return data_frame_make(cmd, status, 0, NULL); } data_frame_tx_t* cmd_processor_mf1_read_one_block(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) { uint8_t block[16] = { 0x00 }; - if (length == 8) { - status = auth_key_use_522_hw(data[1], data[0], &data[2]); - if (status == HF_TAG_OK) { - status = pcd_14a_reader_mf1_read(data[1], block); - if (status == HF_TAG_OK) { - length = 16; - } else { - length = 0; - } - } else { - length = 0; - } - } else { - length = 0; - status = STATUS_PAR_ERR; - } + if (length == 8) { + status = auth_key_use_522_hw(data[1], data[0], &data[2]); + if (status == HF_TAG_OK) { + status = pcd_14a_reader_mf1_read(data[1], block); + if (status == HF_TAG_OK) { + length = 16; + } else { + length = 0; + } + } else { + length = 0; + } + } else { + length = 0; + status = STATUS_PAR_ERR; + } return data_frame_make(cmd, status, length, block); } data_frame_tx_t* cmd_processor_mf1_write_one_block(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) { if (length == 24) { - status = auth_key_use_522_hw(data[1], data[0], &data[2]); - if (status == HF_TAG_OK) { - status = pcd_14a_reader_mf1_write(data[1], &data[8]); - } else { - length = 0; - } - } else { - status = STATUS_PAR_ERR; - } + status = auth_key_use_522_hw(data[1], data[0], &data[2]); + if (status == HF_TAG_OK) { + status = pcd_14a_reader_mf1_write(data[1], &data[8]); + } else { + length = 0; + } + } else { + status = STATUS_PAR_ERR; + } return data_frame_make(cmd, status, 0, NULL); } data_frame_tx_t* cmd_processor_em410x_scan(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) { uint8_t id_buffer[5] = { 0x00 }; - status = PcdScanEM410X(id_buffer); + status = PcdScanEM410X(id_buffer); return data_frame_make(cmd, status, sizeof(id_buffer), id_buffer); } data_frame_tx_t* cmd_processor_write_em410x_2_t57(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) { - if (length >= 13 && (length - 9) % 4 == 0) { - status = PcdWriteT55XX(data, data + 5, data + 9, (length - 9) / 4); - } else { - status = STATUS_PAR_ERR; - } + if (length >= 13 && (length - 9) % 4 == 0) { + status = PcdWriteT55XX(data, data + 5, data + 9, (length - 9) / 4); + } else { + status = STATUS_PAR_ERR; + } return data_frame_make(cmd, status, 0, NULL); } @@ -319,7 +319,7 @@ data_frame_tx_t* cmd_processor_set_slot_activated(uint16_t cmd, uint16_t status, if (length == 1 && data[0] < TAG_MAX_SLOT_NUM) { change_slot_auto(data[0]); status = STATUS_DEVICE_SUCCESS; - } else { + } else { status = STATUS_PAR_ERR; } return data_frame_make(cmd, status, 0, NULL); @@ -330,8 +330,8 @@ data_frame_tx_t* cmd_processor_set_slot_tag_type(uint16_t cmd, uint16_t status, uint8_t num_slot = data[0]; uint8_t tag_type = data[1]; tag_emulation_change_type(num_slot, (tag_specific_type_t)tag_type); - status = STATUS_DEVICE_SUCCESS; - } else { + status = STATUS_DEVICE_SUCCESS; + } else { status = STATUS_PAR_ERR; } return data_frame_make(cmd, status, 0, NULL); @@ -354,7 +354,7 @@ data_frame_tx_t* cmd_processor_set_slot_data_default(uint16_t cmd, uint16_t stat uint8_t num_slot = data[0]; uint8_t tag_type = data[1]; status = tag_emulation_factory_data(num_slot, (tag_specific_type_t)tag_type) ? STATUS_DEVICE_SUCCESS : STATUS_NOT_IMPLEMENTED; - } else { + } else { status = STATUS_PAR_ERR; } return data_frame_make(cmd, status, 0, NULL); @@ -375,7 +375,7 @@ data_frame_tx_t* cmd_processor_set_slot_enable(uint16_t cmd, uint16_t status, ui } } status = STATUS_DEVICE_SUCCESS; - } else { + } else { status = STATUS_PAR_ERR; } return data_frame_make(cmd, status, 0, NULL); @@ -416,7 +416,7 @@ data_frame_tx_t* cmd_processor_set_em410x_emu_id(uint16_t cmd, uint16_t status, memcpy(buffer->buffer, data, LF_EM410X_TAG_ID_SIZE); tag_emulation_load_by_buffer(TAG_TYPE_EM410X, false); status = STATUS_DEVICE_SUCCESS; - } else { + } else { status = STATUS_PAR_ERR; } return data_frame_make(cmd, status, 0, NULL); @@ -435,7 +435,7 @@ data_frame_tx_t* cmd_processor_set_mf1_detection_enable(uint16_t cmd, uint16_t s nfc_tag_mf1_detection_log_clear(); nfc_tag_mf1_set_detection_enable(data[0]); status = STATUS_DEVICE_SUCCESS; - } else { + } else { status = STATUS_PAR_ERR; } return data_frame_make(cmd, status, 0, NULL); @@ -640,7 +640,7 @@ data_frame_tx_t* cmd_processor_set_mf1_gen1a_magic_mode(uint16_t cmd, uint16_t s if (length == 1 && (data[0] == 0 || data[0] == 1)) { nfc_tag_mf1_set_gen1a_magic_mode(data[0]); status = STATUS_DEVICE_SUCCESS; - } else { + } else { status = STATUS_PAR_ERR; } return data_frame_make(cmd, status, 0, NULL); @@ -659,7 +659,7 @@ data_frame_tx_t* cmd_processor_set_mf1_gen2_magic_mode(uint16_t cmd, uint16_t st if (length == 1 && (data[0] == 0 || data[0] == 1)) { nfc_tag_mf1_set_gen2_magic_mode(data[0]); status = STATUS_DEVICE_SUCCESS; - } else { + } else { status = STATUS_PAR_ERR; } return data_frame_make(cmd, status, 0, NULL); @@ -678,7 +678,7 @@ data_frame_tx_t* cmd_processor_set_mf1_use_coll_res(uint16_t cmd, uint16_t statu if (length == 1 && (data[0] == 0 || data[0] == 1)) { nfc_tag_mf1_set_use_mf1_coll_res(data[0]); status = STATUS_DEVICE_SUCCESS; - } else { + } else { status = STATUS_PAR_ERR; } return data_frame_make(cmd, status, 0, NULL); @@ -711,7 +711,7 @@ data_frame_tx_t* cmd_processor_set_mf1_write_mode(uint16_t cmd, uint16_t status, nfc_tag_mf1_set_write_mode(NFC_TAG_MF1_WRITE_SHADOW); } status = STATUS_DEVICE_SUCCESS; - } else { + } else { status = STATUS_PAR_ERR; } return data_frame_make(cmd, status, 0, NULL); @@ -851,15 +851,15 @@ static cmd_data_map_t m_data_cmd_map[] = { * @param resp data */ void auto_response_data(data_frame_tx_t* resp) { - // TODO Please select the reply source automatically according to the message source, + // TODO Please select the reply source automatically according to the message source, // and do not reply by checking the validity of the link layer by layer - if (is_usb_working()) { - usb_cdc_write(resp->buffer, resp->length); - } else if (is_nus_working()) { - nus_data_reponse(resp->buffer, resp->length); - } else { - NRF_LOG_ERROR("No connection valid found at response client."); - } + if (is_usb_working()) { + usb_cdc_write(resp->buffer, resp->length); + } else if (is_nus_working()) { + nus_data_reponse(resp->buffer, resp->length); + } else { + NRF_LOG_ERROR("No connection valid found at response client."); + } } diff --git a/firmware/application/src/app_main.c b/firmware/application/src/app_main.c index 6169e606..1e6485e6 100644 --- a/firmware/application/src/app_main.c +++ b/firmware/application/src/app_main.c @@ -494,11 +494,11 @@ static void offline_status_blink_color(uint8_t blink_color) { } static void offline_status_error(void) { - offline_status_blink_color(0); + offline_status_blink_color(0); } static void offline_status_ok(void) { - offline_status_blink_color(1); + offline_status_blink_color(1); } // fast detect a 14a tag uid to sim diff --git a/firmware/application/src/app_status.h b/firmware/application/src/app_status.h index 3debcf8e..aef73d91 100644 --- a/firmware/application/src/app_status.h +++ b/firmware/application/src/app_status.h @@ -5,38 +5,38 @@ ///////////////////////////////////////////////////////////////////// // 14a status ///////////////////////////////////////////////////////////////////// -#define HF_TAG_OK (0x00) // IC卡操作成功 -#define HF_TAG_NO (0x01) // 没有发现IC卡 -#define HF_ERRSTAT (0x02) // IC卡通信异常 -#define HF_ERRCRC (0x03) // IC卡通信校验异常 -#define HF_COLLISION (0x04) // IC卡冲突 -#define HF_ERRBCC (0x05) // IC卡BCC错误 -#define MF_ERRAUTH (0x06) // MF卡验证失败 -#define HF_ERRPARITY (0x07) // IC卡奇偶校验错误 +#define HF_TAG_OK (0x00) // IC卡操作成功 +#define HF_TAG_NO (0x01) // 没有发现IC卡 +#define HF_ERRSTAT (0x02) // IC卡通信异常 +#define HF_ERRCRC (0x03) // IC卡通信校验异常 +#define HF_COLLISION (0x04) // IC卡冲突 +#define HF_ERRBCC (0x05) // IC卡BCC错误 +#define MF_ERRAUTH (0x06) // MF卡验证失败 +#define HF_ERRPARITY (0x07) // IC卡奇偶校验错误 ///////////////////////////////////////////////////////////////////// // MIFARE status ///////////////////////////////////////////////////////////////////// -#define DARKSIDE_CANT_FIXED_NT (0x20) // Darkside,无法固定随机数,这个情况可能出现在UID卡上 -#define DARKSIDE_LUCK_AUTH_OK (0x21) // Darkside,直接验证成功了,可能刚好密钥是空的 -#define DARKSIDE_NACK_NO_SEND (0x22) // Darkside,卡片不响应nack,可能是一张修复了nack逻辑漏洞的卡片 -#define DARKSIDE_TAG_CHANGED (0x23) // Darkside,在运行darkside的过程中出现了卡片切换,可能信号问题,或者真的是两张卡迅速切换了 -#define NESTED_TAG_IS_STATIC (0x24) // Nested,检测到卡片应答的随机数是固定的 -#define NESTED_TAG_IS_HARD (0x25) // Nested,检测到卡片应答的随机数是不可预测的 +#define DARKSIDE_CANT_FIXED_NT (0x20) // Darkside,无法固定随机数,这个情况可能出现在UID卡上 +#define DARKSIDE_LUCK_AUTH_OK (0x21) // Darkside,直接验证成功了,可能刚好密钥是空的 +#define DARKSIDE_NACK_NO_SEND (0x22) // Darkside,卡片不响应nack,可能是一张修复了nack逻辑漏洞的卡片 +#define DARKSIDE_TAG_CHANGED (0x23) // Darkside,在运行darkside的过程中出现了卡片切换,可能信号问题,或者真的是两张卡迅速切换了 +#define NESTED_TAG_IS_STATIC (0x24) // Nested,检测到卡片应答的随机数是固定的 +#define NESTED_TAG_IS_HARD (0x25) // Nested,检测到卡片应答的随机数是不可预测的 ///////////////////////////////////////////////////////////////////// // lf status ///////////////////////////////////////////////////////////////////// -#define LF_TAG_OK (0x40) // 低频卡的一些操作成功! -#define EM410X_TAG_NO_FOUND (0x41) // 无法搜索到有效的EM410X标签 +#define LF_TAG_OK (0x40) // 低频卡的一些操作成功! +#define EM410X_TAG_NO_FOUND (0x41) // 无法搜索到有效的EM410X标签 ///////////////////////////////////////////////////////////////////// // other status ///////////////////////////////////////////////////////////////////// -#define STATUS_PAR_ERR (0x60) // BLE指令传递的参数错误,或者是调用某些函数传递的参数错误 +#define STATUS_PAR_ERR (0x60) // BLE指令传递的参数错误,或者是调用某些函数传递的参数错误 #define STATUS_DEVIEC_MODE_ERROR (0x66) // 当前设备所处的模式错误,无法调用对应的API #define STATUS_INVALID_CMD (0x67) // 无效的指令 #define STATUS_DEVICE_SUCCESS (0x68) // 设备相关操作成功执行 diff --git a/firmware/application/src/ble_main.c b/firmware/application/src/ble_main.c index 66cae129..acb74e3f 100644 --- a/firmware/application/src/ble_main.c +++ b/firmware/application/src/ble_main.c @@ -193,81 +193,81 @@ static void nrf_qwr_error_handler(uint32_t nrf_error) __INLINE uint32_t map(uint32_t x, uint32_t in_min, uint32_t in_max, uint32_t out_min, uint32_t out_max) { - return (uint32_t)((x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min); + return (uint32_t)((x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min); } //电池电压到百分比计算 uint32_t BATVOL2PERCENT(uint16_t VOL) { - //100% 4.20V 1 - //90 % 4.06V 80%-100% 白 - //80 % 3.98V 1 - //70 % 3.92V 60%-80% 白 - //60 % 3.87V 1 - //50 % 3.82V 40%-60% 白 - //40 % 3.79V 1 - //30 % 3.77V 20%-40% 白 - //20 % 3.74V 1 - //10 % 3.68V 5%-20% 红 - //5 % 3.45V 1 关机 - //0 % 3.00V - //#define P100VOL 4200 - //#define P80VOL 3980 - //#define P60VOL 3870 - //#define P40VOL 3790 - //#define P20VOL 3740 - //#define P5VOL 3450 - - //100% 4.20V 1 - //90 % 4.00V 80%-100% 白 - //80 % 3.89V 1 - //70 % 3.79V 60%-80% 白 - //60 % 3.70V 1 - //50 % 3.62V 40%-60% 白 - //40 % 3.57V 1 - //30 % 3.53V 20%-40% 白 - //20 % 3.51V 1 - //10 % 3.46V 5%-20% 红 - //5 % 3.43V 1 关机 - //0 % 3.00V -#define P100VOL 4200 -#define P80VOL 3890 -#define P60VOL 3700 -#define P40VOL 3570 -#define P20VOL 3510 -#define P5VOL 3230 - - - if(VOL > P80VOL) - { - //80-100 - return map(VOL, P80VOL, P100VOL, 80, 100); - } - else if(VOL > P60VOL) - { - //60-80 - return map(VOL, P60VOL, P80VOL, 60, 80); - } - else if(VOL > P40VOL) - { - //40-60 - return map(VOL, P40VOL, P60VOL, 40, 60); - } - else if(VOL > P20VOL) - { - //20-60 - return map(VOL, P20VOL, P40VOL, 20, 40); - } - else if(VOL > P5VOL) - { - //5-20 - return map(VOL, P5VOL, P20VOL, 5, 20); - } - else - { - //<5 - return 0; - } + //100% 4.20V 1 + //90 % 4.06V 80%-100% 白 + //80 % 3.98V 1 + //70 % 3.92V 60%-80% 白 + //60 % 3.87V 1 + //50 % 3.82V 40%-60% 白 + //40 % 3.79V 1 + //30 % 3.77V 20%-40% 白 + //20 % 3.74V 1 + //10 % 3.68V 5%-20% 红 + //5 % 3.45V 1 关机 + //0 % 3.00V + //#define P100VOL 4200 + //#define P80VOL 3980 + //#define P60VOL 3870 + //#define P40VOL 3790 + //#define P20VOL 3740 + //#define P5VOL 3450 + + //100% 4.20V 1 + //90 % 4.00V 80%-100% 白 + //80 % 3.89V 1 + //70 % 3.79V 60%-80% 白 + //60 % 3.70V 1 + //50 % 3.62V 40%-60% 白 + //40 % 3.57V 1 + //30 % 3.53V 20%-40% 白 + //20 % 3.51V 1 + //10 % 3.46V 5%-20% 红 + //5 % 3.43V 1 关机 + //0 % 3.00V +#define P100VOL 4200 +#define P80VOL 3890 +#define P60VOL 3700 +#define P40VOL 3570 +#define P20VOL 3510 +#define P5VOL 3230 + + + if(VOL > P80VOL) + { + //80-100 + return map(VOL, P80VOL, P100VOL, 80, 100); + } + else if(VOL > P60VOL) + { + //60-80 + return map(VOL, P60VOL, P80VOL, 60, 80); + } + else if(VOL > P40VOL) + { + //40-60 + return map(VOL, P40VOL, P60VOL, 40, 60); + } + else if(VOL > P20VOL) + { + //20-60 + return map(VOL, P20VOL, P40VOL, 20, 40); + } + else if(VOL > P5VOL) + { + //5-20 + return map(VOL, P5VOL, P20VOL, 5, 20); + } + else + { + //<5 + return 0; + } } /**@brief Function for initializing services that will be used by the application. diff --git a/firmware/application/src/bsp/bsp_delay.c b/firmware/application/src/bsp/bsp_delay.c index 63b68cd8..9ef15550 100644 --- a/firmware/application/src/bsp/bsp_delay.c +++ b/firmware/application/src/bsp/bsp_delay.c @@ -12,12 +12,12 @@ void bsp_delay_init(void) //注意nms的范围 void bsp_delay_ms(uint16_t nms) { - nrf_delay_us(nms * 1000); + nrf_delay_us(nms * 1000); } //延时nus //nus为要延时的us数. void bsp_delay_us(uint32_t nus) { - nrf_delay_us(nus); + nrf_delay_us(nus); } diff --git a/firmware/application/src/bsp/bsp_time.c b/firmware/application/src/bsp/bsp_time.c index fd6ce218..67da3395 100644 --- a/firmware/application/src/bsp/bsp_time.c +++ b/firmware/application/src/bsp/bsp_time.c @@ -31,7 +31,7 @@ autotimer* bsp_obtain_timer(uint32_t start_value) { if (bsptimers[i].busy == 0) { bsptimers[i].time = start_value; bsptimers[i].busy = 1; - break; + break; } } return &bsptimers[i]; diff --git a/firmware/application/src/rfid/crc_utils.c b/firmware/application/src/rfid/crc_utils.c index b8a4b1bd..33e9f331 100644 --- a/firmware/application/src/rfid/crc_utils.c +++ b/firmware/application/src/rfid/crc_utils.c @@ -2,38 +2,38 @@ // CRC查表 static uint16_t crc_table[256] = { - 0x0000,0x1189,0x2312,0x329B,0x4624,0x57AD,0x6536,0x74BF, - 0x8C48,0x9DC1,0xAF5A,0xBED3,0xCA6C,0xDBE5,0xE97E,0xF8F7, - 0x1081,0x0108,0x3393,0x221A,0x56A5,0x472C,0x75B7,0x643E, - 0x9CC9,0x8D40,0xBFDB,0xAE52,0xDAED,0xCB64,0xF9FF,0xE876, - 0x2102,0x308B,0x0210,0x1399,0x6726,0x76AF,0x4434,0x55BD, - 0xAD4A,0xBCC3,0x8E58,0x9FD1,0xEB6E,0xFAE7,0xC87C,0xD9F5, - 0x3183,0x200A,0x1291,0x0318,0x77A7,0x662E,0x54B5,0x453C, - 0xBDCB,0xAC42,0x9ED9,0x8F50,0xFBEF,0xEA66,0xD8FD,0xC974, - 0x4204,0x538D,0x6116,0x709F,0x0420,0x15A9,0x2732,0x36BB, - 0xCE4C,0xDFC5,0xED5E,0xFCD7,0x8868,0x99E1,0xAB7A,0xBAF3, - 0x5285,0x430C,0x7197,0x601E,0x14A1,0x0528,0x37B3,0x263A, - 0xDECD,0xCF44,0xFDDF,0xEC56,0x98E9,0x8960,0xBBFB,0xAA72, - 0x6306,0x728F,0x4014,0x519D,0x2522,0x34AB,0x0630,0x17B9, - 0xEF4E,0xFEC7,0xCC5C,0xDDD5,0xA96A,0xB8E3,0x8A78,0x9BF1, - 0x7387,0x620E,0x5095,0x411C,0x35A3,0x242A,0x16B1,0x0738, - 0xFFCF,0xEE46,0xDCDD,0xCD54,0xB9EB,0xA862,0x9AF9,0x8B70, - 0x8408,0x9581,0xA71A,0xB693,0xC22C,0xD3A5,0xE13E,0xF0B7, - 0x0840,0x19C9,0x2B52,0x3ADB,0x4E64,0x5FED,0x6D76,0x7CFF, - 0x9489,0x8500,0xB79B,0xA612,0xD2AD,0xC324,0xF1BF,0xE036, - 0x18C1,0x0948,0x3BD3,0x2A5A,0x5EE5,0x4F6C,0x7DF7,0x6C7E, - 0xA50A,0xB483,0x8618,0x9791,0xE32E,0xF2A7,0xC03C,0xD1B5, - 0x2942,0x38CB,0x0A50,0x1BD9,0x6F66,0x7EEF,0x4C74,0x5DFD, - 0xB58B,0xA402,0x9699,0x8710,0xF3AF,0xE226,0xD0BD,0xC134, - 0x39C3,0x284A,0x1AD1,0x0B58,0x7FE7,0x6E6E,0x5CF5,0x4D7C, - 0xC60C,0xD785,0xE51E,0xF497,0x8028,0x91A1,0xA33A,0xB2B3, - 0x4A44,0x5BCD,0x6956,0x78DF,0x0C60,0x1DE9,0x2F72,0x3EFB, - 0xD68D,0xC704,0xF59F,0xE416,0x90A9,0x8120,0xB3BB,0xA232, - 0x5AC5,0x4B4C,0x79D7,0x685E,0x1CE1,0x0D68,0x3FF3,0x2E7A, - 0xE70E,0xF687,0xC41C,0xD595,0xA12A,0xB0A3,0x8238,0x93B1, - 0x6B46,0x7ACF,0x4854,0x59DD,0x2D62,0x3CEB,0x0E70,0x1FF9, - 0xF78F,0xE606,0xD49D,0xC514,0xB1AB,0xA022,0x92B9,0x8330, - 0x7BC7,0x6A4E,0x58D5,0x495C,0x3DE3,0x2C6A,0x1EF1,0x0F78, + 0x0000,0x1189,0x2312,0x329B,0x4624,0x57AD,0x6536,0x74BF, + 0x8C48,0x9DC1,0xAF5A,0xBED3,0xCA6C,0xDBE5,0xE97E,0xF8F7, + 0x1081,0x0108,0x3393,0x221A,0x56A5,0x472C,0x75B7,0x643E, + 0x9CC9,0x8D40,0xBFDB,0xAE52,0xDAED,0xCB64,0xF9FF,0xE876, + 0x2102,0x308B,0x0210,0x1399,0x6726,0x76AF,0x4434,0x55BD, + 0xAD4A,0xBCC3,0x8E58,0x9FD1,0xEB6E,0xFAE7,0xC87C,0xD9F5, + 0x3183,0x200A,0x1291,0x0318,0x77A7,0x662E,0x54B5,0x453C, + 0xBDCB,0xAC42,0x9ED9,0x8F50,0xFBEF,0xEA66,0xD8FD,0xC974, + 0x4204,0x538D,0x6116,0x709F,0x0420,0x15A9,0x2732,0x36BB, + 0xCE4C,0xDFC5,0xED5E,0xFCD7,0x8868,0x99E1,0xAB7A,0xBAF3, + 0x5285,0x430C,0x7197,0x601E,0x14A1,0x0528,0x37B3,0x263A, + 0xDECD,0xCF44,0xFDDF,0xEC56,0x98E9,0x8960,0xBBFB,0xAA72, + 0x6306,0x728F,0x4014,0x519D,0x2522,0x34AB,0x0630,0x17B9, + 0xEF4E,0xFEC7,0xCC5C,0xDDD5,0xA96A,0xB8E3,0x8A78,0x9BF1, + 0x7387,0x620E,0x5095,0x411C,0x35A3,0x242A,0x16B1,0x0738, + 0xFFCF,0xEE46,0xDCDD,0xCD54,0xB9EB,0xA862,0x9AF9,0x8B70, + 0x8408,0x9581,0xA71A,0xB693,0xC22C,0xD3A5,0xE13E,0xF0B7, + 0x0840,0x19C9,0x2B52,0x3ADB,0x4E64,0x5FED,0x6D76,0x7CFF, + 0x9489,0x8500,0xB79B,0xA612,0xD2AD,0xC324,0xF1BF,0xE036, + 0x18C1,0x0948,0x3BD3,0x2A5A,0x5EE5,0x4F6C,0x7DF7,0x6C7E, + 0xA50A,0xB483,0x8618,0x9791,0xE32E,0xF2A7,0xC03C,0xD1B5, + 0x2942,0x38CB,0x0A50,0x1BD9,0x6F66,0x7EEF,0x4C74,0x5DFD, + 0xB58B,0xA402,0x9699,0x8710,0xF3AF,0xE226,0xD0BD,0xC134, + 0x39C3,0x284A,0x1AD1,0x0B58,0x7FE7,0x6E6E,0x5CF5,0x4D7C, + 0xC60C,0xD785,0xE51E,0xF497,0x8028,0x91A1,0xA33A,0xB2B3, + 0x4A44,0x5BCD,0x6956,0x78DF,0x0C60,0x1DE9,0x2F72,0x3EFB, + 0xD68D,0xC704,0xF59F,0xE416,0x90A9,0x8120,0xB3BB,0xA232, + 0x5AC5,0x4B4C,0x79D7,0x685E,0x1CE1,0x0D68,0x3FF3,0x2E7A, + 0xE70E,0xF687,0xC41C,0xD595,0xA12A,0xB0A3,0x8238,0x93B1, + 0x6B46,0x7ACF,0x4854,0x59DD,0x2D62,0x3CEB,0x0E70,0x1FF9, + 0xF78F,0xE606,0xD49D,0xC514,0xB1AB,0xA022,0x92B9,0x8330, + 0x7BC7,0x6A4E,0x58D5,0x495C,0x3DE3,0x2C6A,0x1EF1,0x0F78, }; @@ -45,10 +45,10 @@ static uint16_t crc_table[256] = { * */ void calc_14a_crc_lut(uint8_t* data, int length, uint8_t* output) { - // 取巧,强制指针类型转换 + // 取巧,强制指针类型转换 uint16_t *crc = (uint16_t *)output; - // 赋予多项式初始值 - *crc = 0x6363; - // 然后开始对每个字节进行查表 + // 赋予多项式初始值 + *crc = 0x6363; + // 然后开始对每个字节进行查表 while (length--) *crc = (*crc >> 8) ^ crc_table[(*crc & 0xFF) ^ *data++]; } diff --git a/firmware/application/src/rfid/hex_utils.c b/firmware/application/src/rfid/hex_utils.c index 47c6dc38..ad105424 100644 --- a/firmware/application/src/rfid/hex_utils.c +++ b/firmware/application/src/rfid/hex_utils.c @@ -2,35 +2,35 @@ /** -* @brief : 将大数字转换为HEX字节数组 -* @param :n : 将被转换的值 -* @param :len : 存放转换后的数值的字节长度 -* @param :dest : 存放转换结果的缓冲区 -* @retval : 无 +* @brief : 将大数字转换为HEX字节数组 +* @param :n : 将被转换的值 +* @param :len : 存放转换后的数值的字节长度 +* @param :dest : 存放转换结果的缓冲区 +* @retval : 无 * */ void num_to_bytes(uint64_t n, uint8_t len, uint8_t* dest) { - while (len--) { - dest[len] = (uint8_t)n; - n >>= 8; - } + while (len--) { + dest[len] = (uint8_t)n; + n >>= 8; + } } /** -* @brief : 将字节数组转换为大数字 -* @param :len : 存放数值的缓冲区的字节长度 -* @param :src : 存放数值的字节缓冲区 -* @retval : 转换结果 +* @brief : 将字节数组转换为大数字 +* @param :len : 存放数值的缓冲区的字节长度 +* @param :src : 存放数值的字节缓冲区 +* @retval : 转换结果 * */ uint64_t bytes_to_num(uint8_t* src, uint8_t len) { - uint64_t num = 0; - while (len--) { - num = (num << 8) | (*src); - src++; - } - return num; + uint64_t num = 0; + while (len--) { + num = (num << 8) | (*src); + src++; + } + return num; } diff --git a/firmware/application/src/rfid/mf1_crapto1.c b/firmware/application/src/rfid/mf1_crapto1.c index 58325134..4aa581e4 100644 --- a/firmware/application/src/rfid/mf1_crapto1.c +++ b/firmware/application/src/rfid/mf1_crapto1.c @@ -146,11 +146,11 @@ uint32_t crypto1_word(struct Crypto1State *s, uint32_t in, int is_encrypted) { */ uint32_t prng_successor(uint32_t x, uint32_t n) { // SWAPENDIAN(x); - x = __REV(x); + x = __REV(x); while (n--) x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21) << 31; // return SWAPENDIAN(x); - return __REV(x); + return __REV(x); } diff --git a/firmware/application/src/rfid/mf1_crypto1.c b/firmware/application/src/rfid/mf1_crypto1.c index c75d9fd1..7c452761 100644 --- a/firmware/application/src/rfid/mf1_crypto1.c +++ b/firmware/application/src/rfid/mf1_crypto1.c @@ -63,9 +63,9 @@ "ror %0" "\n\t" \ "lsr %2" "\n\t" \ "ror %1" \ - : "+r" (__even), \ + : "+r" (__even), \ "+r" (__odd), \ - "+r" (__byte) \ + "+r" (__byte) \ : \ : "r0" ) diff --git a/firmware/application/src/rfid/nfctag/hf/nfc_14a.c b/firmware/application/src/rfid/nfctag/hf/nfc_14a.c index 66506815..3d6cf724 100644 --- a/firmware/application/src/rfid/nfctag/hf/nfc_14a.c +++ b/firmware/application/src/rfid/nfctag/hf/nfc_14a.c @@ -142,14 +142,14 @@ bool nfc_tag_14a_checks_crc(uint8_t *pbtData, size_t szLen) { /** * @brief :包装ISO14443A的比特帧 -* 自动进行奇偶校验位与数据的包装合并 +* 自动进行奇偶校验位与数据的包装合并 * @param :pbtTx:将要传输的比特流 * szTxBits:比特流的长度 * pbtTxPar:奇偶校验位的比特流,这个数据的长度一定是 szTxBits / 8,也就是说 -* 实际上合并之后的比特流的组成结构为: -* data(1byte) - par(1bit) - data(1byte) - par(1bit) ... -* 00001000 - 0 - 10101110 - 1 -* 这种类似的数据结构 +* 实际上合并之后的比特流的组成结构为: +* data(1byte) - par(1bit) - data(1byte) - par(1bit) ... +* 00001000 - 0 - 10101110 - 1 +* 这种类似的数据结构 * pbtFrame: 最终组装完成的数据的缓冲区 * @retval :比特流组装结果缓冲区的长度,注意,是比特长度,换算字节请除以8再取模 */ @@ -208,7 +208,7 @@ uint8_t nfc_tag_14a_wrap_frame(const uint8_t *pbtTx, const size_t szTxBits, cons /** * @brief :解包ISO14443A的比特帧 -* 自动进行奇偶校验位与数据的解包分离 +* 自动进行奇偶校验位与数据的解包分离 * @param :pbtFrame:将要解包的比特流 * szFrameBits:比特流的长度 * pbtRx:解包后的比特流的存放的缓冲区,数据区 diff --git a/firmware/application/src/rfid/nfctag/hf/nfc_mf1.c b/firmware/application/src/rfid/nfctag/hf/nfc_mf1.c index 986c7bbd..ead81122 100644 --- a/firmware/application/src/rfid/nfctag/hf/nfc_mf1.c +++ b/firmware/application/src/rfid/nfctag/hf/nfc_mf1.c @@ -723,7 +723,7 @@ void nfc_tag_mf1_state_handler(uint8_t* p_data, uint16_t szDataBits) { return; } case CMD_WRITE: { - // 正常的卡不允许写block0,不然会被CUID防火墙识别到 + // 正常的卡不允许写block0,不然会被CUID防火墙识别到 if (p_data[1] == 0x00 && !m_tag_information->config.mode_gen2_magic) { // 直接重置14a的状态机,让标签休眠 nfc_tag_14a_set_state(NFC_TAG_STATE_14A_HALTED); diff --git a/firmware/application/src/rfid/nfctag/lf/lf_tag_em.c b/firmware/application/src/rfid/nfctag/lf/lf_tag_em.c index cf8e7851..01096447 100644 --- a/firmware/application/src/rfid/nfctag/lf/lf_tag_em.c +++ b/firmware/application/src/rfid/nfctag/lf/lf_tag_em.c @@ -129,7 +129,7 @@ void timer_ce_handler(nrf_timer_event_t event_type, void* p_context) { switch (event_type) { // 因为我们配置的是使用CC通道2,所以事件回调 // 函数中判断NRF_TIMER_EVENT_COMPARE0事件 - case NRF_TIMER_EVENT_COMPARE2: { + case NRF_TIMER_EVENT_COMPARE2: { if (m_is_send_first_edge) { if (GETBIT(m_id_bit_data, m_bit_send_position)) { // 发送 1 的第一个沿 diff --git a/firmware/application/src/rfid/reader/hf/mf1_toolbox.c b/firmware/application/src/rfid/reader/hf/mf1_toolbox.c index 13e428f5..e3178abd 100644 --- a/firmware/application/src/rfid/reader/hf/mf1_toolbox.c +++ b/firmware/application/src/rfid/reader/hf/mf1_toolbox.c @@ -20,124 +20,124 @@ static picc_14a_tag_t *p_tag_info = &m_tag_info; /** -* @brief : 测算随机数的距离值,根据实时算出来的多项式表 -* 官方注释:x,y valid tag nonces, then prng_successor(x, nonce_distance(x, y)) = y -* @param :msb : 随机数高位,传出结果由此指针完成 -* @param :lsb : 随机数低位,传出结果由此指针完成 -* @retval : 无 +* @brief : 测算随机数的距离值,根据实时算出来的多项式表 +* 官方注释:x,y valid tag nonces, then prng_successor(x, nonce_distance(x, y)) = y +* @param :msb : 随机数高位,传出结果由此指针完成 +* @param :lsb : 随机数低位,传出结果由此指针完成 +* @retval : 无 * */ void nonce_distance_notable(uint32_t *msb, uint32_t *lsb) { - uint16_t x = 1, pos; - uint8_t calc_ok = 0; - - for (uint16_t i = 1; i; ++i) { - // 计算坐标,以获得多项式的步进运算结果 - pos = (x & 0xff) << 8 | x >> 8; - // 判断坐标,我们取出对应的值并且设置以取值的标志位 - if ((pos == *msb) & !(calc_ok >> 0 & 0x01)) { - *msb = i; - calc_ok |= 0x01; - } - if ((pos == *lsb) & !(calc_ok >> 1 & 0x01)) { - *lsb = i; - calc_ok |= 0x02; - } - // 最终两个值的测算都完成的话,我们直接结束运算, - // 以减少不必要的后续CPU性能损耗 - if (calc_ok == 0x03) { - return; - } - x = x >> 1 | (x ^ x >> 2 ^ x >> 3 ^ x >> 5) << 15; - } + uint16_t x = 1, pos; + uint8_t calc_ok = 0; + + for (uint16_t i = 1; i; ++i) { + // 计算坐标,以获得多项式的步进运算结果 + pos = (x & 0xff) << 8 | x >> 8; + // 判断坐标,我们取出对应的值并且设置以取值的标志位 + if ((pos == *msb) & !(calc_ok >> 0 & 0x01)) { + *msb = i; + calc_ok |= 0x01; + } + if ((pos == *lsb) & !(calc_ok >> 1 & 0x01)) { + *lsb = i; + calc_ok |= 0x02; + } + // 最终两个值的测算都完成的话,我们直接结束运算, + // 以减少不必要的后续CPU性能损耗 + if (calc_ok == 0x03) { + return; + } + x = x >> 1 | (x ^ x >> 2 ^ x >> 3 ^ x >> 5) << 15; + } } /** -* @brief : 测算PRNG的步进规律,以验证该随机数是否是可预测的 -* 假若该可预测,那么就可能支持 Darkside攻击 -* 并且可能支持 Nested 攻击 -* @param :nonce : 测量的随机数 -* @retval : true = weak prng -* false = hardend prng +* @brief : 测算PRNG的步进规律,以验证该随机数是否是可预测的 +* 假若该可预测,那么就可能支持 Darkside攻击 +* 并且可能支持 Nested 攻击 +* @param :nonce : 测量的随机数 +* @retval : true = weak prng +* false = hardend prng * */ bool validate_prng_nonce_notable(uint32_t nonce) { - // 给出初始的坐标值 - uint32_t msb = nonce >> 16; - uint32_t lsb = nonce & 0xffff; - // 传入坐标进行直接运算,并且传出也由传入参数间接传出 - nonce_distance_notable(&msb, &lsb); + // 给出初始的坐标值 + uint32_t msb = nonce >> 16; + uint32_t lsb = nonce & 0xffff; + // 传入坐标进行直接运算,并且传出也由传入参数间接传出 + nonce_distance_notable(&msb, &lsb); return ((65535 - msb + lsb) % 65535) == 16; } /** -* @brief : 重置场,在一定的延时之后重启场 +* @brief : 重置场,在一定的延时之后重启场 * */ static inline void ResetRadioFieldWithDelay(void) { - pcd_14a_reader_antenna_off(); - bsp_delay_ms(g_ant_reset_delay); - pcd_14a_reader_antenna_on(); + pcd_14a_reader_antenna_off(); + bsp_delay_ms(g_ant_reset_delay); + pcd_14a_reader_antenna_on(); } /** -* @brief : 发送mifare指令 -* @param :pcs : crypto1句柄 -* @param :crypted : 这批数据是否需要被 crypto1 加密 -* @param :cmd : 将被发送的指令,例如 0x60 表示验证 A 秘钥 -* @param :data : 将被发送的数据,例如 0x03 表示验证 1 扇区 -* @param :answer : 卡片的应答数据存放的数组 -* @param :answer_parity : 卡片的应答数据的奇偶校验位存放的数组 -* @retval : 卡片应答的数据的长度,这个长度是 bit 长度,不是 byte长度 +* @brief : 发送mifare指令 +* @param :pcs : crypto1句柄 +* @param :crypted : 这批数据是否需要被 crypto1 加密 +* @param :cmd : 将被发送的指令,例如 0x60 表示验证 A 秘钥 +* @param :data : 将被发送的数据,例如 0x03 表示验证 1 扇区 +* @param :answer : 卡片的应答数据存放的数组 +* @param :answer_parity : 卡片的应答数据的奇偶校验位存放的数组 +* @retval : 卡片应答的数据的长度,这个长度是 bit 长度,不是 byte长度 * */ uint8_t sendcmd(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t *status, uint8_t *answer, uint8_t *answer_parity, uint16_t answer_max_bit) { - // 这里我们直接设置为静态 - static uint8_t pos; - static uint16_t len; + // 这里我们直接设置为静态 + static uint8_t pos; + static uint16_t len; static uint8_t dcmd[4]; static uint8_t ecmd[4]; - static uint8_t par[4]; + static uint8_t par[4]; - dcmd[0] = ecmd[0] = cmd; - dcmd[1] = ecmd[1] = data; + dcmd[0] = ecmd[0] = cmd; + dcmd[1] = ecmd[1] = data; crc_14a_append(dcmd, 2); ecmd[2] = dcmd[2]; - ecmd[3] = dcmd[3]; - - len = 0; - - if (pcs && crypted) { - for (pos = 0; pos < 4; pos++) { - ecmd[pos] = crypto1_byte(pcs, 0x00, 0) ^ dcmd[pos]; - par[pos] = filter(pcs->odd) ^ oddparity8(dcmd[pos]); - } - *status = pcd_14a_reader_bits_transfer( - ecmd, - 32, - par, - answer, - answer_parity, - &len, - answer_max_bit - ); + ecmd[3] = dcmd[3]; + + len = 0; + + if (pcs && crypted) { + for (pos = 0; pos < 4; pos++) { + ecmd[pos] = crypto1_byte(pcs, 0x00, 0) ^ dcmd[pos]; + par[pos] = filter(pcs->odd) ^ oddparity8(dcmd[pos]); + } + *status = pcd_14a_reader_bits_transfer( + ecmd, + 32, + par, + answer, + answer_parity, + &len, + answer_max_bit + ); } else { - *status = pcd_14a_reader_bytes_transfer( - PCD_TRANSCEIVE, - dcmd, - 4, - answer, - &len, - answer_max_bit - ); + *status = pcd_14a_reader_bytes_transfer( + PCD_TRANSCEIVE, + dcmd, + 4, + answer, + &len, + answer_max_bit + ); } - // 通信有问题,不继续接下来的任务 - if (*status != HF_TAG_OK) { - return len; - } + // 通信有问题,不继续接下来的任务 + if (*status != HF_TAG_OK) { + return len; + } if (crypted == CRYPT_ALL) { if (len == 8) { @@ -157,40 +157,40 @@ uint8_t sendcmd(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t } /** -* @brief : 高级验证过程 -* @param :pcs : crypto1句柄 -* @param :uid : 卡片的UID号 -* @param :blockNo : 验证的块号 -* @param :keyType : 秘钥类型, 0x60(A秘钥) 或者 0x61(B秘钥) -* @param :ui64Key : 卡片的秘钥的U64值 -* @param :isNested : 当前是否是嵌套验证 -* @param :ntptr : 存放NT的地址,如果传入 NULL ,则不保存NT -* @retval : 验证成功返回 0 ,验证不成功返回非 0 值 +* @brief : 高级验证过程 +* @param :pcs : crypto1句柄 +* @param :uid : 卡片的UID号 +* @param :blockNo : 验证的块号 +* @param :keyType : 秘钥类型, 0x60(A秘钥) 或者 0x61(B秘钥) +* @param :ui64Key : 卡片的秘钥的U64值 +* @param :isNested : 当前是否是嵌套验证 +* @param :ntptr : 存放NT的地址,如果传入 NULL ,则不保存NT +* @retval : 验证成功返回 0 ,验证不成功返回非 0 值 * */ int authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr) { - static uint8_t status; // tag resonse status - static uint16_t len; // tag resonse length - static uint32_t pos, nt, ntpp; // Supplied tag nonce - static const uint8_t nr[] = { 0x12, 0x34, 0x56, 0x78 }; // 使用固定的卡片随机数 NR,也就是Nonce Reader。 - uint8_t par[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - uint8_t mf_nr_ar[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - uint8_t answer[] = { 0x00, 0x00, 0x00, 0x00 }; - uint8_t parity[] = { 0x00, 0x00, 0x00, 0x00 }; - - len = sendcmd(pcs, isNested, keyType, blockNo, &status, answer, parity, U8ARR_BIT_LEN(answer)); - if (len != 32) { - NRF_LOG_INFO("No 32 data recv on sendcmd: %d\r\n", len); - return HF_ERRSTAT; - } + static uint8_t status; // tag resonse status + static uint16_t len; // tag resonse length + static uint32_t pos, nt, ntpp; // Supplied tag nonce + static const uint8_t nr[] = { 0x12, 0x34, 0x56, 0x78 }; // 使用固定的卡片随机数 NR,也就是Nonce Reader。 + uint8_t par[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + uint8_t mf_nr_ar[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + uint8_t answer[] = { 0x00, 0x00, 0x00, 0x00 }; + uint8_t parity[] = { 0x00, 0x00, 0x00, 0x00 }; + + len = sendcmd(pcs, isNested, keyType, blockNo, &status, answer, parity, U8ARR_BIT_LEN(answer)); + if (len != 32) { + NRF_LOG_INFO("No 32 data recv on sendcmd: %d\r\n", len); + return HF_ERRSTAT; + } // Save the tag nonce (nt) nt = BYTES4_TO_U32(answer); // ----------------------------- crypto1 create if (isNested) { - crypto1_deinit(pcs); - } + crypto1_deinit(pcs); + } // Init cipher with key crypto1_init(pcs, ui64Key); @@ -210,7 +210,7 @@ int authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyT // Generate (encrypted) nr+parity by loading it into the cipher (Nr) for (pos = 0; pos < 4; pos++) { mf_nr_ar[pos] = crypto1_byte(pcs, nr[pos], 0) ^ nr[pos]; - par[pos] = filter(pcs->odd) ^ oddparity8(nr[pos]); + par[pos] = filter(pcs->odd) ^ oddparity8(nr[pos]); } // Skip 32 bits in pseudo random generator @@ -220,710 +220,710 @@ int authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyT for (pos = 4; pos < 8; pos++) { nt = prng_successor(nt, 8); mf_nr_ar[pos] = crypto1_byte(pcs, 0x00, 0) ^ (nt & 0xff); - par[pos] = filter(pcs->odd) ^ oddparity8(nt); - } - - // 我们不需要status,因为正常的通信会返回 32bit 的数据 - pcd_14a_reader_bits_transfer(mf_nr_ar, 64, par, answer, parity, &len, U8ARR_BIT_LEN(answer)); - if (len == 32) { - ntpp = prng_successor(nt, 32) ^ crypto1_word(pcs, 0, 0); - if (ntpp == BYTES4_TO_U32(answer)) { - // 验证成功! - return HF_TAG_OK; - } else { - // 失败 - return MF_ERRAUTH; - } - } - - // 失败! + par[pos] = filter(pcs->odd) ^ oddparity8(nt); + } + + // 我们不需要status,因为正常的通信会返回 32bit 的数据 + pcd_14a_reader_bits_transfer(mf_nr_ar, 64, par, answer, parity, &len, U8ARR_BIT_LEN(answer)); + if (len == 32) { + ntpp = prng_successor(nt, 32) ^ crypto1_word(pcs, 0, 0); + if (ntpp == BYTES4_TO_U32(answer)) { + // 验证成功! + return HF_TAG_OK; + } else { + // 失败 + return MF_ERRAUTH; + } + } + + // 失败! return MF_ERRAUTH; } /** -* @brief : 选定出现几率最大的一个NT -* @param :tag : 标签信息结构体,快速选卡需要使用此结构体 -* @param :block : 将被攻击的密钥块 -* @param :keytype : 将被攻击的密钥类型 -* @param :nt : 最终选定的NT,这个NT是出现次数最多,且排名最靠前的 +* @brief : 选定出现几率最大的一个NT +* @param :tag : 标签信息结构体,快速选卡需要使用此结构体 +* @param :block : 将被攻击的密钥块 +* @param :keytype : 将被攻击的密钥类型 +* @param :nt : 最终选定的NT,这个NT是出现次数最多,且排名最靠前的 * @retval 最终确定下来的NT值, 如果无法同步卡片时钟,返回对应的异常码,否则返回 HF_TAG_OK * ------------------- * 为何无法固定随机数? -* 0、卡片天线位置有自由或者非自由移动的偏差导致通信不稳定。 -* 1、所处电磁环境非常复杂,导致卡片上电充能到完成通信的过程无法稳定重放 -* 2、卡片针对重放攻击做了漏洞修复,卡片不再被重放攻击套取相同应答 -* 3、此代码所运行的环境非裸机或中断太频繁,或其他任务调度太频繁, -* 导致 CPU 无法在稳定的相同的时间内完成重放攻击。 -* 此种情况基本无解,建议将此段代码之外的非关键中断以及任务调度关闭 +* 0、卡片天线位置有自由或者非自由移动的偏差导致通信不稳定。 +* 1、所处电磁环境非常复杂,导致卡片上电充能到完成通信的过程无法稳定重放 +* 2、卡片针对重放攻击做了漏洞修复,卡片不再被重放攻击套取相同应答 +* 3、此代码所运行的环境非裸机或中断太频繁,或其他任务调度太频繁, +* 导致 CPU 无法在稳定的相同的时间内完成重放攻击。 +* 此种情况基本无解,建议将此段代码之外的非关键中断以及任务调度关闭 */ uint8_t Darkside_Select_Nonces(picc_14a_tag_t *tag, uint8_t block, uint8_t keytype, uint32_t *nt) { #define NT_COUNT 15 - uint8_t tag_auth[4] = { keytype, block, 0x00, 0x00 }; - uint8_t tag_resp[4] = { 0x00 }; - uint8_t nt_count[NT_COUNT] = { 0x00 }; - uint32_t nt_list[NT_COUNT] = { 0x00 }; - uint8_t i, m, max, status; - uint16_t len; - - crc_14a_append(tag_auth, 2); - - // 进行随机数采集 - for(i = 0; i < NT_COUNT; i++) { - // 在进行天线重置时,我们必须要确保 - // 1、天线断电足够久,以此确保卡片完全断电,否则无法重置卡片的伪随机数生成器 - // 2、断电时间适中,不要太长,会影响效率,也不要太短,会无法无法重置卡片 - ResetRadioFieldWithDelay(); - // 完全断电后,我们进行快速选卡,尽可能的将验证耗时压缩 - if (pcd_14a_reader_scan_auto(tag) != HF_TAG_OK) { - NRF_LOG_INFO("Tag can't select!\n"); - return HF_TAG_NO; - } - status = pcd_14a_reader_bytes_transfer(PCD_TRANSCEIVE, tag_auth, 4, tag_resp, &len, U8ARR_BIT_LEN(tag_resp)); - // 在寻找到卡片后,开始采集随机数 - if (status != HF_TAG_OK || len != 32) { - NRF_LOG_INFO("Get nt failed.\n"); - return HF_ERRSTAT; - } - // 转换为u32的类型,并且进行缓存 - nt_list[i] = bytes_to_num(tag_resp, 4); - // 转换应答的字节数组为10进制的NT - // NRF_LOG_INFO("Get nt: %"PRIu32"\r\n", nt_list[i]); - } - - // 对随机数进行取重 - for(i = 0; i < NT_COUNT; i++) { - uint32_t nt_a = nt_list[i]; - for(m = i + 1; m < NT_COUNT; m++) { - uint32_t nt_b = nt_list[m]; - if (nt_a == nt_b) { - nt_count[i] += 1; - } - } - } - - // 对取重后的最大次数值进行取值 - max = nt_count[0]; - m = 0; - for(i = 1; i < NT_COUNT; i++) { - if(nt_count[i] > max) { - max = nt_count[i]; - m = i; - } - } - - // 最终,我们判定一下max次数是否大于0, - // 如果不大于0,说明无法同步时钟。 - if(max == 0) { - NRF_LOG_INFO("Can't sync nt.\n"); - return DARKSIDE_CANT_FIXED_NT; - } - - // NT 固定成功,我们取出出现次数最高的那个 - // NRF_LOG_INFO("Sync nt: %"PRIu32", max = %d\n", nt_list[m], max); - if (nt) *nt = nt_list[m]; // 只有调用者需要获得NT时才传出 - return HF_TAG_OK; + uint8_t tag_auth[4] = { keytype, block, 0x00, 0x00 }; + uint8_t tag_resp[4] = { 0x00 }; + uint8_t nt_count[NT_COUNT] = { 0x00 }; + uint32_t nt_list[NT_COUNT] = { 0x00 }; + uint8_t i, m, max, status; + uint16_t len; + + crc_14a_append(tag_auth, 2); + + // 进行随机数采集 + for(i = 0; i < NT_COUNT; i++) { + // 在进行天线重置时,我们必须要确保 + // 1、天线断电足够久,以此确保卡片完全断电,否则无法重置卡片的伪随机数生成器 + // 2、断电时间适中,不要太长,会影响效率,也不要太短,会无法无法重置卡片 + ResetRadioFieldWithDelay(); + // 完全断电后,我们进行快速选卡,尽可能的将验证耗时压缩 + if (pcd_14a_reader_scan_auto(tag) != HF_TAG_OK) { + NRF_LOG_INFO("Tag can't select!\n"); + return HF_TAG_NO; + } + status = pcd_14a_reader_bytes_transfer(PCD_TRANSCEIVE, tag_auth, 4, tag_resp, &len, U8ARR_BIT_LEN(tag_resp)); + // 在寻找到卡片后,开始采集随机数 + if (status != HF_TAG_OK || len != 32) { + NRF_LOG_INFO("Get nt failed.\n"); + return HF_ERRSTAT; + } + // 转换为u32的类型,并且进行缓存 + nt_list[i] = bytes_to_num(tag_resp, 4); + // 转换应答的字节数组为10进制的NT + // NRF_LOG_INFO("Get nt: %"PRIu32"\r\n", nt_list[i]); + } + + // 对随机数进行取重 + for(i = 0; i < NT_COUNT; i++) { + uint32_t nt_a = nt_list[i]; + for(m = i + 1; m < NT_COUNT; m++) { + uint32_t nt_b = nt_list[m]; + if (nt_a == nt_b) { + nt_count[i] += 1; + } + } + } + + // 对取重后的最大次数值进行取值 + max = nt_count[0]; + m = 0; + for(i = 1; i < NT_COUNT; i++) { + if(nt_count[i] > max) { + max = nt_count[i]; + m = i; + } + } + + // 最终,我们判定一下max次数是否大于0, + // 如果不大于0,说明无法同步时钟。 + if(max == 0) { + NRF_LOG_INFO("Can't sync nt.\n"); + return DARKSIDE_CANT_FIXED_NT; + } + + // NT 固定成功,我们取出出现次数最高的那个 + // NRF_LOG_INFO("Sync nt: %"PRIu32", max = %d\n", nt_list[m], max); + if (nt) *nt = nt_list[m]; // 只有调用者需要获得NT时才传出 + return HF_TAG_OK; } /** -* @brief : 使用Darkside漏洞破解一个未知的密钥 -* @param :dc : darkside破解的核心应答 -* @param :dp : darkside破解的核心参数 -* @retval : 收集成功返回 HF_TAG_OK ,验证不成功返回对应的异常码 +* @brief : 使用Darkside漏洞破解一个未知的密钥 +* @param :dc : darkside破解的核心应答 +* @param :dp : darkside破解的核心参数 +* @retval : 收集成功返回 HF_TAG_OK ,验证不成功返回对应的异常码 * */ uint8_t Darkside_Recover_Key(uint8_t targetBlk, uint8_t targetTyp, - uint8_t firstRecover, uint8_t ntSyncMax, DarksideCore* dc) { - - // 被固定使用的卡片信息 - static uint32_t uid_ori = 0; - uint32_t uid_cur = 0; - - // 被固定随机数和每次获得的随机数 - static uint32_t nt_ori = 0; - uint32_t nt_cur = 0; - - // mr_nr 生成时每次的变化量 - static uint8_t par_low = 0; - static uint8_t mf_nr_ar3 = 0; - - // 卡片交互通信 哇塞,好整齐的变量定义 - uint8_t tag_auth[4] = { targetTyp, targetBlk, 0x00, 0x00 }; - uint8_t par_list[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - uint8_t ks_list[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - uint8_t mf_nr_ar[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - - // 真正通信的时候,全程8个byte的长度足够容纳所有的数据 - uint8_t par_byte[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - uint8_t dat_recv[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - - // 控制变量 - uint8_t resync_count = 0x00; // 这个变量负责统计当前同步时钟以同步NT的尝试次数 - uint8_t received_nack = 0x00; // 这个变量负责标志当前是否接收到了NACK的回复 - uint8_t par = 0x00; // 这个变量负责奇偶校验位的递增,以碰撞卡片的回复 - uint8_t status = 0x00; // 这个变量负责保存卡片通信的状态 - uint16_t len = 0x00; // 这个变量负责保存通信过程中卡片的数据应答长度 - uint8_t nt_diff = 0x00; // 这个变量很关键哦,别不初始化,因为下面直接使用了 - - // 我们需要先确认使用某一张卡 - if (pcd_14a_reader_scan_auto(p_tag_info) == HF_TAG_OK) { - uid_cur = get_u32_tag_uid(p_tag_info); - } else { - return HF_TAG_NO; - } - - // 验证指令需要追加CRC16 - crc_14a_append(tag_auth, 2); - - // 初始化静态变量如果是第一次发起攻击 - if (firstRecover) { - // 重置关键变量 - nt_ori = 0; - mf_nr_ar3 = 0; - par_low = 0; - - // 第一次运行的话,我们需要固定使用一个卡片 - uid_ori = get_u32_tag_uid(p_tag_info); - - // 然后还需要固定一个大概率出现的随机数 - status = Darkside_Select_Nonces(p_tag_info, targetBlk, targetTyp, &nt_ori); - if (status != HF_TAG_OK) { - // 固定随机数失败,无法进行下一步操作 - return status; - } - } else { - // we were unsuccessful on a previous call. - // Try another READER nonce (first 3 parity bits remain the same) - mf_nr_ar3++; - mf_nr_ar[3] = mf_nr_ar3; - par = par_low; - - if (uid_ori != uid_cur) { - return DARKSIDE_TAG_CHANGED; - } - } - - // 在一个大循环里面一直采集不同的nr ar下的nack - do { - // 重置nack的接收标志 - received_nack = 0; - - // 在进行天线重置时,我们必须要确保 - // 1、天线断电足够久,以此确保卡片完全断电,否则无法重置卡片的伪随机数生成器 - // 2、断电时间适中,不要太长,会影响效率,也不要太短,会无法无法重置卡片 - ResetRadioFieldWithDelay(); - - // 完全断电后,我们进行快速选卡,尽可能的将验证耗时压缩 - if (pcd_14a_reader_scan_auto(p_tag_info) != HF_TAG_OK) { - NRF_LOG_INFO("Tag can't select!\n"); - return HF_TAG_NO; - } - - status = pcd_14a_reader_bytes_transfer(PCD_TRANSCEIVE, tag_auth, 4, dat_recv, &len, U8ARR_BIT_LEN(dat_recv)); - - // 在寻找到卡片后,开始采集随机数 - if (status != HF_TAG_OK || len != 32) { - NRF_LOG_INFO("Get nt failed.\n"); - return HF_ERRSTAT; - } - - // 转换应答的字节数组为10进制的 NT - nt_cur = bytes_to_num(dat_recv, 4); - // NRF_LOG_INFO("Get nt: %"PRIu32"\r\n", nt_cur); - - // 判断时钟同步(使NT固定) - if (nt_cur != nt_ori) { - // 随机数不同步,但是我们已经选择过随机数了 - // 并且我们选择的随机数也被成功的重放攻击了 - // 也就说,这种误差,已经没机会修正随机数了 - if (++resync_count == ntSyncMax) { - NRF_LOG_INFO("Can't fix nonce.\r\n"); - return DARKSIDE_CANT_FIXED_NT; - } - - // 时钟不同步的情况下,下面的操作是没意义的 - // 因此直接跳过下面的操作,进入下一轮循环, - // 上帝保佑下一轮循环能同步时钟。。。 - // NRF_LOG_INFO("Sync nt -> nt_fix: %"PRIu32", nt_new: %"PRIu32"\r\n", nt_ori, nt_cur); - continue; - } - - // 本来我们只需要发 par 的,利用其中的每一个Bit当做校验位来的 - // 但是奈何我们实现的发送函数只支持以一个uint8_t,也就是一个字节当做一个bit来用 - // 因此此处我们需要把 PM3 的通信写法换成我们的。 - // 这里反正次数不多,我们直接展开换算的代码 - par_byte[0] = par >> 0 & 0x1; - par_byte[1] = par >> 1 & 0x1; - par_byte[2] = par >> 2 & 0x1; - par_byte[3] = par >> 3 & 0x1; - par_byte[4] = par >> 4 & 0x1; - par_byte[5] = par >> 5 & 0x1; - par_byte[6] = par >> 6 & 0x1; - par_byte[7] = par >> 7 & 0x1; - - len = 0; - pcd_14a_reader_bits_transfer(mf_nr_ar, 64, par_byte, dat_recv, par_byte, &len, U8ARR_BIT_LEN(dat_recv)); - - // 重置固定随机数上限计数 - resync_count = 0; - - if (len == 4) { - // NRF_LOG_INFO("NACK get: 0x%x\r\n", receivedAnswer[0]); - received_nack = 1; - } else if (len == 32) { - // did we get lucky and got our dummykey to be valid? - // however we dont feed key w uid it the prng.. - NRF_LOG_INFO("Auth Ok, you are so lucky!\n"); - return DARKSIDE_LUCK_AUTH_OK; - } - - // Receive answer. This will be a 4 Bit NACK when the 8 parity bits are OK after decoding - if (received_nack) { - if (nt_diff == 0) { - // there is no need to check all parities for other nt_diff. Parity Bits for mf_nr_ar[0..2] won't change - par_low = par & 0xE0; - } - - par_list[nt_diff] = (par * 0x0202020202ULL & 0x010884422010ULL) % 1023; - ks_list[nt_diff] = dat_recv[0] ^ 0x05; // xor with NACK value to get keystream - - // Test if the information is complete - if (nt_diff == 0x07) { - break; - } - - nt_diff = (nt_diff + 1) & 0x07; - mf_nr_ar[3] = (mf_nr_ar[3] & 0x1F) | (nt_diff << 5); - par = par_low; - } else { - // No NACK. - if (nt_diff == 0) { - par++; - if (par == 0) { // tried all 256 possible parities without success. Card doesn't send NACK. - NRF_LOG_INFO("Card doesn't send NACK.\r\n"); - return DARKSIDE_NACK_NO_SEND; - } - } else { - // Why this? - par = ((par & 0x1F) + 1) | par_low; - } - } - } while(1); - - mf_nr_ar[3] &= 0x1F; - - // 没有出现意外情况,本次执行判定为成功! - // 我们需要对结果进行封装返回 - - get_4byte_tag_uid(p_tag_info, dc->uid); + uint8_t firstRecover, uint8_t ntSyncMax, DarksideCore* dc) { + + // 被固定使用的卡片信息 + static uint32_t uid_ori = 0; + uint32_t uid_cur = 0; + + // 被固定随机数和每次获得的随机数 + static uint32_t nt_ori = 0; + uint32_t nt_cur = 0; + + // mr_nr 生成时每次的变化量 + static uint8_t par_low = 0; + static uint8_t mf_nr_ar3 = 0; + + // 卡片交互通信 哇塞,好整齐的变量定义 + uint8_t tag_auth[4] = { targetTyp, targetBlk, 0x00, 0x00 }; + uint8_t par_list[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + uint8_t ks_list[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + uint8_t mf_nr_ar[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + // 真正通信的时候,全程8个byte的长度足够容纳所有的数据 + uint8_t par_byte[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + uint8_t dat_recv[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + // 控制变量 + uint8_t resync_count = 0x00; // 这个变量负责统计当前同步时钟以同步NT的尝试次数 + uint8_t received_nack = 0x00; // 这个变量负责标志当前是否接收到了NACK的回复 + uint8_t par = 0x00; // 这个变量负责奇偶校验位的递增,以碰撞卡片的回复 + uint8_t status = 0x00; // 这个变量负责保存卡片通信的状态 + uint16_t len = 0x00; // 这个变量负责保存通信过程中卡片的数据应答长度 + uint8_t nt_diff = 0x00; // 这个变量很关键哦,别不初始化,因为下面直接使用了 + + // 我们需要先确认使用某一张卡 + if (pcd_14a_reader_scan_auto(p_tag_info) == HF_TAG_OK) { + uid_cur = get_u32_tag_uid(p_tag_info); + } else { + return HF_TAG_NO; + } + + // 验证指令需要追加CRC16 + crc_14a_append(tag_auth, 2); + + // 初始化静态变量如果是第一次发起攻击 + if (firstRecover) { + // 重置关键变量 + nt_ori = 0; + mf_nr_ar3 = 0; + par_low = 0; + + // 第一次运行的话,我们需要固定使用一个卡片 + uid_ori = get_u32_tag_uid(p_tag_info); + + // 然后还需要固定一个大概率出现的随机数 + status = Darkside_Select_Nonces(p_tag_info, targetBlk, targetTyp, &nt_ori); + if (status != HF_TAG_OK) { + // 固定随机数失败,无法进行下一步操作 + return status; + } + } else { + // we were unsuccessful on a previous call. + // Try another READER nonce (first 3 parity bits remain the same) + mf_nr_ar3++; + mf_nr_ar[3] = mf_nr_ar3; + par = par_low; + + if (uid_ori != uid_cur) { + return DARKSIDE_TAG_CHANGED; + } + } + + // 在一个大循环里面一直采集不同的nr ar下的nack + do { + // 重置nack的接收标志 + received_nack = 0; + + // 在进行天线重置时,我们必须要确保 + // 1、天线断电足够久,以此确保卡片完全断电,否则无法重置卡片的伪随机数生成器 + // 2、断电时间适中,不要太长,会影响效率,也不要太短,会无法无法重置卡片 + ResetRadioFieldWithDelay(); + + // 完全断电后,我们进行快速选卡,尽可能的将验证耗时压缩 + if (pcd_14a_reader_scan_auto(p_tag_info) != HF_TAG_OK) { + NRF_LOG_INFO("Tag can't select!\n"); + return HF_TAG_NO; + } + + status = pcd_14a_reader_bytes_transfer(PCD_TRANSCEIVE, tag_auth, 4, dat_recv, &len, U8ARR_BIT_LEN(dat_recv)); + + // 在寻找到卡片后,开始采集随机数 + if (status != HF_TAG_OK || len != 32) { + NRF_LOG_INFO("Get nt failed.\n"); + return HF_ERRSTAT; + } + + // 转换应答的字节数组为10进制的 NT + nt_cur = bytes_to_num(dat_recv, 4); + // NRF_LOG_INFO("Get nt: %"PRIu32"\r\n", nt_cur); + + // 判断时钟同步(使NT固定) + if (nt_cur != nt_ori) { + // 随机数不同步,但是我们已经选择过随机数了 + // 并且我们选择的随机数也被成功的重放攻击了 + // 也就说,这种误差,已经没机会修正随机数了 + if (++resync_count == ntSyncMax) { + NRF_LOG_INFO("Can't fix nonce.\r\n"); + return DARKSIDE_CANT_FIXED_NT; + } + + // 时钟不同步的情况下,下面的操作是没意义的 + // 因此直接跳过下面的操作,进入下一轮循环, + // 上帝保佑下一轮循环能同步时钟。。。 + // NRF_LOG_INFO("Sync nt -> nt_fix: %"PRIu32", nt_new: %"PRIu32"\r\n", nt_ori, nt_cur); + continue; + } + + // 本来我们只需要发 par 的,利用其中的每一个Bit当做校验位来的 + // 但是奈何我们实现的发送函数只支持以一个uint8_t,也就是一个字节当做一个bit来用 + // 因此此处我们需要把 PM3 的通信写法换成我们的。 + // 这里反正次数不多,我们直接展开换算的代码 + par_byte[0] = par >> 0 & 0x1; + par_byte[1] = par >> 1 & 0x1; + par_byte[2] = par >> 2 & 0x1; + par_byte[3] = par >> 3 & 0x1; + par_byte[4] = par >> 4 & 0x1; + par_byte[5] = par >> 5 & 0x1; + par_byte[6] = par >> 6 & 0x1; + par_byte[7] = par >> 7 & 0x1; + + len = 0; + pcd_14a_reader_bits_transfer(mf_nr_ar, 64, par_byte, dat_recv, par_byte, &len, U8ARR_BIT_LEN(dat_recv)); + + // 重置固定随机数上限计数 + resync_count = 0; + + if (len == 4) { + // NRF_LOG_INFO("NACK get: 0x%x\r\n", receivedAnswer[0]); + received_nack = 1; + } else if (len == 32) { + // did we get lucky and got our dummykey to be valid? + // however we dont feed key w uid it the prng.. + NRF_LOG_INFO("Auth Ok, you are so lucky!\n"); + return DARKSIDE_LUCK_AUTH_OK; + } + + // Receive answer. This will be a 4 Bit NACK when the 8 parity bits are OK after decoding + if (received_nack) { + if (nt_diff == 0) { + // there is no need to check all parities for other nt_diff. Parity Bits for mf_nr_ar[0..2] won't change + par_low = par & 0xE0; + } + + par_list[nt_diff] = (par * 0x0202020202ULL & 0x010884422010ULL) % 1023; + ks_list[nt_diff] = dat_recv[0] ^ 0x05; // xor with NACK value to get keystream + + // Test if the information is complete + if (nt_diff == 0x07) { + break; + } + + nt_diff = (nt_diff + 1) & 0x07; + mf_nr_ar[3] = (mf_nr_ar[3] & 0x1F) | (nt_diff << 5); + par = par_low; + } else { + // No NACK. + if (nt_diff == 0) { + par++; + if (par == 0) { // tried all 256 possible parities without success. Card doesn't send NACK. + NRF_LOG_INFO("Card doesn't send NACK.\r\n"); + return DARKSIDE_NACK_NO_SEND; + } + } else { + // Why this? + par = ((par & 0x1F) + 1) | par_low; + } + } + } while(1); + + mf_nr_ar[3] &= 0x1F; + + // 没有出现意外情况,本次执行判定为成功! + // 我们需要对结果进行封装返回 + + get_4byte_tag_uid(p_tag_info, dc->uid); num_to_bytes(nt_cur, 4, dc->nt); memcpy(dc->par_list, par_list, sizeof(dc->par_list)); memcpy(dc->ks_list, ks_list, sizeof(dc->ks_list)); memcpy(dc->nr, mf_nr_ar, sizeof(dc->nr)); memcpy(dc->ar, mf_nr_ar + 4, sizeof(dc->ar)); - // NRF_LOG_INFO("Darkside done!\n"); - return HF_TAG_OK; + // NRF_LOG_INFO("Darkside done!\n"); + return HF_TAG_OK; } /** -* @brief : 修改天线重启的中间延时 -* 延时越长,越能重启某些非标卡片, -* 延时越短,越块处理天线重启过程,进而处理后续业务 -* @param :delay_ms : 延时的具体值,单位为毫秒 -* @retval : 无 +* @brief : 修改天线重启的中间延时 +* 延时越长,越能重启某些非标卡片, +* 延时越短,越块处理天线重启过程,进而处理后续业务 +* @param :delay_ms : 延时的具体值,单位为毫秒 +* @retval : 无 * */ void Atenna_Switch_Delay(uint32_t delay_ms) { - g_ant_reset_delay = delay_ms; + g_ant_reset_delay = delay_ms; } /** -* @brief : 判断此卡片是否支持Darkside攻击 -* @retval : 如果支持,返回 HF_TAG_OK,如果不支持, -* 返回检测过程中发生异常的结果码: -* 1、DARKSIDE_CANT_FIXED_NT -* 2、DARKSIDE_NACK_NO_SEND -* 3、DARKSIDE_TAG_CHANGED -* 或者其他的卡片相关的通信错误,最常见的是丢失卡片 HF_TAG_NO +* @brief : 判断此卡片是否支持Darkside攻击 +* @retval : 如果支持,返回 HF_TAG_OK,如果不支持, +* 返回检测过程中发生异常的结果码: +* 1、DARKSIDE_CANT_FIXED_NT +* 2、DARKSIDE_NACK_NO_SEND +* 3、DARKSIDE_TAG_CHANGED +* 或者其他的卡片相关的通信错误,最常见的是丢失卡片 HF_TAG_NO * */ uint8_t Check_Darkside_Support() { - // 实例化参数 - DarksideCore dc; - // 直接判断并且返回结果 - return Darkside_Recover_Key(0x03, PICC_AUTHENT1A, true, 0x15, &dc); + // 实例化参数 + DarksideCore dc; + // 直接判断并且返回结果 + return Darkside_Recover_Key(0x03, PICC_AUTHENT1A, true, 0x15, &dc); } /** -* @brief : 判断此卡片是否支持M1的验证步骤 -* @retval : 如果支持,将返回HF_TAG_OK, -* 如果不支持,则返回对应的错误码 +* @brief : 判断此卡片是否支持M1的验证步骤 +* @retval : 如果支持,将返回HF_TAG_OK, +* 如果不支持,则返回对应的错误码 * */ uint8_t Check_Tag_Response_NT(picc_14a_tag_t *tag, uint32_t *nt) { - struct Crypto1State mpcs = { 0, 0 }; - struct Crypto1State *pcs = &mpcs; - uint8_t par_recv[4] = { 0x00 }; - uint8_t dat_recv[4] = { 0x00 }; - uint8_t status; - - // 重置卡片通信 - pcd_14a_reader_halt_tag(); - - // 我们进行快速选卡,尽可能的将验证耗时压缩 - if (pcd_14a_reader_scan_auto(tag) != HF_TAG_OK) { - NRF_LOG_INFO("Tag can't select\r\n"); - return HF_TAG_NO; - } - - // 发送指令并且获取NT返回 - *nt = sendcmd(pcs, AUTH_FIRST, PICC_AUTHENT1A, 0x03, &status, dat_recv, par_recv, U8ARR_BIT_LEN(dat_recv)); - if (*nt != 32) { - // dbg_block_printf("No 32 data recv on sendcmd: %d\n", *nt); - return HF_ERRSTAT; - } - *nt = bytes_to_num(dat_recv, 4); - return HF_TAG_OK; + struct Crypto1State mpcs = { 0, 0 }; + struct Crypto1State *pcs = &mpcs; + uint8_t par_recv[4] = { 0x00 }; + uint8_t dat_recv[4] = { 0x00 }; + uint8_t status; + + // 重置卡片通信 + pcd_14a_reader_halt_tag(); + + // 我们进行快速选卡,尽可能的将验证耗时压缩 + if (pcd_14a_reader_scan_auto(tag) != HF_TAG_OK) { + NRF_LOG_INFO("Tag can't select\r\n"); + return HF_TAG_NO; + } + + // 发送指令并且获取NT返回 + *nt = sendcmd(pcs, AUTH_FIRST, PICC_AUTHENT1A, 0x03, &status, dat_recv, par_recv, U8ARR_BIT_LEN(dat_recv)); + if (*nt != 32) { + // dbg_block_printf("No 32 data recv on sendcmd: %d\n", *nt); + return HF_ERRSTAT; + } + *nt = bytes_to_num(dat_recv, 4); + return HF_TAG_OK; } /** -* @brief : 判断此卡片是否支持标签MF三次验证协议 -* @retval : 如果支持,返回 HF_TAG_OK,如果不支持, -* 则返回 HF_ERRSTAT -* 或者其他的卡片相关的通信错误,最常见的是 -* 丢失卡片 HF_TAG_NO 和错误的状态 HF_ERRSTAT +* @brief : 判断此卡片是否支持标签MF三次验证协议 +* @retval : 如果支持,返回 HF_TAG_OK,如果不支持, +* 则返回 HF_ERRSTAT +* 或者其他的卡片相关的通信错误,最常见的是 +* 丢失卡片 HF_TAG_NO 和错误的状态 HF_ERRSTAT * */ uint8_t Check_STDMifareNT_Support() { - uint32_t nt1 = 0; + uint32_t nt1 = 0; - // 寻卡,场内搜索 - if (pcd_14a_reader_scan_auto(p_tag_info) != HF_TAG_OK) { - return HF_TAG_NO; - } + // 寻卡,场内搜索 + if (pcd_14a_reader_scan_auto(p_tag_info) != HF_TAG_OK) { + return HF_TAG_NO; + } - // 获取NT - return Check_Tag_Response_NT(p_tag_info, &nt1); + // 获取NT + return Check_Tag_Response_NT(p_tag_info, &nt1); } /** -* @brief : 判断此卡片是否支持StaticNested攻击 -* @retval : 如果支持,返回 NESTED_TAG_IS_STATIC,如果不支持, -* 则返回 HF_TAG_OK -* 或者其他的卡片相关的通信错误,最常见的是丢失卡片 HF_TAG_NO +* @brief : 判断此卡片是否支持StaticNested攻击 +* @retval : 如果支持,返回 NESTED_TAG_IS_STATIC,如果不支持, +* 则返回 HF_TAG_OK +* 或者其他的卡片相关的通信错误,最常见的是丢失卡片 HF_TAG_NO * */ uint8_t Check_StaticNested_Support() { - uint32_t nt1, nt2; - uint8_t status; - - // 寻卡,场内搜索 - if (pcd_14a_reader_scan_auto(p_tag_info) != HF_TAG_OK) { - return HF_TAG_NO; - } - - // 第一波获取NT - status = Check_Tag_Response_NT(p_tag_info, &nt1); - if (status != HF_TAG_OK) { - return status; - } - - // 获取完成后谨记重置场 - // 如果不重置场的话,某些卡会在场内维持功能时一直提供一个静态的NT - // 因此此处的重置非常重要。 - ResetRadioFieldWithDelay(); - - // 第二波获取NT - status = Check_Tag_Response_NT(p_tag_info, &nt2); - if (status != HF_TAG_OK) { - return status; - } - - // 检测随机数是否是静态的 - if (nt1 == nt2) { - return NESTED_TAG_IS_STATIC; - } - - return HF_TAG_OK; + uint32_t nt1, nt2; + uint8_t status; + + // 寻卡,场内搜索 + if (pcd_14a_reader_scan_auto(p_tag_info) != HF_TAG_OK) { + return HF_TAG_NO; + } + + // 第一波获取NT + status = Check_Tag_Response_NT(p_tag_info, &nt1); + if (status != HF_TAG_OK) { + return status; + } + + // 获取完成后谨记重置场 + // 如果不重置场的话,某些卡会在场内维持功能时一直提供一个静态的NT + // 因此此处的重置非常重要。 + ResetRadioFieldWithDelay(); + + // 第二波获取NT + status = Check_Tag_Response_NT(p_tag_info, &nt2); + if (status != HF_TAG_OK) { + return status; + } + + // 检测随机数是否是静态的 + if (nt1 == nt2) { + return NESTED_TAG_IS_STATIC; + } + + return HF_TAG_OK; } /** -* @brief : 判断此卡片是否支持最普通,最弱,最容易的prng攻击 -* @retval : 判断结果 +* @brief : 判断此卡片是否支持最普通,最弱,最容易的prng攻击 +* @retval : 判断结果 * */ uint8_t Check_WeakNested_Support() { - uint8_t status; - uint32_t nt1; - - status = Check_StaticNested_Support(); - - // 如果判断的过程中,发现并不能完成staticnested的检测 - // 那就直接返回状态,不需要进行下面的判断逻辑了。 - if (status != HF_TAG_OK) { - return status; - } - - // 非static的卡片,还可以继续往下跑逻辑 - // ------------------------------------ - - // 每次重新操作前,都尝试休眠标签 - // 以重置其可能有问题的状态机 - pcd_14a_reader_halt_tag(); - - // 进行寻卡操作 - if (pcd_14a_reader_scan_auto(p_tag_info) != HF_TAG_OK) { - return HF_TAG_NO; - } - - // 获取NT,只需要获取一次 - status = Check_Tag_Response_NT(p_tag_info, &nt1); - if (status != HF_TAG_OK) { - return status; - } - - // 测算NT的有效性 - if (validate_prng_nonce_notable(nt1)) { - // NRF_LOG_INFO("The tag support Nested\n"); - return HF_TAG_OK; - } - // NRF_LOG_INFO("The tag support HardNested\n"); - // NT不可预测,无效。 - - // ------------------------------------ - // end - - return NESTED_TAG_IS_HARD; + uint8_t status; + uint32_t nt1; + + status = Check_StaticNested_Support(); + + // 如果判断的过程中,发现并不能完成staticnested的检测 + // 那就直接返回状态,不需要进行下面的判断逻辑了。 + if (status != HF_TAG_OK) { + return status; + } + + // 非static的卡片,还可以继续往下跑逻辑 + // ------------------------------------ + + // 每次重新操作前,都尝试休眠标签 + // 以重置其可能有问题的状态机 + pcd_14a_reader_halt_tag(); + + // 进行寻卡操作 + if (pcd_14a_reader_scan_auto(p_tag_info) != HF_TAG_OK) { + return HF_TAG_NO; + } + + // 获取NT,只需要获取一次 + status = Check_Tag_Response_NT(p_tag_info, &nt1); + if (status != HF_TAG_OK) { + return status; + } + + // 测算NT的有效性 + if (validate_prng_nonce_notable(nt1)) { + // NRF_LOG_INFO("The tag support Nested\n"); + return HF_TAG_OK; + } + // NRF_LOG_INFO("The tag support HardNested\n"); + // NT不可预测,无效。 + + // ------------------------------------ + // end + + return NESTED_TAG_IS_HARD; } /** -* @brief : 计算两个随机数的距离 -* @param :from : 从哪个随机数开始 -* @param :to : 到哪个随机数结束 -* @retval : 距离值 +* @brief : 计算两个随机数的距离 +* @param :from : 从哪个随机数开始 +* @param :to : 到哪个随机数结束 +* @retval : 距离值 * */ uint32_t measure_nonces(uint32_t from, uint32_t to) { - // 给出初始的坐标值 - uint32_t msb = from >> 16; - uint32_t lsb = to >> 16; - // 传入坐标进行直接运算,并且传出也由传入参数间接传出 - nonce_distance_notable(&msb, &lsb); - return (65535 + lsb - msb) % 65535; + // 给出初始的坐标值 + uint32_t msb = from >> 16; + uint32_t lsb = to >> 16; + // 传入坐标进行直接运算,并且传出也由传入参数间接传出 + nonce_distance_notable(&msb, &lsb); + return (65535 + lsb - msb) % 65535; } /** -* @brief : 中间值测量 -* @param :src : 测量源 -* @param :length : 测量源的个数 -* @retval : 中间值 +* @brief : 中间值测量 +* @param :src : 测量源 +* @param :length : 测量源的个数 +* @retval : 中间值 * */ uint32_t measure_medin(uint32_t *src, uint32_t length) { - uint32_t len = length; - uint32_t minIndex; - uint32_t temp, i; - - if (length == 1) { - return src[0]; - } - - for (i = 0;i < len;i++) { - // i是已排列的序列的末尾 - minIndex = i; - for (int j = i + 1;j < len;j++) { - if (src[j] < src[minIndex]) { - minIndex = j; - } - } - if (minIndex != i) { - temp = src[i]; - src[i] = src[minIndex]; - src[minIndex] = temp; - } - } - return src[length / 2 - 1]; + uint32_t len = length; + uint32_t minIndex; + uint32_t temp, i; + + if (length == 1) { + return src[0]; + } + + for (i = 0;i < len;i++) { + // i是已排列的序列的末尾 + minIndex = i; + for (int j = i + 1;j < len;j++) { + if (src[j] < src[minIndex]) { + minIndex = j; + } + } + if (minIndex != i) { + temp = src[i]; + src[i] = src[minIndex]; + src[minIndex] = temp; + } + } + return src[length / 2 - 1]; } /** -* @brief : 进行Nested攻击前要测量距离,如果距离合适,则可以快速破解 -* @param :u64Key : 卡片的秘钥的U64值 -* @param :block : 验证的块号 -* @param :type : 秘钥类型, 0x60(A秘钥) 或者 0x61(B秘钥) -* @param :distance : 最终的距离 -* @retval : 操作结果 +* @brief : 进行Nested攻击前要测量距离,如果距离合适,则可以快速破解 +* @param :u64Key : 卡片的秘钥的U64值 +* @param :block : 验证的块号 +* @param :type : 秘钥类型, 0x60(A秘钥) 或者 0x61(B秘钥) +* @param :distance : 最终的距离 +* @retval : 操作结果 * */ uint8_t Measure_Distance(uint64_t u64Key, uint8_t block, uint8_t type, uint32_t *distance) { struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs = &mpcs; - uint32_t distances[DIST_NR] = { 0x00 }; - uint32_t uid = get_u32_tag_uid(p_tag_info); + struct Crypto1State *pcs = &mpcs; + uint32_t distances[DIST_NR] = { 0x00 }; + uint32_t uid = get_u32_tag_uid(p_tag_info); uint32_t nt1, nt2; - uint8_t index = 0; - - do { - // 重置卡片通信 - pcd_14a_reader_halt_tag(); - // 我们进行快速选卡,尽可能的将验证耗时压缩 - if (pcd_14a_reader_scan_auto(p_tag_info) != HF_TAG_OK) { - NRF_LOG_INFO("Tag can't select\r\n"); - return HF_TAG_NO; - } - // 进行第一次验证,以便获取未经加密的NT1 - if(authex(pcs, uid, block, type, u64Key, AUTH_FIRST, &nt1) != HF_TAG_OK) { - NRF_LOG_INFO("Auth failed 1\r\n"); - return MF_ERRAUTH; - } - // 进行嵌套验证,以便获取经过加密的NT2_ENC - if(authex(pcs, uid, block, type, u64Key, AUTH_NESTED, &nt2) != HF_TAG_OK) { - NRF_LOG_INFO("Auth failed 2\r\n"); - return MF_ERRAUTH; - } - // 判断两个随机数是否是相同的,正常情况下, - // 我们不可能的带相同的随机数,因为PRNG是随时在更新chip的 - // 如果确实遇到了相同的NT,那么只能说明,这张卡是特殊固件的ST卡 - if (nt1 == nt2) { - NRF_LOG_INFO("StaticNested: %08x vs %08x\n", nt1, nt2); - return NESTED_TAG_IS_STATIC; - } - // 测量完成之后存放到buffer中 - distances[index++] = measure_nonces(nt1, nt2); - // dbg_block_printf("dist = %"PRIu32"\n\n", distances[index - 1]); - } while(index < DIST_NR); - - // 最终计算两个NT的距离并且直接传出 - *distance = measure_medin(distances, DIST_NR); - // 需要返回OK值,以标志任务成功 - return HF_TAG_OK; + uint8_t index = 0; + + do { + // 重置卡片通信 + pcd_14a_reader_halt_tag(); + // 我们进行快速选卡,尽可能的将验证耗时压缩 + if (pcd_14a_reader_scan_auto(p_tag_info) != HF_TAG_OK) { + NRF_LOG_INFO("Tag can't select\r\n"); + return HF_TAG_NO; + } + // 进行第一次验证,以便获取未经加密的NT1 + if(authex(pcs, uid, block, type, u64Key, AUTH_FIRST, &nt1) != HF_TAG_OK) { + NRF_LOG_INFO("Auth failed 1\r\n"); + return MF_ERRAUTH; + } + // 进行嵌套验证,以便获取经过加密的NT2_ENC + if(authex(pcs, uid, block, type, u64Key, AUTH_NESTED, &nt2) != HF_TAG_OK) { + NRF_LOG_INFO("Auth failed 2\r\n"); + return MF_ERRAUTH; + } + // 判断两个随机数是否是相同的,正常情况下, + // 我们不可能的带相同的随机数,因为PRNG是随时在更新chip的 + // 如果确实遇到了相同的NT,那么只能说明,这张卡是特殊固件的ST卡 + if (nt1 == nt2) { + NRF_LOG_INFO("StaticNested: %08x vs %08x\n", nt1, nt2); + return NESTED_TAG_IS_STATIC; + } + // 测量完成之后存放到buffer中 + distances[index++] = measure_nonces(nt1, nt2); + // dbg_block_printf("dist = %"PRIu32"\n\n", distances[index - 1]); + } while(index < DIST_NR); + + // 最终计算两个NT的距离并且直接传出 + *distance = measure_medin(distances, DIST_NR); + // 需要返回OK值,以标志任务成功 + return HF_TAG_OK; } /** -* @brief : Nested核心,用于收集随机数,此函数只负责收集,不负责转换与解析为KS -* @param :pnc : nested 核心结构体,保存相关的通信数据 -* @param :keyKnown : 卡片的已知秘钥的U64值 -* @param :blkKnown : 卡片的已知秘钥的所属扇区 -* @param :typKnown : 卡片的已知秘钥的类型, 0x60(A秘钥) 或者 0x61(B秘钥) -* @param :targetBlock : 需要nested攻击的目标扇区 -* @param :targetType : 需要nested攻击的目标秘钥类型 -* @retval : 成功返回 HF_TAG_OK ,验证不成功返回非 HF_TAG_OK 值 +* @brief : Nested核心,用于收集随机数,此函数只负责收集,不负责转换与解析为KS +* @param :pnc : nested 核心结构体,保存相关的通信数据 +* @param :keyKnown : 卡片的已知秘钥的U64值 +* @param :blkKnown : 卡片的已知秘钥的所属扇区 +* @param :typKnown : 卡片的已知秘钥的类型, 0x60(A秘钥) 或者 0x61(B秘钥) +* @param :targetBlock : 需要nested攻击的目标扇区 +* @param :targetType : 需要nested攻击的目标秘钥类型 +* @retval : 成功返回 HF_TAG_OK ,验证不成功返回非 HF_TAG_OK 值 * */ uint8_t Nested_Recover_Core(NestedCore *pnc, uint64_t keyKnown, uint8_t blkKnown, uint8_t typKnown, uint8_t targetBlock, uint8_t targetType) { struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs = &mpcs; - uint8_t status; - uint8_t parity[4] = {0x00}; - uint8_t answer[4] = {0x00}; - uint32_t uid, nt1; - // 转换UID为U32类型,后面用得上 - uid = get_u32_tag_uid(p_tag_info); - // 重置卡片通信 - pcd_14a_reader_halt_tag(); - // 快速选卡,以便完成验证步骤收集NT1和NT2_ENC - if (pcd_14a_reader_scan_auto(p_tag_info) != HF_TAG_OK) { - return HF_TAG_NO; - } - // 第一步验证,基础验证不需要嵌套加密 - if(authex(pcs, uid, blkKnown, typKnown, keyKnown, AUTH_FIRST, &nt1) != HF_TAG_OK) { - return MF_ERRAUTH; - } - // 然后就是嵌套验证 - if (sendcmd(pcs, AUTH_NESTED, targetType, targetBlock, &status, answer, parity, U8ARR_BIT_LEN(answer)) != 32) { - return HF_ERRSTAT; - }; - // 第一次验证的明文随机数 - num_to_bytes(nt1, 4, pnc->nt1); - // 嵌套验证的被目标扇区的密码加密的随机数 - memcpy(pnc->nt2, answer, 4); - // 保存3个bit的奇偶校验位 - pnc->par = 0; - pnc->par |= ((oddparity8(answer[0]) != parity[0]) << 0); - pnc->par |= ((oddparity8(answer[1]) != parity[1]) << 1); - pnc->par |= ((oddparity8(answer[2]) != parity[2]) << 2); - return HF_TAG_OK; + struct Crypto1State *pcs = &mpcs; + uint8_t status; + uint8_t parity[4] = {0x00}; + uint8_t answer[4] = {0x00}; + uint32_t uid, nt1; + // 转换UID为U32类型,后面用得上 + uid = get_u32_tag_uid(p_tag_info); + // 重置卡片通信 + pcd_14a_reader_halt_tag(); + // 快速选卡,以便完成验证步骤收集NT1和NT2_ENC + if (pcd_14a_reader_scan_auto(p_tag_info) != HF_TAG_OK) { + return HF_TAG_NO; + } + // 第一步验证,基础验证不需要嵌套加密 + if(authex(pcs, uid, blkKnown, typKnown, keyKnown, AUTH_FIRST, &nt1) != HF_TAG_OK) { + return MF_ERRAUTH; + } + // 然后就是嵌套验证 + if (sendcmd(pcs, AUTH_NESTED, targetType, targetBlock, &status, answer, parity, U8ARR_BIT_LEN(answer)) != 32) { + return HF_ERRSTAT; + }; + // 第一次验证的明文随机数 + num_to_bytes(nt1, 4, pnc->nt1); + // 嵌套验证的被目标扇区的密码加密的随机数 + memcpy(pnc->nt2, answer, 4); + // 保存3个bit的奇偶校验位 + pnc->par = 0; + pnc->par |= ((oddparity8(answer[0]) != parity[0]) << 0); + pnc->par |= ((oddparity8(answer[1]) != parity[1]) << 1); + pnc->par |= ((oddparity8(answer[2]) != parity[2]) << 2); + return HF_TAG_OK; } /** -* @brief : Nested默认实现,用于收集 SETS_NR 组随机数,此函数只负责收集,不负责转换与解析为KS -* @param :ncs : nested 核心结构体数组,保存相关的通信数据 -* @param :keyKnown : 卡片的已知秘钥的U64值 -* @param :blkKnown : 卡片的已知秘钥的所属扇区 -* @param :typKnown : 卡片的已知秘钥的类型, 0x60(A秘钥) 或者 0x61(B秘钥) -* @param :targetBlock : 需要nested攻击的目标扇区 -* @param :targetType : 需要nested攻击的目标秘钥类型 -* @retval : 攻击返回 HF_TAG_OK ,攻击不成功返回非 HF_TAG_OK 值 +* @brief : Nested默认实现,用于收集 SETS_NR 组随机数,此函数只负责收集,不负责转换与解析为KS +* @param :ncs : nested 核心结构体数组,保存相关的通信数据 +* @param :keyKnown : 卡片的已知秘钥的U64值 +* @param :blkKnown : 卡片的已知秘钥的所属扇区 +* @param :typKnown : 卡片的已知秘钥的类型, 0x60(A秘钥) 或者 0x61(B秘钥) +* @param :targetBlock : 需要nested攻击的目标扇区 +* @param :targetType : 需要nested攻击的目标秘钥类型 +* @retval : 攻击返回 HF_TAG_OK ,攻击不成功返回非 HF_TAG_OK 值 * */ uint8_t Nested_Recover_Key(uint64_t keyKnown, uint8_t blkKnown, uint8_t typKnown, uint8_t targetBlock, uint8_t targetType, NestedCore ncs[SETS_NR]) { - uint8_t m, res; - // 先寻卡,所有的操作都要基于有卡的情况 - res = pcd_14a_reader_scan_auto(p_tag_info); - if (res!= HF_TAG_OK) { - return res; - } - // 然后采集指定个数的随机数组 - for (m = 0; m < SETS_NR; m++) { - res = Nested_Recover_Core( - &(ncs[m]), - keyKnown, - blkKnown, - typKnown, - targetBlock, - targetType - ); - if (res != HF_TAG_OK) { - return res; - } - } - return HF_TAG_OK; + uint8_t m, res; + // 先寻卡,所有的操作都要基于有卡的情况 + res = pcd_14a_reader_scan_auto(p_tag_info); + if (res!= HF_TAG_OK) { + return res; + } + // 然后采集指定个数的随机数组 + for (m = 0; m < SETS_NR; m++) { + res = Nested_Recover_Core( + &(ncs[m]), + keyKnown, + blkKnown, + typKnown, + targetBlock, + targetType + ); + if (res != HF_TAG_OK) { + return res; + } + } + return HF_TAG_OK; } /** -* @brief : Nested 距离探测实现 -* @param :block : 卡片的已知秘钥的所属扇区 -* @param :type : 卡片的已知秘钥的类型, 0x60(A秘钥) 或者 0x61(B秘钥) -* @param :key : 卡片的已知秘钥的U64值 -* @param :nd : 随机数距离的探测结果 -* @retval : 操作状态值 +* @brief : Nested 距离探测实现 +* @param :block : 卡片的已知秘钥的所属扇区 +* @param :type : 卡片的已知秘钥的类型, 0x60(A秘钥) 或者 0x61(B秘钥) +* @param :key : 卡片的已知秘钥的U64值 +* @param :nd : 随机数距离的探测结果 +* @retval : 操作状态值 * */ uint8_t Nested_Distacne_Detect(uint8_t block, uint8_t type, uint8_t *key, NestedDist *nd) { - uint8_t status = HF_TAG_OK; - uint32_t distance = 0; - // 必须要确保场内有卡 - status = pcd_14a_reader_scan_auto(p_tag_info); - if (status != HF_TAG_OK) { + uint8_t status = HF_TAG_OK; + uint32_t distance = 0; + // 必须要确保场内有卡 + status = pcd_14a_reader_scan_auto(p_tag_info); + if (status != HF_TAG_OK) { return status; } else { // 至少卡片是存在的,可以先复制UID到缓冲区 get_4byte_tag_uid(p_tag_info, nd->uid); } - // 获取距离,为接下来的攻击做准备 - status = Measure_Distance( - bytes_to_num(key, 6), - block, - type, - &distance - ); + // 获取距离,为接下来的攻击做准备 + status = Measure_Distance( + bytes_to_num(key, 6), + block, + type, + &distance + ); // 一切正常,我们需要将距离值放入结果中 - if (status == HF_TAG_OK) { - num_to_bytes(distance, 4, nd->distance); - } - return status; + if (status == HF_TAG_OK) { + num_to_bytes(distance, 4, nd->distance); + } + return status; } /** -* @brief : 使用基于RC522的M1算法模块去验证密钥 -* @retval : 验证结果 +* @brief : 使用基于RC522的M1算法模块去验证密钥 +* @retval : 验证结果 * */ uint8_t auth_key_use_522_hw(uint8_t block, uint8_t type, uint8_t* key) { - // 每次验证一个block都要重新寻卡 - if (pcd_14a_reader_scan_auto(p_tag_info) != HF_TAG_OK) { - return HF_TAG_NO; - } - // 寻到卡后我们开始验证! - return pcd_14a_reader_mf1_auth(p_tag_info, type, block, key); + // 每次验证一个block都要重新寻卡 + if (pcd_14a_reader_scan_auto(p_tag_info) != HF_TAG_OK) { + return HF_TAG_NO; + } + // 寻到卡后我们开始验证! + return pcd_14a_reader_mf1_auth(p_tag_info, type, block, key); } diff --git a/firmware/application/src/rfid/reader/hf/mf1_toolbox.h b/firmware/application/src/rfid/reader/hf/mf1_toolbox.h index 9cbe0a55..dcac3801 100644 --- a/firmware/application/src/rfid/reader/hf/mf1_toolbox.h +++ b/firmware/application/src/rfid/reader/hf/mf1_toolbox.h @@ -8,35 +8,35 @@ #include -#define SETS_NR 2 // 使用几组随机数探针,至少是2个能确保有两组随机数组合进行交集查询,这个值越大越容易成功 -#define DIST_NR 3 // 越多的距离值越能准确判断当前卡片的通信稳定性 +#define SETS_NR 2 // 使用几组随机数探针,至少是2个能确保有两组随机数组合进行交集查询,这个值越大越容易成功 +#define DIST_NR 3 // 越多的距离值越能准确判断当前卡片的通信稳定性 // mifare authentication -#define CRYPT_NONE 0 -#define CRYPT_ALL 1 -#define CRYPT_REQUEST 2 -#define AUTH_FIRST 0 -#define AUTH_NESTED 2 +#define CRYPT_NONE 0 +#define CRYPT_ALL 1 +#define CRYPT_REQUEST 2 +#define AUTH_FIRST 0 +#define AUTH_NESTED 2 -typedef struct { // 应答 nested 攻击需要的 距离参数 - uint8_t uid[4]; // 这个距离数据的所属UID的U32部分 - uint8_t distance[4]; // 未经加密的明文随机数 +typedef struct { // 应答 nested 攻击需要的 距离参数 + uint8_t uid[4]; // 这个距离数据的所属UID的U32部分 + uint8_t distance[4]; // 未经加密的明文随机数 } NestedDist; -typedef struct { // 应答 nested 攻击需要的 随机数参数 - uint8_t nt1[4]; // 未经加密的明文随机数 - uint8_t nt2[4]; // 嵌套验证加密的随机数 - uint8_t par; // 嵌套验证加密的通信过程的奇偶校验位,只用到了 '低3位',也就是右3位 +typedef struct { // 应答 nested 攻击需要的 随机数参数 + uint8_t nt1[4]; // 未经加密的明文随机数 + uint8_t nt2[4]; // 嵌套验证加密的随机数 + uint8_t par; // 嵌套验证加密的通信过程的奇偶校验位,只用到了 '低3位',也就是右3位 } NestedCore; typedef struct { - uint8_t uid[4]; - uint8_t nt[4]; - uint8_t par_list[8]; - uint8_t ks_list[8]; - uint8_t nr[4]; - uint8_t ar[4]; + uint8_t uid[4]; + uint8_t nt[4]; + uint8_t par_list[8]; + uint8_t ks_list[8]; + uint8_t nr[4]; + uint8_t ar[4]; } DarksideCore; @@ -46,17 +46,17 @@ extern "C" { uint8_t Darkside_Recover_Key( - uint8_t targetBlk, - uint8_t targetTyp, - uint8_t firstRecover, - uint8_t ntSyncMax, - DarksideCore* dc + uint8_t targetBlk, + uint8_t targetTyp, + uint8_t firstRecover, + uint8_t ntSyncMax, + DarksideCore* dc ); uint8_t Nested_Distacne_Detect( - uint8_t block, - uint8_t type, - uint8_t *key, - NestedDist *nd + uint8_t block, + uint8_t type, + uint8_t *key, + NestedDist *nd ); uint8_t Nested_Recover_Key( uint64_t keyKnown, diff --git a/firmware/application/src/rfid/reader/hf/rc522.c b/firmware/application/src/rfid/reader/hf/rc522.c index 05ee4fbd..defdd868 100644 --- a/firmware/application/src/rfid/reader/hf/rc522.c +++ b/firmware/application/src/rfid/reader/hf/rc522.c @@ -36,7 +36,7 @@ static autotimer* g_timeout_auto_timer; // RC522使用的SPI #define SPI_INSTANCE 0 /**< SPI instance index. */ -static const nrf_drv_spi_t s_spiHandle = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE); // SPI instance +static const nrf_drv_spi_t s_spiHandle = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE); // SPI instance #define ONCE_OPT __attribute__((optimize("O3"))) @@ -47,7 +47,7 @@ static const nrf_drv_spi_t s_spiHandle = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE); // */ uint8_t read_register_single(uint8_t Address) { - RC522_DOSEL; + RC522_DOSEL; Address = (uint8_t)(((Address << 1) & 0x7E) | 0x80); @@ -61,16 +61,16 @@ uint8_t read_register_single(uint8_t Address) NRF_SPI0->EVENTS_READY = 0; Address = NRF_SPI0->RXD; - RC522_UNSEL; + RC522_UNSEL; - return Address; + return Address; } void read_register_buffer(uint8_t Address, uint8_t *pInBuffer, uint8_t len) { - RC522_DOSEL; + RC522_DOSEL; - Address = (((Address << 1) & 0x7E) | 0x80); + Address = (((Address << 1) & 0x7E) | 0x80); NRF_SPI0->TXD = Address; while ( NRF_SPI0->EVENTS_READY == 0 ); // 等待传输结束 @@ -86,19 +86,19 @@ void read_register_buffer(uint8_t Address, uint8_t *pInBuffer, uint8_t len) pInBuffer[i] = NRF_SPI0->RXD; // 读取一次,给一个电平 } while(++i < len); - RC522_UNSEL; + RC522_UNSEL; } /** * @brief :写寄存器 * @param :Address:寄存器地址 -* value: 将要写入的值 +* value: 将要写入的值 */ void ONCE_OPT write_register_single(uint8_t Address, uint8_t value) { - RC522_DOSEL; + RC522_DOSEL; - Address = ((Address << 1) & 0x7E); + Address = ((Address << 1) & 0x7E); // 先传地址 NRF_SPI0->TXD = Address; @@ -112,14 +112,14 @@ void ONCE_OPT write_register_single(uint8_t Address, uint8_t value) NRF_SPI0->EVENTS_READY = 0; (void)NRF_SPI0->RXD; - RC522_UNSEL; + RC522_UNSEL; } void write_register_buffer(uint8_t Address, uint8_t *values, uint8_t len) { - RC522_DOSEL; + RC522_DOSEL; - Address = ((Address << 1) & 0x7E); + Address = ((Address << 1) & 0x7E); NRF_SPI0->TXD = Address; while ( NRF_SPI0->EVENTS_READY == 0 ); @@ -135,27 +135,27 @@ void write_register_buffer(uint8_t Address, uint8_t *values, uint8_t len) (void)NRF_SPI0->RXD; } while(++i < len); - RC522_UNSEL; + RC522_UNSEL; } /** * @brief :寄存器功能开关 * @param :reg:寄存器地址 -* mask: 开关范围 +* mask: 开关范围 */ inline void set_register_mask(uint8_t reg, uint8_t mask) { - write_register_single(reg, read_register_single(reg) | mask); // set bit mask + write_register_single(reg, read_register_single(reg) | mask); // set bit mask } /** * @brief :寄存器功能开关 * @param :reg:寄存器地址 -* mask: 开关范围 +* mask: 开关范围 */ inline void clear_register_mask(uint8_t reg, uint8_t mask) { - write_register_single(reg, read_register_single(reg) & ~mask); // clear bit mask + write_register_single(reg, read_register_single(reg) & ~mask); // clear bit mask } /** @@ -164,32 +164,32 @@ inline void clear_register_mask(uint8_t reg, uint8_t mask) */ void pcd_14a_reader_init(void) { - // 确保只初始化一次 - if (!m_reader_is_init) { - // 标志为已经初始化状态 - m_reader_is_init = true; - - // 初始化NSS脚GPIO - nrf_gpio_cfg_output(HF_SPI_SELECT); - - // 初始化SPI - ret_code_t errCode; - - nrf_drv_spi_config_t spiConfig = NRF_DRV_SPI_DEFAULT_CONFIG; // 使用SPI默认配置 - // 配置SPI端口,注意CSN不要在这设置,另外用GPIO口控制 - spiConfig.miso_pin = HF_SPI_MISO; - spiConfig.mosi_pin = HF_SPI_MOSI; - spiConfig.sck_pin = HF_SPI_SCK; - spiConfig.mode = NRF_DRV_SPI_MODE_0; - spiConfig.frequency = NRF_DRV_SPI_FREQ_8M; - // 配置为堵塞型操作 - errCode = nrf_drv_spi_init(&s_spiHandle, &spiConfig, NULL, NULL); - APP_ERROR_CHECK(errCode); - - // 初始化定时器 - // 这个定时器初始化后就不释放了,始终需要占用着 - g_timeout_auto_timer = bsp_obtain_timer(0); - } + // 确保只初始化一次 + if (!m_reader_is_init) { + // 标志为已经初始化状态 + m_reader_is_init = true; + + // 初始化NSS脚GPIO + nrf_gpio_cfg_output(HF_SPI_SELECT); + + // 初始化SPI + ret_code_t errCode; + + nrf_drv_spi_config_t spiConfig = NRF_DRV_SPI_DEFAULT_CONFIG; // 使用SPI默认配置 + // 配置SPI端口,注意CSN不要在这设置,另外用GPIO口控制 + spiConfig.miso_pin = HF_SPI_MISO; + spiConfig.mosi_pin = HF_SPI_MOSI; + spiConfig.sck_pin = HF_SPI_SCK; + spiConfig.mode = NRF_DRV_SPI_MODE_0; + spiConfig.frequency = NRF_DRV_SPI_FREQ_8M; + // 配置为堵塞型操作 + errCode = nrf_drv_spi_init(&s_spiHandle, &spiConfig, NULL, NULL); + APP_ERROR_CHECK(errCode); + + // 初始化定时器 + // 这个定时器初始化后就不释放了,始终需要占用着 + g_timeout_auto_timer = bsp_obtain_timer(0); + } } /** @@ -198,28 +198,28 @@ void pcd_14a_reader_init(void) */ void pcd_14a_reader_reset(void) { - // 确保已经初始化再进行通信与软重置 - if (m_reader_is_init) { - // 软重置 522 - write_register_single(CommandReg, PCD_IDLE); - write_register_single(CommandReg, PCD_RESET); - - // 开关天线 - clear_register_mask(TxControlReg, 0x03); - set_register_mask(TxControlReg, 0x03); - - // 禁用522的定时器,使用MCU的定时器超时 - write_register_single(TModeReg, 0x00); - - // 调制发送信号为100%ASK - write_register_single(TxAutoReg, 0x40); - // 定义发送和接收常用模式 和Mifare卡通讯,CRC初始值0x6363 - write_register_single(ModeReg, 0x3D); - - // 然后默认不使能天线 - // 请不要持续使能高频的天线 - pcd_14a_reader_antenna_off(); - } + // 确保已经初始化再进行通信与软重置 + if (m_reader_is_init) { + // 软重置 522 + write_register_single(CommandReg, PCD_IDLE); + write_register_single(CommandReg, PCD_RESET); + + // 开关天线 + clear_register_mask(TxControlReg, 0x03); + set_register_mask(TxControlReg, 0x03); + + // 禁用522的定时器,使用MCU的定时器超时 + write_register_single(TModeReg, 0x00); + + // 调制发送信号为100%ASK + write_register_single(TxAutoReg, 0x40); + // 定义发送和接收常用模式 和Mifare卡通讯,CRC初始值0x6363 + write_register_single(ModeReg, 0x3D); + + // 然后默认不使能天线 + // 请不要持续使能高频的天线 + pcd_14a_reader_antenna_off(); + } } /** @@ -228,12 +228,12 @@ void pcd_14a_reader_reset(void) */ void pcd_14a_reader_uninit(void) { - // 确保已经初始化过设备了,再进行反初始化 - if (m_reader_is_init) { + // 确保已经初始化过设备了,再进行反初始化 + if (m_reader_is_init) { m_reader_is_init = false; - bsp_return_timer(g_timeout_auto_timer); - nrf_drv_spi_uninit(&s_spiHandle); - } + bsp_return_timer(g_timeout_auto_timer); + nrf_drv_spi_uninit(&s_spiHandle); + } } /** @@ -244,7 +244,7 @@ void pcd_14a_reader_uninit(void) */ void pcd_14a_reader_timeout_set(uint16_t timeout_ms) { - g_com_timeout_ms = timeout_ms; + g_com_timeout_ms = timeout_ms; } /** @@ -253,7 +253,7 @@ void pcd_14a_reader_timeout_set(uint16_t timeout_ms) * @retval 超时值 */ uint16_t pcd_14a_reader_timeout_get() { - return g_com_timeout_ms; + return g_com_timeout_ms; } /** @@ -267,230 +267,230 @@ uint16_t pcd_14a_reader_timeout_get() { */ uint8_t pcd_14a_reader_bytes_transfer(uint8_t Command, uint8_t* pIn, uint8_t InLenByte, uint8_t* pOut, uint16_t* pOutLenBit, uint16_t maxOutLenBit) { - uint8_t status = HF_ERRSTAT; - uint8_t waitFor = 0x00; - uint8_t lastBits = 0; - uint8_t n = 0; - uint8_t pcd_err_val = 0; - uint8_t not_timeout = 0; - // 重置接收到的数据的长度 - *pOutLenBit = 0; - - switch(Command) { - case PCD_AUTHENT: // Mifare认证 - waitFor = 0x10; // 认证寻卡等待时候 查询空闲中断标志位 - break; - - case PCD_TRANSCEIVE: - waitFor = 0x30; // 寻卡等待时候 查询接收中断标志位与 空闲中断标志位 - break; - } - - write_register_single(CommandReg, PCD_IDLE); // 置位FlushBuffer清除内部FIFO的读和写指针以及ErrReg的BufferOvfl标志位被清除 - clear_register_mask(ComIrqReg, 0x80); // Set1该位清零时,CommIRqReg的屏蔽位清零 - set_register_mask(FIFOLevelReg, 0x80); // 写空闲命令 - - write_register_buffer(FIFODataReg, pIn, InLenByte); // 写数据进FIFOdata - write_register_single(CommandReg, Command); // 写命令 - - if (Command == PCD_TRANSCEIVE) { - set_register_mask(BitFramingReg, 0x80); // StartSend置位启动数据发送 该位与收发命令使用时才有效 - } - - if (pOut == NULL) { - // 如果开发者不需要接收数据,那么在发送完成后直接返回! - while((read_register_single(Status2Reg) & 0x07) == 0x03); - return HF_TAG_OK; - } - - bsp_set_timer(g_timeout_auto_timer, 0); // 在启动操作前先归零超时计数器 - - do { - n = read_register_single(ComIrqReg); // 读取通信中断寄存器,判断当前的IO任务是否完成! - not_timeout = NO_TIMEOUT_1MS(g_timeout_auto_timer, g_com_timeout_ms); - } while (not_timeout && (!(n & waitFor))); // 退出条件:超时中断,与写空闲命令中断 - // NRF_LOG_INFO("N = %02x\n", n); - - if (Command == PCD_TRANSCEIVE) { - clear_register_mask(BitFramingReg, 0x80); // 清理允许StartSend位与比特长度位 - } - - // 是否接收超时 - if (not_timeout) { - // 先判断是否有错误寄存器的置位 - if (n & 0x02) { - // 有错误发生 - // 读错误标志寄存器 BufferOfI CollErr ParityErr ProtocolErr - pcd_err_val = read_register_single(ErrorReg); - // 检测接收是否有异常 - if (pcd_err_val & 0x01) { // ProtocolErr 错误仅在下述两种情况下出现: - if (Command == PCD_AUTHENT) { // 在MFAuthent命令执行期间,若一个数据流收到的字节数错误则该位置位 - // 因此我们需要处理好,假设是验证过程中出现问题,那么我们需要认为此乃正常情况 - status = MF_ERRAUTH; - } else { // 如果SOF出错,则该位置位,接收器启动阶段自动清零,仅在106kBd速率下有效 - NRF_LOG_INFO("Protocol error\n"); - status = HF_ERRSTAT; - } - } else if (pcd_err_val & 0x02) { - // 检测是否有奇偶错误 - NRF_LOG_INFO("Parity error\n"); - status = HF_ERRPARITY; - } else if (pcd_err_val & 0x04) { // 检测是否有CRC错误 - NRF_LOG_INFO("CRC error\n"); - status = HF_ERRCRC; - } else if (pcd_err_val & 0x08) { // 检测标签是否有冲突 - NRF_LOG_INFO("Collision tag\n"); - status = HF_COLLISION; - } else { // 有其他的未处理的异常 - NRF_LOG_INFO("HF error: 0x%0x2\n", pcd_err_val); - status = HF_ERRSTAT; - } - } else { - // 无错误发生 - // NRF_LOG_INFO("COM OK\n"); - if (Command == PCD_TRANSCEIVE) { - n = read_register_single(FIFOLevelReg); // 读FIFO中保存的字节数 - if (n == 0) { n = 1; } - - lastBits = read_register_single(Control522Reg) & 0x07; // 最后接收到得字节的有效位数 - - if (lastBits) { *pOutLenBit = (n - 1) * 8 + lastBits; } // N个字节数减去1(最后一个字节)+ 最后一位的位数 读取到的数据总位数 - else { *pOutLenBit = n * 8; } // 最后接收到的字节整个字节有效 - - if (*pOutLenBit <= maxOutLenBit) { - // 将FIFO中的所有数据读取出来 - read_register_buffer(FIFODataReg, pOut, n); - // 传输指令,读到正常的数据才能认为成功! - status = HF_TAG_OK; - } else { - NRF_LOG_INFO("pcd_14a_reader_bytes_transfer receive response overflow: %d, max = %d\n", *pOutLenBit, maxOutLenBit); - // 我们不能把有问题的数据传出去,这暂时没意义 - *pOutLenBit = 0; - // 既然数据有问题,那就直接通知上层,告知一下 - status = HF_ERRSTAT; - } - } else { - // 非传输指令,执行完成无错误就认为成功! - status = HF_TAG_OK; - } - } - } else { - status = HF_TAG_NO; - // NRF_LOG_INFO("Tag lost(timeout).\n"); - } - - if (status != HF_TAG_OK) { - // 如果有某些操作异常的话, - // 我们可能需要清除 MFCrypto1On 这个寄存器标志, - // 因为可能是因为验证过导致的错误加密的通信 - clear_register_mask(Status2Reg, 0x08); - } - - // NRF_LOG_INFO("Com status: %d\n", status); - return status; + uint8_t status = HF_ERRSTAT; + uint8_t waitFor = 0x00; + uint8_t lastBits = 0; + uint8_t n = 0; + uint8_t pcd_err_val = 0; + uint8_t not_timeout = 0; + // 重置接收到的数据的长度 + *pOutLenBit = 0; + + switch(Command) { + case PCD_AUTHENT: // Mifare认证 + waitFor = 0x10; // 认证寻卡等待时候 查询空闲中断标志位 + break; + + case PCD_TRANSCEIVE: + waitFor = 0x30; // 寻卡等待时候 查询接收中断标志位与 空闲中断标志位 + break; + } + + write_register_single(CommandReg, PCD_IDLE); // 置位FlushBuffer清除内部FIFO的读和写指针以及ErrReg的BufferOvfl标志位被清除 + clear_register_mask(ComIrqReg, 0x80); // Set1该位清零时,CommIRqReg的屏蔽位清零 + set_register_mask(FIFOLevelReg, 0x80); // 写空闲命令 + + write_register_buffer(FIFODataReg, pIn, InLenByte); // 写数据进FIFOdata + write_register_single(CommandReg, Command); // 写命令 + + if (Command == PCD_TRANSCEIVE) { + set_register_mask(BitFramingReg, 0x80); // StartSend置位启动数据发送 该位与收发命令使用时才有效 + } + + if (pOut == NULL) { + // 如果开发者不需要接收数据,那么在发送完成后直接返回! + while((read_register_single(Status2Reg) & 0x07) == 0x03); + return HF_TAG_OK; + } + + bsp_set_timer(g_timeout_auto_timer, 0); // 在启动操作前先归零超时计数器 + + do { + n = read_register_single(ComIrqReg); // 读取通信中断寄存器,判断当前的IO任务是否完成! + not_timeout = NO_TIMEOUT_1MS(g_timeout_auto_timer, g_com_timeout_ms); + } while (not_timeout && (!(n & waitFor))); // 退出条件:超时中断,与写空闲命令中断 + // NRF_LOG_INFO("N = %02x\n", n); + + if (Command == PCD_TRANSCEIVE) { + clear_register_mask(BitFramingReg, 0x80); // 清理允许StartSend位与比特长度位 + } + + // 是否接收超时 + if (not_timeout) { + // 先判断是否有错误寄存器的置位 + if (n & 0x02) { + // 有错误发生 + // 读错误标志寄存器 BufferOfI CollErr ParityErr ProtocolErr + pcd_err_val = read_register_single(ErrorReg); + // 检测接收是否有异常 + if (pcd_err_val & 0x01) { // ProtocolErr 错误仅在下述两种情况下出现: + if (Command == PCD_AUTHENT) { // 在MFAuthent命令执行期间,若一个数据流收到的字节数错误则该位置位 + // 因此我们需要处理好,假设是验证过程中出现问题,那么我们需要认为此乃正常情况 + status = MF_ERRAUTH; + } else { // 如果SOF出错,则该位置位,接收器启动阶段自动清零,仅在106kBd速率下有效 + NRF_LOG_INFO("Protocol error\n"); + status = HF_ERRSTAT; + } + } else if (pcd_err_val & 0x02) { + // 检测是否有奇偶错误 + NRF_LOG_INFO("Parity error\n"); + status = HF_ERRPARITY; + } else if (pcd_err_val & 0x04) { // 检测是否有CRC错误 + NRF_LOG_INFO("CRC error\n"); + status = HF_ERRCRC; + } else if (pcd_err_val & 0x08) { // 检测标签是否有冲突 + NRF_LOG_INFO("Collision tag\n"); + status = HF_COLLISION; + } else { // 有其他的未处理的异常 + NRF_LOG_INFO("HF error: 0x%0x2\n", pcd_err_val); + status = HF_ERRSTAT; + } + } else { + // 无错误发生 + // NRF_LOG_INFO("COM OK\n"); + if (Command == PCD_TRANSCEIVE) { + n = read_register_single(FIFOLevelReg); // 读FIFO中保存的字节数 + if (n == 0) { n = 1; } + + lastBits = read_register_single(Control522Reg) & 0x07; // 最后接收到得字节的有效位数 + + if (lastBits) { *pOutLenBit = (n - 1) * 8 + lastBits; } // N个字节数减去1(最后一个字节)+ 最后一位的位数 读取到的数据总位数 + else { *pOutLenBit = n * 8; } // 最后接收到的字节整个字节有效 + + if (*pOutLenBit <= maxOutLenBit) { + // 将FIFO中的所有数据读取出来 + read_register_buffer(FIFODataReg, pOut, n); + // 传输指令,读到正常的数据才能认为成功! + status = HF_TAG_OK; + } else { + NRF_LOG_INFO("pcd_14a_reader_bytes_transfer receive response overflow: %d, max = %d\n", *pOutLenBit, maxOutLenBit); + // 我们不能把有问题的数据传出去,这暂时没意义 + *pOutLenBit = 0; + // 既然数据有问题,那就直接通知上层,告知一下 + status = HF_ERRSTAT; + } + } else { + // 非传输指令,执行完成无错误就认为成功! + status = HF_TAG_OK; + } + } + } else { + status = HF_TAG_NO; + // NRF_LOG_INFO("Tag lost(timeout).\n"); + } + + if (status != HF_TAG_OK) { + // 如果有某些操作异常的话, + // 我们可能需要清除 MFCrypto1On 这个寄存器标志, + // 因为可能是因为验证过导致的错误加密的通信 + clear_register_mask(Status2Reg, 0x08); + } + + // NRF_LOG_INFO("Com status: %d\n", status); + return status; } /** * @brief :通过RC522和ISO14443卡通讯 * @param -* pTx :通过RC522发送到卡片的数据 -* szTxBits :发送数据的比特长度 -* pTxPar : 发送数据的奇偶校验位 -* pRx :存放解包后的卡片回应的数据的缓冲区 -* pRxPar :存放卡片回应的奇偶校验数据的缓冲区 +* pTx :通过RC522发送到卡片的数据 +* szTxBits :发送数据的比特长度 +* pTxPar : 发送数据的奇偶校验位 +* pRx :存放解包后的卡片回应的数据的缓冲区 +* pRxPar :存放卡片回应的奇偶校验数据的缓冲区 * @retval :成功的时候返回卡片回应的数据的比特长度, - 失败的时候返回对应的错误码。 + 失败的时候返回对应的错误码。 */ uint8_t pcd_14a_reader_bits_transfer(uint8_t* pTx, uint16_t szTxBits, uint8_t* pTxPar, uint8_t* pRx, uint8_t* pRxPar, uint16_t* pRxLenBit, uint16_t szRxLenBitMax) { - static uint8_t buffer[DEF_FIFO_LENGTH]; - uint8_t status = 0, - modulus = 0, - i = 0, - dataLen = 0; - - buffer[0] = pTx[0]; - if (szTxBits > 8) { - // 判断到需要合并奇偶校验到数据流中 - if (pTxPar != NULL) { - // 几个字节就需要几个bit,因此会 - // 多出对应字节个数的bit的数据 - modulus = dataLen = szTxBits / 8; - buffer[1] = (pTxPar[0] | (pTx[1] << 1)); - for( i = 2; i < dataLen; i++ ) { - // add the remaining prev byte and parity - buffer[i] = ((pTxPar[i - 1] << (i - 1)) | (pTx[ i - 1] >> (9 - i))); - // add next byte and push i bits - buffer[i] |= (pTx[i] << i); - } - // add remainder of last byte + end parity - buffer[dataLen] = ((pTxPar[dataLen - 1] << (i - 1)) | (pTx[dataLen-1] >> (9 - i))); - dataLen += 1; - } else { - modulus = szTxBits % 8; - dataLen = modulus > 0 ? (szTxBits / 8 + 1) : (szTxBits / 8); - // 不需要合并奇偶校验位,就当做是外部已经做好了此处理 - for( i = 1; i < dataLen; i++ ) { - buffer[i] = pTx[i]; - } - } - } else { - dataLen = 1; - modulus = szTxBits; - } - - set_register_mask(BitFramingReg, modulus); // 设置最后一个字节传输N位 - set_register_mask(MfRxReg, 0x10); // 需要关闭奇偶校验位的使能 - - status = pcd_14a_reader_bytes_transfer( - PCD_TRANSCEIVE, - buffer, - dataLen, // 数据的字节计数 - buffer, // 接收缓冲区 - pRxLenBit, // 接收到的数据的长度,注意,是比特流的长度 - U8ARR_BIT_LEN(buffer) // 能收的数据的上限长度 - ); - - clear_register_mask(BitFramingReg, modulus); - clear_register_mask(MfRxReg, 0x10); // 使能奇偶校验位 - - // 单纯判断数据传输的长度 - if (status != HF_TAG_OK) { - // NRF_LOG_INFO("pcd_14a_reader_bytes_transfer error status: %d\n", status); - return status; - } - - pRx[0] = buffer[0]; - modulus = 0; - if (*pRxLenBit > 8) { - // 取余,等下要用来统计字节数 - modulus = *pRxLenBit % 8; - // 取字节数,等下要用来解包 - dataLen = *pRxLenBit / 8 + (modulus > 0); - // 取比特数,这个是最终的数据的长度 - *pRxLenBit = *pRxLenBit - modulus; - - // 进一步判断数据解码之后是否会溢出 - if (*pRxLenBit > szRxLenBitMax) { - NRF_LOG_INFO("pcd_14a_reader_bits_transfer decode parity data overflow: %d, max = %d\n", *pRxLenBit, szRxLenBitMax); - // 此处也要在出现溢出有,重置有效接收的数据的长度,避免外部调用者以此误判 - *pRxLenBit = 0; - return HF_ERRSTAT; - } - - // 最终的奇偶校验与数据的分离解包过程 - for(i = 1; i < dataLen - 1; i++) { - if (pRxPar != NULL) { - pRxPar[i - 1] = (buffer[i] & (1 << (i - 1))) >> (i - 1); - } - pRx[i] = (buffer[i] >> i) | (buffer[i + 1] << (8 - i)); - } - if (pRxPar != NULL) { - pRxPar[i - 1] = (buffer[i] & (1 << (i - 1)) ) >> (i - 1); - } - } - return HF_TAG_OK; + static uint8_t buffer[DEF_FIFO_LENGTH]; + uint8_t status = 0, + modulus = 0, + i = 0, + dataLen = 0; + + buffer[0] = pTx[0]; + if (szTxBits > 8) { + // 判断到需要合并奇偶校验到数据流中 + if (pTxPar != NULL) { + // 几个字节就需要几个bit,因此会 + // 多出对应字节个数的bit的数据 + modulus = dataLen = szTxBits / 8; + buffer[1] = (pTxPar[0] | (pTx[1] << 1)); + for( i = 2; i < dataLen; i++ ) { + // add the remaining prev byte and parity + buffer[i] = ((pTxPar[i - 1] << (i - 1)) | (pTx[ i - 1] >> (9 - i))); + // add next byte and push i bits + buffer[i] |= (pTx[i] << i); + } + // add remainder of last byte + end parity + buffer[dataLen] = ((pTxPar[dataLen - 1] << (i - 1)) | (pTx[dataLen-1] >> (9 - i))); + dataLen += 1; + } else { + modulus = szTxBits % 8; + dataLen = modulus > 0 ? (szTxBits / 8 + 1) : (szTxBits / 8); + // 不需要合并奇偶校验位,就当做是外部已经做好了此处理 + for( i = 1; i < dataLen; i++ ) { + buffer[i] = pTx[i]; + } + } + } else { + dataLen = 1; + modulus = szTxBits; + } + + set_register_mask(BitFramingReg, modulus); // 设置最后一个字节传输N位 + set_register_mask(MfRxReg, 0x10); // 需要关闭奇偶校验位的使能 + + status = pcd_14a_reader_bytes_transfer( + PCD_TRANSCEIVE, + buffer, + dataLen, // 数据的字节计数 + buffer, // 接收缓冲区 + pRxLenBit, // 接收到的数据的长度,注意,是比特流的长度 + U8ARR_BIT_LEN(buffer) // 能收的数据的上限长度 + ); + + clear_register_mask(BitFramingReg, modulus); + clear_register_mask(MfRxReg, 0x10); // 使能奇偶校验位 + + // 单纯判断数据传输的长度 + if (status != HF_TAG_OK) { + // NRF_LOG_INFO("pcd_14a_reader_bytes_transfer error status: %d\n", status); + return status; + } + + pRx[0] = buffer[0]; + modulus = 0; + if (*pRxLenBit > 8) { + // 取余,等下要用来统计字节数 + modulus = *pRxLenBit % 8; + // 取字节数,等下要用来解包 + dataLen = *pRxLenBit / 8 + (modulus > 0); + // 取比特数,这个是最终的数据的长度 + *pRxLenBit = *pRxLenBit - modulus; + + // 进一步判断数据解码之后是否会溢出 + if (*pRxLenBit > szRxLenBitMax) { + NRF_LOG_INFO("pcd_14a_reader_bits_transfer decode parity data overflow: %d, max = %d\n", *pRxLenBit, szRxLenBitMax); + // 此处也要在出现溢出有,重置有效接收的数据的长度,避免外部调用者以此误判 + *pRxLenBit = 0; + return HF_ERRSTAT; + } + + // 最终的奇偶校验与数据的分离解包过程 + for(i = 1; i < dataLen - 1; i++) { + if (pRxPar != NULL) { + pRxPar[i - 1] = (buffer[i] & (1 << (i - 1))) >> (i - 1); + } + pRx[i] = (buffer[i] >> i) | (buffer[i + 1] << (8 - i)); + } + if (pRxPar != NULL) { + pRxPar[i - 1] = (buffer[i] & (1 << (i - 1)) ) >> (i - 1); + } + } + return HF_TAG_OK; } /** @@ -499,29 +499,29 @@ uint8_t pcd_14a_reader_bits_transfer(uint8_t* pTx, uint16_t szTxBits, uint8_t* * @retval :状态值HF_TAG_OK,成功 */ uint8_t pcd_14a_reader_scan_once(picc_14a_tag_t *tag) { - // 初始化关键的参数 - if (tag) { - tag->uid_len = 0; - memset(tag->uid, 0, 10); + // 初始化关键的参数 + if (tag) { + tag->uid_len = 0; + memset(tag->uid, 0, 10); } else { - return STATUS_PAR_ERR; // 寻卡不允许不传入标签信息结构体 - } + return STATUS_PAR_ERR; // 寻卡不允许不传入标签信息结构体 + } - // 唤醒 + // 唤醒 if (pcd_14a_reader_atqa_request(tag->atqa, NULL, U8ARR_BIT_LEN(tag->atqa)) != HF_TAG_OK) { - // NRF_LOG_INFO("pcd_14a_reader_atqa_request HF_TAG_NO\r\n"); - return HF_TAG_NO; - } + // NRF_LOG_INFO("pcd_14a_reader_atqa_request HF_TAG_NO\r\n"); + return HF_TAG_NO; + } uint8_t resp[DEF_FIFO_LENGTH] = {0}; // theoretically. A usual RATS will be much smaller // uint8_t resp_par[MAX_PARITY_SIZE] = {0}; - uint16_t len; - uint8_t status; + uint16_t len; + uint8_t status; uint8_t do_cascade = 1; uint8_t cascade_level = 0; - // OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in + // OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in // which case we need to make a cascade 2 request and select - this is a long UID // While the UID is not complete, the 3nd bit (from the right) is set in the SAK. for (; do_cascade; cascade_level++) { @@ -531,49 +531,49 @@ uint8_t pcd_14a_reader_scan_once(picc_14a_tag_t *tag) { uint8_t uid_resp[5] = {0}; // UID + original BCC sel_uid[0] = sel_all[0] = PICC_ANTICOLL1 + cascade_level * 2; - // 发送防冲撞指令 - status = pcd_14a_reader_bytes_transfer(PCD_TRANSCEIVE, sel_all, sizeof(sel_all), resp, &len, U8ARR_BIT_LEN(resp)); - - // 出现标签冲撞,我们需要解决冲撞 - if (status != HF_TAG_OK) { - // 该冲撞还是得冲撞,解密过程中还是不要有这种情况发生 - // 所以暂时不去解决冲撞,而是直接告知用户,让用户保证场内只有一张卡 - NRF_LOG_INFO("Err at tag collision.\n"); - return status; - } else { // no collision, use the response to SELECT_ALL as current uid - memcpy(uid_resp, resp, 5); // UID + original BCC - } + // 发送防冲撞指令 + status = pcd_14a_reader_bytes_transfer(PCD_TRANSCEIVE, sel_all, sizeof(sel_all), resp, &len, U8ARR_BIT_LEN(resp)); + + // 出现标签冲撞,我们需要解决冲撞 + if (status != HF_TAG_OK) { + // 该冲撞还是得冲撞,解密过程中还是不要有这种情况发生 + // 所以暂时不去解决冲撞,而是直接告知用户,让用户保证场内只有一张卡 + NRF_LOG_INFO("Err at tag collision.\n"); + return status; + } else { // no collision, use the response to SELECT_ALL as current uid + memcpy(uid_resp, resp, 5); // UID + original BCC + } - uint8_t uid_resp_len = 4; + uint8_t uid_resp_len = 4; - // 永远使用最后的UID段当做u32类型的UID, - // 不管是几字节的UID段 - // *u32Uid = bytes_to_num(uid_resp, 4); + // 永远使用最后的UID段当做u32类型的UID, + // 不管是几字节的UID段 + // *u32Uid = bytes_to_num(uid_resp, 4); - // Construct SELECT UID command + // Construct SELECT UID command sel_uid[1] = 0x70; // transmitting a full UID (1 Byte cmd, 1 Byte NVB, 4 Byte UID, 1 Byte BCC, 2 Bytes CRC) - memcpy(sel_uid + 2, uid_resp, 5); // the UID received during anticollision with original BCC - uint8_t bcc = sel_uid[2] ^ sel_uid[3] ^ sel_uid[4] ^ sel_uid[5]; // calculate BCC - if (sel_uid[6] != bcc) { - NRF_LOG_INFO("BCC%d incorrect, got 0x%02x, expected 0x%02x\n", cascade_level, sel_uid[6], bcc); - return HF_ERRBCC; - } + memcpy(sel_uid + 2, uid_resp, 5); // the UID received during anticollision with original BCC + uint8_t bcc = sel_uid[2] ^ sel_uid[3] ^ sel_uid[4] ^ sel_uid[5]; // calculate BCC + if (sel_uid[6] != bcc) { + NRF_LOG_INFO("BCC%d incorrect, got 0x%02x, expected 0x%02x\n", cascade_level, sel_uid[6], bcc); + return HF_ERRBCC; + } - crc_14a_append(sel_uid, 7); // calculate and add CRC + crc_14a_append(sel_uid, 7); // calculate and add CRC - // 发送 9x 70 去选卡 + // 发送 9x 70 去选卡 status = pcd_14a_reader_bytes_transfer(PCD_TRANSCEIVE, sel_uid, sizeof(sel_uid), resp, &len, U8ARR_BIT_LEN(resp)); - if (status != HF_TAG_OK) { - NRF_LOG_INFO("Err at sak receive.\n"); - return HF_ERRSTAT; - } + if (status != HF_TAG_OK) { + NRF_LOG_INFO("Err at sak receive.\n"); + return HF_ERRSTAT; + } - // 缓冲接收到的SAK - tag->sak = resp[0]; + // 缓冲接收到的SAK + tag->sak = resp[0]; - // 如果UID是以 0X88 的形式开头的,说明UID还不完整 - // 下次循环我们需要进行递增级联,返回结束防冲撞,完成级联 + // 如果UID是以 0X88 的形式开头的,说明UID还不完整 + // 下次循环我们需要进行递增级联,返回结束防冲撞,完成级联 do_cascade = (((tag->sak & 0x04) /* && uid_resp[0] == 0x88 */) > 0); if (do_cascade) { // Remove first byte, 0x88 is not an UID byte, it CT, see page 3 of: @@ -584,14 +584,14 @@ uint8_t pcd_14a_reader_scan_once(picc_14a_tag_t *tag) { uid_resp_len = 3; } - // 拷贝卡片的UID信息到传入的结构体中 - memcpy(tag->uid + (cascade_level * 3), uid_resp, uid_resp_len); - tag->uid_len += uid_resp_len; - // 级联只有 1 2 3 三种,对应 4 7 10 字节的卡号 - // 因此需要在下标为0的基础上 + 1 - tag->cascade = cascade_level + 1; - } - return HF_TAG_OK; + // 拷贝卡片的UID信息到传入的结构体中 + memcpy(tag->uid + (cascade_level * 3), uid_resp, uid_resp_len); + tag->uid_len += uid_resp_len; + // 级联只有 1 2 3 三种,对应 4 7 10 字节的卡号 + // 因此需要在下标为0的基础上 + 1 + tag->cascade = cascade_level + 1; + } + return HF_TAG_OK; } /** @@ -600,22 +600,22 @@ uint8_t pcd_14a_reader_scan_once(picc_14a_tag_t *tag) { * @retval :状态值HF_TAG_OK,成功 */ uint8_t pcd_14a_reader_scan_auto(picc_14a_tag_t *tag) { - uint8_t status; - - // 第一次寻卡 - status = pcd_14a_reader_scan_once(tag); - if (status == HF_TAG_OK) { - return HF_TAG_OK; - } - - // 第二次寻卡 - status = pcd_14a_reader_scan_once(tag); - if (status == HF_TAG_OK) { - return HF_TAG_OK; - } - - // 超过上限次数 - return status; + uint8_t status; + + // 第一次寻卡 + status = pcd_14a_reader_scan_once(tag); + if (status == HF_TAG_OK) { + return HF_TAG_OK; + } + + // 第二次寻卡 + status = pcd_14a_reader_scan_once(tag); + if (status == HF_TAG_OK) { + return HF_TAG_OK; + } + + // 超过上限次数 + return status; } /** @@ -625,19 +625,19 @@ uint8_t pcd_14a_reader_scan_auto(picc_14a_tag_t *tag) { * @retval :状态值HF_TAG_OK,成功 */ uint8_t pcd_14a_reader_ats_request(uint8_t *pAts, uint16_t *szAts, uint16_t szAtsBitMax) { - uint8_t rats[] = { PICC_RATS, 0x80, 0x31, 0x73 }; // FSD=256, FSDI=8, CID=0 - uint8_t status; + uint8_t rats[] = { PICC_RATS, 0x80, 0x31, 0x73 }; // FSD=256, FSDI=8, CID=0 + uint8_t status; - status = pcd_14a_reader_bytes_transfer(PCD_TRANSCEIVE, rats, sizeof(rats), pAts, szAts, szAtsBitMax); + status = pcd_14a_reader_bytes_transfer(PCD_TRANSCEIVE, rats, sizeof(rats), pAts, szAts, szAtsBitMax); - if (status != HF_TAG_OK) { - NRF_LOG_INFO("Err at ats receive.\n"); - return status; - } + if (status != HF_TAG_OK) { + NRF_LOG_INFO("Err at ats receive.\n"); + return status; + } - // NRF_LOG_INFO("Length: %d\n", *szAts); + // NRF_LOG_INFO("Length: %d\n", *szAts); - if (*szAts > 0) { *szAts = *szAts / 8; } + if (*szAts > 0) { *szAts = *szAts / 8; } return HF_TAG_OK; } @@ -647,106 +647,106 @@ uint8_t pcd_14a_reader_ats_request(uint8_t *pAts, uint16_t *szAts, uint16_t szAt * @retval :状态值HF_TAG_OK,成功 */ uint8_t pcd_14a_reader_atqa_request(uint8_t *resp, uint8_t *resp_par, uint16_t resp_max_bit) { - uint16_t len = 0; + uint16_t len = 0; uint8_t retry = 0; - uint8_t status = HF_TAG_OK; - uint8_t wupa[] = { PICC_REQALL }; // 0x26 - REQA 0x52 - WAKE-UP + uint8_t status = HF_TAG_OK; + uint8_t wupa[] = { PICC_REQALL }; // 0x26 - REQA 0x52 - WAKE-UP // we may need several tries if we did send an unknown command or a wrong authentication before... do { // Broadcast for a card, WUPA (0x52) will force response from all cards in the field and Receive the ATQA status = pcd_14a_reader_bits_transfer(wupa, 7, NULL, resp, resp_par, &len, resp_max_bit); - // NRF_LOG_INFO("pcd_14a_reader_atqa_request len: %d\n", len); + // NRF_LOG_INFO("pcd_14a_reader_atqa_request len: %d\n", len); } while (len != 16 && (retry++ < 10)); - // 正常的 ATQA 是2字节,也就是16bit的, - // 我们需要进行判断,收到的数据是否正确 - if (status == HF_TAG_OK && len == 16) { - // 可以确认当前场内存在至少一张14A的卡了 - return HF_TAG_OK; - } + // 正常的 ATQA 是2字节,也就是16bit的, + // 我们需要进行判断,收到的数据是否正确 + if (status == HF_TAG_OK && len == 16) { + // 可以确认当前场内存在至少一张14A的卡了 + return HF_TAG_OK; + } - // 不存在卡片 + // 不存在卡片 return HF_TAG_NO; } /** * @brief : 解锁GEN1A后门卡以进行非标准M1操作步骤 -* 注意,解锁之后不要halt卡片,后门指令的生命周期只存在于当次解锁后的 -* 数据块读写操作范围内,如果发生场掉电或卡片被halt或者重新防冲撞, -* 将会失去后门权限,需要调用此函数重新启动。 +* 注意,解锁之后不要halt卡片,后门指令的生命周期只存在于当次解锁后的 +* 数据块读写操作范围内,如果发生场掉电或卡片被halt或者重新防冲撞, +* 将会失去后门权限,需要调用此函数重新启动。 * * @retval :状态值 HF_TAG_OK,解锁成功,其他状态值表示解锁失败 */ uint8_t pcd_14a_reader_gen1a_unlock(void) { - // 初始化变量 - uint8_t unlock, status; - uint16_t rx_length = 0; - uint8_t recvbuf[1] = { 0x00 }; - - // 重启通信(非常重要) - pcd_14a_reader_halt_tag(); - - // 第一步解锁,发送7bit的 0x40 - unlock = PICC_MAGICWUPC1; - status = pcd_14a_reader_bits_transfer(&unlock, 7, NULL, recvbuf, NULL, &rx_length, U8ARR_BIT_LEN(recvbuf)); - if (!(status == HF_TAG_OK && rx_length == 4 && recvbuf[0] == 0x0A)) { - NRF_LOG_INFO("UNLOCK(MAGICWUPC1) FAILED! Length: %d, Status: %02x\n", rx_length, status); - return HF_ERRSTAT; - } - - // 第二步解锁,发送整字节的 0x43 - unlock = PICC_MAGICWUPC2; - status = pcd_14a_reader_bytes_transfer(PCD_TRANSCEIVE, &unlock, 1, recvbuf, &rx_length, U8ARR_BIT_LEN(recvbuf)); - if (!(status == HF_TAG_OK && rx_length == 4 && recvbuf[0] == 0x0A)) { - NRF_LOG_INFO("UNLOCK(MAGICWUPC2) FAILED! Length: %d, Status: %02x\n", rx_length, status); - return HF_ERRSTAT; - } - - // 两次解锁都没问题,我们默认这次解锁操作成功! - return HF_TAG_OK; + // 初始化变量 + uint8_t unlock, status; + uint16_t rx_length = 0; + uint8_t recvbuf[1] = { 0x00 }; + + // 重启通信(非常重要) + pcd_14a_reader_halt_tag(); + + // 第一步解锁,发送7bit的 0x40 + unlock = PICC_MAGICWUPC1; + status = pcd_14a_reader_bits_transfer(&unlock, 7, NULL, recvbuf, NULL, &rx_length, U8ARR_BIT_LEN(recvbuf)); + if (!(status == HF_TAG_OK && rx_length == 4 && recvbuf[0] == 0x0A)) { + NRF_LOG_INFO("UNLOCK(MAGICWUPC1) FAILED! Length: %d, Status: %02x\n", rx_length, status); + return HF_ERRSTAT; + } + + // 第二步解锁,发送整字节的 0x43 + unlock = PICC_MAGICWUPC2; + status = pcd_14a_reader_bytes_transfer(PCD_TRANSCEIVE, &unlock, 1, recvbuf, &rx_length, U8ARR_BIT_LEN(recvbuf)); + if (!(status == HF_TAG_OK && rx_length == 4 && recvbuf[0] == 0x0A)) { + NRF_LOG_INFO("UNLOCK(MAGICWUPC2) FAILED! Length: %d, Status: %02x\n", rx_length, status); + return HF_ERRSTAT; + } + + // 两次解锁都没问题,我们默认这次解锁操作成功! + return HF_TAG_OK; } /** * @brief : 对UFUID卡进行上锁操作,封锁后门指令,使其成为普通卡,不响应后门指令 -* 这个操作成功的前提是: -* 1、已经调用 pcd_14a_reader_gen1a_unlock() 函数解锁卡片成功 -* 2、卡片具有 UFUID 卡的封后门指令功能 +* 这个操作成功的前提是: +* 1、已经调用 pcd_14a_reader_gen1a_unlock() 函数解锁卡片成功 +* 2、卡片具有 UFUID 卡的封后门指令功能 * * @retval :状态值 HF_TAG_OK,封卡或者存在封卡后门, - 其他状态值表示封卡失败或者没有封卡后门 + 其他状态值表示封卡失败或者没有封卡后门 */ uint8_t pcd_14a_reader_gen1a_uplock(void) { - uint8_t status; - uint16_t rx_length = 0; - - // 我们已知的双层封卡指令 - uint8_t uplock_1[] = { 0xE1, 0x00, 0xE1, 0xEE }; - uint8_t uplock_2[] = { 0x85, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x08, - 0x18, 0x47 - }; - - uint8_t recvbuf[1] = { 0x00 }; - - status = pcd_14a_reader_bytes_transfer(PCD_TRANSCEIVE, uplock_1, sizeof(uplock_1), recvbuf, &rx_length, U8ARR_BIT_LEN(recvbuf)); - if (!(status == HF_TAG_OK && rx_length == 4 && recvbuf[0] == 0x0A)) { - NRF_LOG_INFO("UPLOCK1(UFUID) FAILED!\n"); - return HF_ERRSTAT; - } - - status = pcd_14a_reader_bytes_transfer(PCD_TRANSCEIVE, uplock_2, sizeof(uplock_2), recvbuf, &rx_length, U8ARR_BIT_LEN(recvbuf)); - if (!(status == HF_TAG_OK && rx_length == 4 && recvbuf[0] == 0x0A)) { - NRF_LOG_INFO("UPLOCK2(UFUID) FAILED!\n"); - return HF_ERRSTAT; - } - - // 封卡成功 - return HF_TAG_OK; + uint8_t status; + uint16_t rx_length = 0; + + // 我们已知的双层封卡指令 + uint8_t uplock_1[] = { 0xE1, 0x00, 0xE1, 0xEE }; + uint8_t uplock_2[] = { 0x85, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, + 0x18, 0x47 + }; + + uint8_t recvbuf[1] = { 0x00 }; + + status = pcd_14a_reader_bytes_transfer(PCD_TRANSCEIVE, uplock_1, sizeof(uplock_1), recvbuf, &rx_length, U8ARR_BIT_LEN(recvbuf)); + if (!(status == HF_TAG_OK && rx_length == 4 && recvbuf[0] == 0x0A)) { + NRF_LOG_INFO("UPLOCK1(UFUID) FAILED!\n"); + return HF_ERRSTAT; + } + + status = pcd_14a_reader_bytes_transfer(PCD_TRANSCEIVE, uplock_2, sizeof(uplock_2), recvbuf, &rx_length, U8ARR_BIT_LEN(recvbuf)); + if (!(status == HF_TAG_OK && rx_length == 4 && recvbuf[0] == 0x0A)) { + NRF_LOG_INFO("UPLOCK2(UFUID) FAILED!\n"); + return HF_ERRSTAT; + } + + // 封卡成功 + return HF_TAG_OK; } /** @@ -761,134 +761,134 @@ uint8_t pcd_14a_reader_gen1a_uplock(void) */ uint8_t pcd_14a_reader_mf1_auth(picc_14a_tag_t *tag, uint8_t type, uint8_t addr, uint8_t* pKey) { - uint8_t dat_buff[12] = { type, addr }; - uint16_t data_len = 0; + uint8_t dat_buff[12] = { type, addr }; + uint16_t data_len = 0; - memcpy(&dat_buff[2], pKey, 6); - get_4byte_tag_uid(tag, &dat_buff[8]); + memcpy(&dat_buff[2], pKey, 6); + get_4byte_tag_uid(tag, &dat_buff[8]); - pcd_14a_reader_bytes_transfer(PCD_AUTHENT, dat_buff, 12, dat_buff, &data_len, U8ARR_BIT_LEN(dat_buff)); + pcd_14a_reader_bytes_transfer(PCD_AUTHENT, dat_buff, 12, dat_buff, &data_len, U8ARR_BIT_LEN(dat_buff)); - // 为了提高兼容性,我们此处直接判断执行完成 PCD_AUTHENT - // 指令之后,Status2Reg中的通信加密位是否被置位就行了。 - if (read_register_single(Status2Reg) & 0x08) { - return HF_TAG_OK; - } + // 为了提高兼容性,我们此处直接判断执行完成 PCD_AUTHENT + // 指令之后,Status2Reg中的通信加密位是否被置位就行了。 + if (read_register_single(Status2Reg) & 0x08) { + return HF_TAG_OK; + } - // 其他的情况都认为失败! - return MF_ERRAUTH; + // 其他的情况都认为失败! + return MF_ERRAUTH; } /** * @brief :取消已经校验的密钥的状态 */ void pcd_14a_reader_mf1_unauth(void) { - clear_register_mask(Status2Reg, 0x08); + clear_register_mask(Status2Reg, 0x08); } /** * @brief :读取M1卡的指定块地址的数据 * @param :cmd : 读块指令 -* addr:块地址 -* p :读出的数据,16字节 +* addr:块地址 +* p :读出的数据,16字节 * @retval :状态值HF_TAG_OK,成功 */ uint8_t pcd_14a_reader_mf1_read_by_cmd(uint8_t cmd, uint8_t addr, uint8_t* p) { - uint8_t status; - uint16_t len; - uint8_t dat_buff[MAX_MIFARE_FRAME_SIZE] = { cmd, addr }; - uint8_t crc_buff[DEF_CRC_LENGTH] = { 0x00 }; - - // 短数据直接让 MCU 计算 - crc_14a_append(dat_buff, 2); - // 然后发起通信 - status = pcd_14a_reader_bytes_transfer(PCD_TRANSCEIVE, dat_buff, 4, dat_buff, &len, U8ARR_BIT_LEN(dat_buff)); - if (status == HF_TAG_OK) - { - if (len == 0x90 /* 0x90 = 144bits */) { - // 16字节长度的CRC数据,为了不浪费CPU性能, - // 我们可以让 522 去计算 - crc_14a_calculate(dat_buff, 16, crc_buff); - // 校验一下CRC,避免数据出错 - if ((crc_buff[0] != dat_buff[16]) || (crc_buff[1] != dat_buff[17])) { - status = HF_ERRCRC; - } - // 虽然 CRC 校验有毛病,但是我们还是可以回传 - // 读取到的卡片数据,因为开发者有可能有特殊用法 - memcpy(p, dat_buff, 16); - } else { - // 传回来的数据有毛病,可能是环境因素或者卡片不遵守规范! - // 又或者是控制位影响到了读取! - status = HF_ERRSTAT; - } - } - return status; + uint8_t status; + uint16_t len; + uint8_t dat_buff[MAX_MIFARE_FRAME_SIZE] = { cmd, addr }; + uint8_t crc_buff[DEF_CRC_LENGTH] = { 0x00 }; + + // 短数据直接让 MCU 计算 + crc_14a_append(dat_buff, 2); + // 然后发起通信 + status = pcd_14a_reader_bytes_transfer(PCD_TRANSCEIVE, dat_buff, 4, dat_buff, &len, U8ARR_BIT_LEN(dat_buff)); + if (status == HF_TAG_OK) + { + if (len == 0x90 /* 0x90 = 144bits */) { + // 16字节长度的CRC数据,为了不浪费CPU性能, + // 我们可以让 522 去计算 + crc_14a_calculate(dat_buff, 16, crc_buff); + // 校验一下CRC,避免数据出错 + if ((crc_buff[0] != dat_buff[16]) || (crc_buff[1] != dat_buff[17])) { + status = HF_ERRCRC; + } + // 虽然 CRC 校验有毛病,但是我们还是可以回传 + // 读取到的卡片数据,因为开发者有可能有特殊用法 + memcpy(p, dat_buff, 16); + } else { + // 传回来的数据有毛病,可能是环境因素或者卡片不遵守规范! + // 又或者是控制位影响到了读取! + status = HF_ERRSTAT; + } + } + return status; } /** * @brief :读取M1卡的指定块地址的数据 * @param :addr:块地址 -* p :读出的数据,16字节 +* p :读出的数据,16字节 * @retval :状态值HF_TAG_OK,成功 */ uint8_t pcd_14a_reader_mf1_read(uint8_t addr, uint8_t* p) { - // 标准的M1规范内的读卡 - return pcd_14a_reader_mf1_read_by_cmd(PICC_READ, addr, p); + // 标准的M1规范内的读卡 + return pcd_14a_reader_mf1_read_by_cmd(PICC_READ, addr, p); } /** * @brief :在M1卡的指定块地址写入指定数据 * @param :cmd : 写块指令 -* addr:块地址 -* p :写入的数据,16字节 +* addr:块地址 +* p :写入的数据,16字节 * * @retval :状态值HF_TAG_OK,成功 */ uint8_t pcd_14a_reader_mf1_write_by_cmd(uint8_t cmd, uint8_t addr, uint8_t* p) { - uint8_t status; - uint16_t dat_len; - - // 准备写卡数据,用于发起写卡 - uint8_t dat_buff[18] = { cmd, addr }; - crc_14a_append(dat_buff, 2); - - // NRF_LOG_INFO("0 pcd_14a_reader_mf1_write addr = %d\r\n", addr); - - // 请求写卡,此时,卡片应当回复ACK - status = pcd_14a_reader_bytes_transfer(PCD_TRANSCEIVE, dat_buff, 4, dat_buff, &dat_len, U8ARR_BIT_LEN(dat_buff)); - // 通信失败,直接返回原因 - if (status != HF_TAG_OK) { - return status; - } - // 通信成功,但是操作被卡片拒绝! - if ((dat_len != 4) || ((dat_buff[0] & 0x0F) != 0x0A)) { - // NRF_LOG_INFO("1 status = %d, datalen = %d, data = %02x\n", status, dat_len, dat_buff[0]); - status = HF_ERRSTAT; - } - // 通信成功,卡片接受了写卡操作 - if (status == HF_TAG_OK) { - // 1、拷贝数据并且计算 CRC - memcpy(dat_buff, p, 16); - crc_14a_calculate(dat_buff, 16, &dat_buff[16]); - - // NRF_LOG_INFO_hex("Will send: ", (uint8_t *)p, 16); - // NRF_LOG_INFO("\n"); - - // 2、传输最终的写卡数据完成写卡 - status = pcd_14a_reader_bytes_transfer(PCD_TRANSCEIVE, dat_buff, 18, dat_buff, &dat_len, U8ARR_BIT_LEN(dat_buff)); - // 通信失败,直接返回原因 - if (status != HF_TAG_OK) { - return status; - } - // 通信成功,我们需要判断卡片接收到数据后是否成功处理 - // 并且回复ACK - if ((dat_len != 4) || ((dat_buff[0] & 0x0F) != 0x0A)) { - // NRF_LOG_INFO("2 status = %d, datalen = %d, data = %02x\n", status, dat_len, dat_buff[0]); - status = HF_ERRSTAT; - } - } - return status; + uint8_t status; + uint16_t dat_len; + + // 准备写卡数据,用于发起写卡 + uint8_t dat_buff[18] = { cmd, addr }; + crc_14a_append(dat_buff, 2); + + // NRF_LOG_INFO("0 pcd_14a_reader_mf1_write addr = %d\r\n", addr); + + // 请求写卡,此时,卡片应当回复ACK + status = pcd_14a_reader_bytes_transfer(PCD_TRANSCEIVE, dat_buff, 4, dat_buff, &dat_len, U8ARR_BIT_LEN(dat_buff)); + // 通信失败,直接返回原因 + if (status != HF_TAG_OK) { + return status; + } + // 通信成功,但是操作被卡片拒绝! + if ((dat_len != 4) || ((dat_buff[0] & 0x0F) != 0x0A)) { + // NRF_LOG_INFO("1 status = %d, datalen = %d, data = %02x\n", status, dat_len, dat_buff[0]); + status = HF_ERRSTAT; + } + // 通信成功,卡片接受了写卡操作 + if (status == HF_TAG_OK) { + // 1、拷贝数据并且计算 CRC + memcpy(dat_buff, p, 16); + crc_14a_calculate(dat_buff, 16, &dat_buff[16]); + + // NRF_LOG_INFO_hex("Will send: ", (uint8_t *)p, 16); + // NRF_LOG_INFO("\n"); + + // 2、传输最终的写卡数据完成写卡 + status = pcd_14a_reader_bytes_transfer(PCD_TRANSCEIVE, dat_buff, 18, dat_buff, &dat_len, U8ARR_BIT_LEN(dat_buff)); + // 通信失败,直接返回原因 + if (status != HF_TAG_OK) { + return status; + } + // 通信成功,我们需要判断卡片接收到数据后是否成功处理 + // 并且回复ACK + if ((dat_len != 4) || ((dat_buff[0] & 0x0F) != 0x0A)) { + // NRF_LOG_INFO("2 status = %d, datalen = %d, data = %02x\n", status, dat_len, dat_buff[0]); + status = HF_ERRSTAT; + } + } + return status; } /** @@ -899,8 +899,8 @@ uint8_t pcd_14a_reader_mf1_write_by_cmd(uint8_t cmd, uint8_t addr, uint8_t* p) { */ uint8_t pcd_14a_reader_mf1_write(uint8_t addr, uint8_t* p) { - // 标准的M1规范内的写卡 - return pcd_14a_reader_mf1_write_by_cmd(PICC_WRITE, addr, p); + // 标准的M1规范内的写卡 + return pcd_14a_reader_mf1_write_by_cmd(PICC_WRITE, addr, p); } /** @@ -910,12 +910,12 @@ uint8_t pcd_14a_reader_mf1_write(uint8_t addr, uint8_t* p) */ uint8_t pcd_14a_reader_halt_tag(void) { - uint8_t status; - uint16_t unLen; - // 直接准备好成型的数据了,还计算个鬼的CRC - uint8_t data[] = { PICC_HALT, 0x00, 0x57, 0xCD }; - status = pcd_14a_reader_bytes_transfer(PCD_TRANSCEIVE, data, 4, data, &unLen, U8ARR_BIT_LEN(data)); - return status == HF_TAG_NO && unLen == 0; + uint8_t status; + uint16_t unLen; + // 直接准备好成型的数据了,还计算个鬼的CRC + uint8_t data[] = { PICC_HALT, 0x00, 0x57, 0xCD }; + status = pcd_14a_reader_bytes_transfer(PCD_TRANSCEIVE, data, 4, data, &unLen, U8ARR_BIT_LEN(data)); + return status == HF_TAG_NO && unLen == 0; } /** @@ -925,8 +925,8 @@ uint8_t pcd_14a_reader_halt_tag(void) */ void pcd_14a_reader_fast_halt_tag(void) { - uint8_t data[] = { PICC_HALT, 0x00, 0x57, 0xCD }; - pcd_14a_reader_bytes_transfer(PCD_TRANSCEIVE, data, 4, NULL, NULL, U8ARR_BIT_LEN(data)); + uint8_t data[] = { PICC_HALT, 0x00, 0x57, 0xCD }; + pcd_14a_reader_bytes_transfer(PCD_TRANSCEIVE, data, 4, NULL, NULL, U8ARR_BIT_LEN(data)); } /** @@ -938,28 +938,28 @@ void pcd_14a_reader_fast_halt_tag(void) */ void pcd_14a_reader_calc_crc(uint8_t* pbtData, size_t szLen, uint8_t* pbtCrc) { - uint8_t i, n; - - // 重置状态机 - clear_register_mask(Status1Reg, 0x20); - write_register_single(CommandReg, PCD_IDLE); - set_register_mask(FIFOLevelReg, 0x80); - - // 向FIFO写入要计算CRC的数据 - write_register_buffer(FIFODataReg, pbtData, szLen); - write_register_single(CommandReg, PCD_CALCCRC); - - // 等待计算完成 - i = szLen * 2; - do - { - n = read_register_single(Status1Reg); - i--; - } while ((i != 0) && !(n & 0x20)); - - // 获得最终计算出来的CRC数据 - pbtCrc[0] = read_register_single(CRCResultRegL); - pbtCrc[1] = read_register_single(CRCResultRegM); + uint8_t i, n; + + // 重置状态机 + clear_register_mask(Status1Reg, 0x20); + write_register_single(CommandReg, PCD_IDLE); + set_register_mask(FIFOLevelReg, 0x80); + + // 向FIFO写入要计算CRC的数据 + write_register_buffer(FIFODataReg, pbtData, szLen); + write_register_single(CommandReg, PCD_CALCCRC); + + // 等待计算完成 + i = szLen * 2; + do + { + n = read_register_single(Status1Reg); + i--; + } while ((i != 0) && !(n & 0x20)); + + // 获得最终计算出来的CRC数据 + pbtCrc[0] = read_register_single(CRCResultRegL); + pbtCrc[1] = read_register_single(CRCResultRegM); } /** @@ -967,7 +967,7 @@ void pcd_14a_reader_calc_crc(uint8_t* pbtData, size_t szLen, uint8_t* pbtCrc) */ inline void pcd_14a_reader_antenna_on(void) { - set_register_mask(TxControlReg, 0x03); + set_register_mask(TxControlReg, 0x03); } /** @@ -975,101 +975,101 @@ inline void pcd_14a_reader_antenna_on(void) */ inline void pcd_14a_reader_antenna_off(void) { - clear_register_mask(TxControlReg, 0x03); + clear_register_mask(TxControlReg, 0x03); } /** * @brief :奇偶校验位启用 */ inline void pcd_14a_reader_parity_on(void) { - clear_register_mask(MfRxReg, 0x10); + clear_register_mask(MfRxReg, 0x10); } /** * @brief :奇偶校验位关闭 */ inline void pcd_14a_reader_parity_off(void) { - set_register_mask(MfRxReg, 0x10); + set_register_mask(MfRxReg, 0x10); } /** -* @brief : 获得级联命令,输入只允许存在三种情况 -* 1 表示第一次级联,命令是 PICC_ANTICOLL1 -* 2 表示第二次级联,命令是 PICC_ANTICOLL2 -* 3 表示第三次级联,命令是 PICC_ANTICOLL3 -* @param :len : 存放数值的缓冲区的字节长度 -* @param :src : 存放数值的字节缓冲区 -* @retval : 转换结果 +* @brief : 获得级联命令,输入只允许存在三种情况 +* 1 表示第一次级联,命令是 PICC_ANTICOLL1 +* 2 表示第二次级联,命令是 PICC_ANTICOLL2 +* 3 表示第三次级联,命令是 PICC_ANTICOLL3 +* @param :len : 存放数值的缓冲区的字节长度 +* @param :src : 存放数值的字节缓冲区 +* @retval : 转换结果 * */ uint8_t cascade_to_cmd(uint8_t cascade) { - uint8_t ret = PICC_ANTICOLL1; - switch(cascade) { - case 1: - ret = PICC_ANTICOLL1; - break; - - case 2: - ret = PICC_ANTICOLL2; - break; - - case 3: - ret = PICC_ANTICOLL3; - break; - } - return ret; + uint8_t ret = PICC_ANTICOLL1; + switch(cascade) { + case 1: + ret = PICC_ANTICOLL1; + break; + + case 2: + ret = PICC_ANTICOLL2; + break; + + case 3: + ret = PICC_ANTICOLL3; + break; + } + return ret; } /** -* @brief : 获得标签的4字节类型的UID,根据传入的基础卡片信息决定 -* 1 表示一次级联,UID有 4 字节,直接使用全部的 -* 2 表示二次级联,UID有 7 字节,使用后四位 -* 3 表示三次级联,UID有 10 字节,使用后四位 -* @param :tag : 存放卡片信息的结构体 -* @param :pUid : 存放结果的字节缓冲区 -* @retval : 返回实际上我们搜索到的有效UID字节的起始地址, +* @brief : 获得标签的4字节类型的UID,根据传入的基础卡片信息决定 +* 1 表示一次级联,UID有 4 字节,直接使用全部的 +* 2 表示二次级联,UID有 7 字节,使用后四位 +* 3 表示三次级联,UID有 10 字节,使用后四位 +* @param :tag : 存放卡片信息的结构体 +* @param :pUid : 存放结果的字节缓冲区 +* @retval : 返回实际上我们搜索到的有效UID字节的起始地址, * 注意:此地址可能是指向栈中的,不保证一定是全局有效的地址, * 此地址根据 tag 处于的内存位置决定生命周期。 * */ uint8_t* get_4byte_tag_uid(picc_14a_tag_t *tag, uint8_t *pUid) { - uint8_t *p_TmpUid = NULL; - switch(tag->cascade) { - case 1: - p_TmpUid = tag->uid; - break; - - case 2: - p_TmpUid = tag->uid + 3; - break; - - case 3: - p_TmpUid = tag->uid + 6; - break; - } - if (pUid != NULL) { - memcpy(pUid, p_TmpUid, 4); - } + uint8_t *p_TmpUid = NULL; + switch(tag->cascade) { + case 1: + p_TmpUid = tag->uid; + break; + + case 2: + p_TmpUid = tag->uid + 3; + break; + + case 3: + p_TmpUid = tag->uid + 6; + break; + } + if (pUid != NULL) { + memcpy(pUid, p_TmpUid, 4); + } return p_TmpUid; } /** -* @brief : 获得标签的U32类型的UID,根据传入的基础卡片信息决定 -* 1 表示一次级联,UID有 4 字节 -* 2 表示二次级联,UID有 7 字节 -* 3 表示三次级联,UID有 10 字节 -* @param :tag : 存放卡片信息的结构体 -* @retval : 转换结果 +* @brief : 获得标签的U32类型的UID,根据传入的基础卡片信息决定 +* 1 表示一次级联,UID有 4 字节 +* 2 表示二次级联,UID有 7 字节 +* 3 表示三次级联,UID有 10 字节 +* @param :tag : 存放卡片信息的结构体 +* @retval : 转换结果 * */ uint32_t get_u32_tag_uid(picc_14a_tag_t *tag) { - uint8_t uid_buf[4] = { 0x00 }; - // 直接调用封装好的函数拷贝目标值 - get_4byte_tag_uid(tag, uid_buf); - return bytes_to_num(uid_buf, 4); + uint8_t uid_buf[4] = { 0x00 }; + // 直接调用封装好的函数拷贝目标值 + get_4byte_tag_uid(tag, uid_buf); + return bytes_to_num(uid_buf, 4); } /** @@ -1077,17 +1077,17 @@ uint32_t get_u32_tag_uid(picc_14a_tag_t *tag) * */ inline void crc_14a_calculate(uint8_t* pbtData, size_t szLen, uint8_t* pbtCrc) { - switch(m_crc_computer) { - case 0: { - calc_14a_crc_lut(pbtData, szLen, pbtCrc); - } break; - case 1: { - pcd_14a_reader_calc_crc(pbtData, szLen, pbtCrc); - } break; - default: { - // - } break; - } + switch(m_crc_computer) { + case 0: { + calc_14a_crc_lut(pbtData, szLen, pbtCrc); + } break; + case 1: { + pcd_14a_reader_calc_crc(pbtData, szLen, pbtCrc); + } break; + default: { + // + } break; + } } @@ -1096,26 +1096,26 @@ inline void crc_14a_calculate(uint8_t* pbtData, size_t szLen, uint8_t* pbtCrc) { * */ inline void crc_14a_append(uint8_t* pbtData, size_t szLen) { - switch(m_crc_computer) { - case 0: { - calc_14a_crc_lut(pbtData, szLen, pbtData + szLen); - } break; - case 1: { - pcd_14a_reader_calc_crc(pbtData, szLen, pbtData + szLen); - } break; - default: { - - } break; - } + switch(m_crc_computer) { + case 0: { + calc_14a_crc_lut(pbtData, szLen, pbtData + szLen); + } break; + case 1: { + pcd_14a_reader_calc_crc(pbtData, szLen, pbtData + szLen); + } break; + default: { + + } break; + } } /** * @brief 切换CRC的计算源,默认在 MCU 上计算, -* 可以切换到RC522上计算,如果MCU的性能不是很足 -* 如果 MCU 的性能很足,建议放在 MCU 上计算,让计算过程更加的顺畅 -* 如果 MCU 的性能不足,建议放在 522 上计算,缓解MCU的计算压力 +* 可以切换到RC522上计算,如果MCU的性能不是很足 +* 如果 MCU 的性能很足,建议放在 MCU 上计算,让计算过程更加的顺畅 +* 如果 MCU 的性能不足,建议放在 522 上计算,缓解MCU的计算压力 * */ inline void pcd_14a_reader_crc_computer(uint8_t use522CalcCRC) { - m_crc_computer = use522CalcCRC; + m_crc_computer = use522CalcCRC; } diff --git a/firmware/application/src/rfid/reader/hf/rc522.h b/firmware/application/src/rfid/reader/hf/rc522.h index e565165b..9ceebc1f 100644 --- a/firmware/application/src/rfid/reader/hf/rc522.h +++ b/firmware/application/src/rfid/reader/hf/rc522.h @@ -15,7 +15,7 @@ #define PCD_RECEIVE 0x08 //接收数据 #define PCD_TRANSMIT 0x04 //发送数据 #define PCD_TRANSCEIVE 0x0C //发送并接收数据 -#define PCD_RESET 0x0F //复位 +#define PCD_RESET 0x0F //复位 #define PCD_CALCCRC 0x03 //CRC计算 /* @@ -26,7 +26,7 @@ #define PICC_ANTICOLL1 0x93 //防冲撞 #define PICC_ANTICOLL2 0x95 //防冲撞 #define PICC_ANTICOLL3 0x97 //防冲撞 -#define PICC_RATS 0xE0 //选择应答 +#define PICC_RATS 0xE0 //选择应答 /* * M1卡片命令字 @@ -42,28 +42,28 @@ #define PICC_HALT 0x50 //休眠 // GEN1A标签的命令字 -#define PICC_MAGICWUPC1 0x40 // 后门指令1 -#define PICC_MAGICWUPC2 0x43 // 后门指令2 -#define PICC_MAGICWIPEC 0x41 // 后门清卡指令 +#define PICC_MAGICWUPC1 0x40 // 后门指令1 +#define PICC_MAGICWUPC2 0x43 // 后门指令2 +#define PICC_MAGICWIPEC 0x41 // 后门清卡指令 /* RC522 FIFO长度定义 */ -#define DEF_FIFO_LENGTH 64 //FIFO size=64byte +#define DEF_FIFO_LENGTH 64 //FIFO size=64byte // RC522 CRC长度定义 -#define DEF_CRC_LENGTH 2 +#define DEF_CRC_LENGTH 2 /* - RC522 默认定时器超时配置,这个值可以动态调整,通过 PcdSetTimeout 函数 - 操作标准M1卡最大等待时间 25ms - 我们可以提高超时以兼容一些反应比较迟钝的卡 - 比如某些手环模拟的卡,比如某些其他硬件模拟的卡,例如变色龙 - 如果超时值太小,就有可能没办法读到UID(Gen1A)卡! + RC522 默认定时器超时配置,这个值可以动态调整,通过 PcdSetTimeout 函数 + 操作标准M1卡最大等待时间 25ms + 我们可以提高超时以兼容一些反应比较迟钝的卡 + 比如某些手环模拟的卡,比如某些其他硬件模拟的卡,例如变色龙 + 如果超时值太小,就有可能没办法读到UID(Gen1A)卡! */ -#define DEF_COM_TIMEOUT 25 +#define DEF_COM_TIMEOUT 25 // 数据IO长度定义 -#define MAX_MIFARE_FRAME_SIZE 18 // biggest Mifare frame is answer to a read (one block = 16 Bytes) + 2 Bytes CRC -#define MAX_MIFARE_PARITY_SIZE 3 // need 18 parity bits for the 18 Byte above. 3 Bytes are enough to store these +#define MAX_MIFARE_FRAME_SIZE 18 // biggest Mifare frame is answer to a read (one block = 16 Bytes) + 2 Bytes CRC +#define MAX_MIFARE_PARITY_SIZE 3 // need 18 parity bits for the 18 Byte above. 3 Bytes are enough to store these #define CARD_MEMORY_SIZE 4096 ///////////////////////////////////////////////////////////////////// @@ -136,7 +136,7 @@ #define RFU3C 0x3C //保留 #define RFU3D 0x3D //保留 #define RFU3E 0x3E //保留 -#define RFU3F 0x3F //保留 +#define RFU3F 0x3F //保留 ///////////////////////////////////////////////////////////////////// @@ -152,84 +152,84 @@ // 标签信息的基本结构封装 typedef struct { - uint8_t uid[10]; // 卡号的字节数组,最长10字节 - uint8_t uid_len; // 卡号的长度 - uint8_t cascade; // 防冲撞等级 值为1表示 4byte,2表示7byte,3表示10byte - uint8_t sak; // 选择确认 - uint8_t atqa[2]; // 请求应答 + uint8_t uid[10]; // 卡号的字节数组,最长10字节 + uint8_t uid_len; // 卡号的长度 + uint8_t cascade; // 防冲撞等级 值为1表示 4byte,2表示7byte,3表示10byte + uint8_t sak; // 选择确认 + uint8_t atqa[2]; // 请求应答 } picc_14a_tag_t; #ifdef __cplusplus extern "C" { #endif - // Device control - void pcd_14a_reader_init(void); + // Device control + void pcd_14a_reader_init(void); void pcd_14a_reader_uninit(void); void pcd_14a_reader_reset(void); void pcd_14a_reader_antenna_on(void); void pcd_14a_reader_antenna_off(void); - // Device register - uint8_t read_register_single(uint8_t Address); + // Device register + uint8_t read_register_single(uint8_t Address); void write_register_single(uint8_t Address, uint8_t value); void clear_register_mask(uint8_t reg, uint8_t mask); void set_register_mask(uint8_t reg, uint8_t mask); - // Device comunication control - uint16_t pcd_14a_reader_timeout_get(void); - void pcd_14a_reader_timeout_set(uint16_t timeout_ms); + // Device comunication control + uint16_t pcd_14a_reader_timeout_get(void); + void pcd_14a_reader_timeout_set(uint16_t timeout_ms); - // Device comunication interface + // Device comunication interface uint8_t pcd_14a_reader_bytes_transfer(uint8_t Command, uint8_t* pIn, uint8_t InLenByte, uint8_t* pOut, uint16_t* pOutLenBit, - uint16_t maxOutLenBit); + uint16_t maxOutLenBit); uint8_t pcd_14a_reader_bits_transfer(uint8_t* pTx, uint16_t szTxBits, uint8_t* pTxPar, uint8_t* pRx, uint8_t* pRxPar, - uint16_t* pRxLenBit, - uint16_t szRxLenBitMax); + uint16_t* pRxLenBit, + uint16_t szRxLenBitMax); - // Device auto append and check 14443-A parity enable or disable. - void pcd_14a_reader_parity_on(void); + // Device auto append and check 14443-A parity enable or disable. + void pcd_14a_reader_parity_on(void); void pcd_14a_reader_parity_off(void); - // 14443-A tag operation - uint8_t pcd_14a_reader_scan_auto(picc_14a_tag_t *tag); - uint8_t pcd_14a_reader_ats_request(uint8_t *pAts, uint16_t *szAts, uint16_t szAtsBitMax); - uint8_t pcd_14a_reader_atqa_request(uint8_t *resp, uint8_t *resp_par, uint16_t resp_max_bit); + // 14443-A tag operation + uint8_t pcd_14a_reader_scan_auto(picc_14a_tag_t *tag); + uint8_t pcd_14a_reader_ats_request(uint8_t *pAts, uint16_t *szAts, uint16_t szAtsBitMax); + uint8_t pcd_14a_reader_atqa_request(uint8_t *resp, uint8_t *resp_par, uint16_t resp_max_bit); - // M1 tag operation + // M1 tag operation uint8_t pcd_14a_reader_mf1_auth(picc_14a_tag_t *tag, uint8_t type, uint8_t addr, uint8_t* pKey); - void pcd_14a_reader_mf1_unauth(void); - // 写卡操作 - uint8_t pcd_14a_reader_mf1_write_by_cmd(uint8_t cmd, uint8_t addr, uint8_t* p); + void pcd_14a_reader_mf1_unauth(void); + // 写卡操作 + uint8_t pcd_14a_reader_mf1_write_by_cmd(uint8_t cmd, uint8_t addr, uint8_t* p); uint8_t pcd_14a_reader_mf1_write(uint8_t addr, uint8_t* pData); - // 读卡操作 - uint8_t pcd_14a_reader_mf1_read_by_cmd(uint8_t cmd, uint8_t addr, uint8_t* p); + // 读卡操作 + uint8_t pcd_14a_reader_mf1_read_by_cmd(uint8_t cmd, uint8_t addr, uint8_t* p); uint8_t pcd_14a_reader_mf1_read(uint8_t addr, uint8_t* pData); // 休眠卡操作 - uint8_t pcd_14a_reader_halt_tag(void); - void pcd_14a_reader_fast_halt_tag(void); + uint8_t pcd_14a_reader_halt_tag(void); + void pcd_14a_reader_fast_halt_tag(void); - // UID & UFUID tag operation - uint8_t pcd_14a_reader_gen1a_unlock(void); - uint8_t pcd_14a_reader_gen1a_uplock(void); + // UID & UFUID tag operation + uint8_t pcd_14a_reader_gen1a_unlock(void); + uint8_t pcd_14a_reader_gen1a_uplock(void); - // CRC calulate - void pcd_14a_reader_calc_crc(uint8_t* pbtData, size_t szLen, uint8_t* pbtCrc); - void crc_14a_calculate(uint8_t* pbtData, size_t szLen, uint8_t* pbtCrc); + // CRC calulate + void pcd_14a_reader_calc_crc(uint8_t* pbtData, size_t szLen, uint8_t* pbtCrc); + void crc_14a_calculate(uint8_t* pbtData, size_t szLen, uint8_t* pbtCrc); void crc_14a_append(uint8_t* pbtData, size_t szLen); - void pcd_14a_reader_crc_computer(uint8_t use522CalcCRC); + void pcd_14a_reader_crc_computer(uint8_t use522CalcCRC); - // other - uint8_t cascade_to_cmd(uint8_t cascade); - uint32_t get_u32_tag_uid(picc_14a_tag_t *tag); - uint8_t* get_4byte_tag_uid(picc_14a_tag_t *tag, uint8_t *out); + // other + uint8_t cascade_to_cmd(uint8_t cascade); + uint32_t get_u32_tag_uid(picc_14a_tag_t *tag); + uint8_t* get_4byte_tag_uid(picc_14a_tag_t *tag, uint8_t *out); #ifdef __cplusplus } #endif diff --git a/firmware/application/src/rfid/reader/lf/data_utils.c b/firmware/application/src/rfid/reader/lf/data_utils.c index 4e47fb5b..a40b818a 100644 --- a/firmware/application/src/rfid/reader/lf/data_utils.c +++ b/firmware/application/src/rfid/reader/lf/data_utils.c @@ -4,119 +4,119 @@ //向raw写入2bit数据,datab存0bit,dataa存1bit void writebit(uint8_t *dataa, uint8_t *datab, uint8_t pos, uint8_t adata) { - if (adata >= 4) - { - return; - } - static uint8_t aimbyte = 0; - static uint8_t aimbit = 0; - aimbyte = pos / 8; - aimbit = pos % 8; - getbit(adata, 1) ? setbit(dataa[aimbyte], aimbit) : clrbit(dataa[aimbyte], aimbit); - getbit(adata, 0) ? setbit(datab[aimbyte], aimbit) : clrbit(datab[aimbyte], aimbit); + if (adata >= 4) + { + return; + } + static uint8_t aimbyte = 0; + static uint8_t aimbit = 0; + aimbyte = pos / 8; + aimbit = pos % 8; + getbit(adata, 1) ? setbit(dataa[aimbyte], aimbit) : clrbit(dataa[aimbyte], aimbit); + getbit(adata, 0) ? setbit(datab[aimbyte], aimbit) : clrbit(datab[aimbyte], aimbit); } //输出raw的2bit组合数据 uint8_t readbit(uint8_t *dataa, uint8_t *datab, uint8_t pos) { - static uint8_t aimbyte = 0; - static uint8_t aimbit = 0; - aimbyte = pos / 8; - aimbit = pos % 8; - return ( - (getbit(dataa[aimbyte], aimbit) << 1) | - (getbit(datab[aimbyte], aimbit))); + static uint8_t aimbyte = 0; + static uint8_t aimbit = 0; + aimbyte = pos / 8; + aimbit = pos % 8; + return ( + (getbit(dataa[aimbyte], aimbit) << 1) | + (getbit(datab[aimbyte], aimbit))); } //向raw写入2bit数据(大端方法,每个byte的第8位写数据的第1位),datab存0bit,dataa存1bit void writebit_msb(uint8_t *dataa, uint8_t *datab, uint8_t pos, uint8_t adata) { - if (adata >= 4) - { - return; - } - static uint8_t aimbyte = 0; - static uint8_t aimbit = 0; - aimbyte = pos / 8; - aimbit = 7 - (pos % 8); - getbit(adata, 1) ? setbit(dataa[aimbyte], aimbit) : clrbit(dataa[aimbyte], aimbit); - getbit(adata, 0) ? setbit(datab[aimbyte], aimbit) : clrbit(datab[aimbyte], aimbit); + if (adata >= 4) + { + return; + } + static uint8_t aimbyte = 0; + static uint8_t aimbit = 0; + aimbyte = pos / 8; + aimbit = 7 - (pos % 8); + getbit(adata, 1) ? setbit(dataa[aimbyte], aimbit) : clrbit(dataa[aimbyte], aimbit); + getbit(adata, 0) ? setbit(datab[aimbyte], aimbit) : clrbit(datab[aimbyte], aimbit); } //输出raw的2bit组合数据(大端方法,每个byte的第8位读数据的第1位) uint8_t readbit_msb(uint8_t *dataa, uint8_t *datab, uint8_t pos) { - static uint8_t aimbyte = 0; - static uint8_t aimbit = 0; - aimbyte = pos / 8; - aimbit = 7 - (pos % 8); - return ( - (getbit(dataa[aimbyte], aimbit) << 1) | - (getbit(datab[aimbyte], aimbit))); + static uint8_t aimbyte = 0; + static uint8_t aimbit = 0; + aimbyte = pos / 8; + aimbit = 7 - (pos % 8); + return ( + (getbit(dataa[aimbyte], aimbit) << 1) | + (getbit(datab[aimbyte], aimbit))); } //高低位翻转 uint8_t invert_num(uint8_t num) { - uint8_t temp = 0, sh = 0xf; - uint8_t i = 0; - for (i = 0; i < sizeof(uint8_t); i++) - { - temp |= (num & (sh << ((sizeof(uint8_t) - 1 - i) << 2))) << ((i << 3) + 4); - temp |= (num & (sh << ((sizeof(uint8_t) + i) << 2))) >> ((i << 3) + 4); - } - num = ((temp << 2) & 0xcccccccccccccccc) | ((temp >> 2) & 0x3333333333333333); - num = ((num << 1) & 0xaaaaaaaaaaaaaaaa) | ((num >> 1) & 0x5555555555555555); - - return num; + uint8_t temp = 0, sh = 0xf; + uint8_t i = 0; + for (i = 0; i < sizeof(uint8_t); i++) + { + temp |= (num & (sh << ((sizeof(uint8_t) - 1 - i) << 2))) << ((i << 3) + 4); + temp |= (num & (sh << ((sizeof(uint8_t) + i) << 2))) >> ((i << 3) + 4); + } + num = ((temp << 2) & 0xcccccccccccccccc) | ((temp >> 2) & 0x3333333333333333); + num = ((num << 1) & 0xaaaaaaaaaaaaaaaa) | ((num >> 1) & 0x5555555555555555); + + return num; } //原始数据转换为2倍长度的hex字符数组 void ByteToHexStr(uint8_t *source, uint8_t *dest, uint8_t sourceLen) { - uint8_t i, highByte, lowByte; - - for (i = 0; i < sourceLen; i++) - { - highByte = source[i] >> 4; - lowByte = source[i] & 0x0f; - - highByte += 0x30; - - if (highByte > 0x39) - dest[i * 2] = highByte + 0x07; - else - dest[i * 2] = highByte; - - lowByte += 0x30; - if (lowByte > 0x39) - dest[i * 2 + 1] = lowByte + 0x07; - else - dest[i * 2 + 1] = lowByte; - } - return; + uint8_t i, highByte, lowByte; + + for (i = 0; i < sourceLen; i++) + { + highByte = source[i] >> 4; + lowByte = source[i] & 0x0f; + + highByte += 0x30; + + if (highByte > 0x39) + dest[i * 2] = highByte + 0x07; + else + dest[i * 2] = highByte; + + lowByte += 0x30; + if (lowByte > 0x39) + dest[i * 2 + 1] = lowByte + 0x07; + else + dest[i * 2 + 1] = lowByte; + } + return; } void HexStrToByte(uint8_t *source, uint8_t *dest, uint8_t sourceLen) { - uint8_t i, highByte, lowByte; - - for (i = 0; i < sourceLen; i += 2) - { - highByte = toupper(source[i]); - lowByte = toupper(source[i + 1]); - - if (highByte > 0x39) - highByte -= 0x37; - else - highByte -= 0x30; - - if (lowByte > 0x39) - lowByte -= 0x37; - else - lowByte -= 0x30; - - dest[i / 2] = (highByte << 4) | lowByte; - } - return; + uint8_t i, highByte, lowByte; + + for (i = 0; i < sourceLen; i += 2) + { + highByte = toupper(source[i]); + lowByte = toupper(source[i + 1]); + + if (highByte > 0x39) + highByte -= 0x37; + else + highByte -= 0x30; + + if (lowByte > 0x39) + lowByte -= 0x37; + else + lowByte -= 0x30; + + dest[i / 2] = (highByte << 4) | lowByte; + } + return; } diff --git a/firmware/application/src/rfid/reader/lf/data_utils.h b/firmware/application/src/rfid/reader/lf/data_utils.h index 083207f1..e930a186 100644 --- a/firmware/application/src/rfid/reader/lf/data_utils.h +++ b/firmware/application/src/rfid/reader/lf/data_utils.h @@ -12,10 +12,10 @@ uint8_t (*(WATCH))[(LENG)] = (uint8_t (*)[(LENG)])(PDATA) #define DEBUG_READ_BREAK(WATCH) (*(WATCH))[0] = (*(WATCH))[0] -#define setbit(x,y) (x|=(1<> (y)&1) +#define setbit(x,y) (x|=(1<> (y)&1) void writebit(uint8_t *dataa, uint8_t *datab, uint8_t pos, uint8_t adata); uint8_t readbit(uint8_t *dataa, uint8_t *datab, uint8_t pos); diff --git a/firmware/application/src/rfid/reader/lf/lf_em410x_data.c b/firmware/application/src/rfid/reader/lf/lf_em410x_data.c index f3470751..8ecfa185 100644 --- a/firmware/application/src/rfid/reader/lf/lf_em410x_data.c +++ b/firmware/application/src/rfid/reader/lf/lf_em410x_data.c @@ -16,8 +16,8 @@ NRF_LOG_MODULE_REGISTER(); static RAWBUF_TYPE_S carddata; -static volatile uint8_t dataindex = 0; //记录变化沿次数 -uint8_t cardbufbyte[cardbufbytesize]; //卡片数据 +static volatile uint8_t dataindex = 0; //记录变化沿次数 +uint8_t cardbufbyte[cardbufbytesize]; //卡片数据 #ifdef debug410x uint8_t datatest[256] = { 0x00 }; @@ -29,158 +29,158 @@ uint8_t datatest[256] = { 0x00 }; //Pdata为rawbuffer uint8_t mcst(RAWBUF_TYPE_S *Pdata) { - uint8_t sync = 1; //当前间隔处理完后,是否在判定线上 - uint8_t cardindex = 0; //记录变化次数 - for (int i = Pdata->startbit; i < rawbufsize * 8; i++) - { - uint8_t thisbit = readbit(Pdata->rawa, Pdata->rawb, i); - switch (sync) - { - case 1: //同步状态 - switch (thisbit) - { - case 0: //同步状态的1T,添加1位0,依然同步 - writebit(Pdata->hexbuf, Pdata->hexbuf, cardindex, 0); - cardindex++; - break; - case 1: //同步状态的1.5T,添加1位1,切换到非同步状态 - writebit(Pdata->hexbuf, Pdata->hexbuf, cardindex, 1); - cardindex++; - sync = 0; - break; - case 2: //同步状态的2T,添加2位10,依然同步 - writebit(Pdata->hexbuf, Pdata->hexbuf, cardindex, 1); - cardindex++; - writebit(Pdata->hexbuf, Pdata->hexbuf, cardindex, 0); - cardindex++; - break; - default: - return 0; - } - break; - case 0: //非同步状态 - switch (thisbit) - { - case 0: //非同步状态的1T,添加1位1,依然非同步 - writebit(Pdata->hexbuf, Pdata->hexbuf, cardindex, 1); - cardindex++; - break; - case 1: //非同步状态的1.5T,添加2位10,切换到同步状态 - writebit(Pdata->hexbuf, Pdata->hexbuf, cardindex, 1); - cardindex++; - writebit(Pdata->hexbuf, Pdata->hexbuf, cardindex, 0); - cardindex++; - sync = 1; - break; - case 2: //非同步状态的2T,不可能出现的情况,报错。 - return 0; - default: - return 0; - } - break; - } - if (cardindex >= cardbufsize * 8) - break; - } - return 1; + uint8_t sync = 1; //当前间隔处理完后,是否在判定线上 + uint8_t cardindex = 0; //记录变化次数 + for (int i = Pdata->startbit; i < rawbufsize * 8; i++) + { + uint8_t thisbit = readbit(Pdata->rawa, Pdata->rawb, i); + switch (sync) + { + case 1: //同步状态 + switch (thisbit) + { + case 0: //同步状态的1T,添加1位0,依然同步 + writebit(Pdata->hexbuf, Pdata->hexbuf, cardindex, 0); + cardindex++; + break; + case 1: //同步状态的1.5T,添加1位1,切换到非同步状态 + writebit(Pdata->hexbuf, Pdata->hexbuf, cardindex, 1); + cardindex++; + sync = 0; + break; + case 2: //同步状态的2T,添加2位10,依然同步 + writebit(Pdata->hexbuf, Pdata->hexbuf, cardindex, 1); + cardindex++; + writebit(Pdata->hexbuf, Pdata->hexbuf, cardindex, 0); + cardindex++; + break; + default: + return 0; + } + break; + case 0: //非同步状态 + switch (thisbit) + { + case 0: //非同步状态的1T,添加1位1,依然非同步 + writebit(Pdata->hexbuf, Pdata->hexbuf, cardindex, 1); + cardindex++; + break; + case 1: //非同步状态的1.5T,添加2位10,切换到同步状态 + writebit(Pdata->hexbuf, Pdata->hexbuf, cardindex, 1); + cardindex++; + writebit(Pdata->hexbuf, Pdata->hexbuf, cardindex, 0); + cardindex++; + sync = 1; + break; + case 2: //非同步状态的2T,不可能出现的情况,报错。 + return 0; + default: + return 0; + } + break; + } + if (cardindex >= cardbufsize * 8) + break; + } + return 1; } //处理卡片,寻找校验位并且判断是否正常 uint8_t em410x_decoder(uint8_t *pData, uint8_t size, uint8_t *pOut) { - if (size != 8) - { - //NRF_LOG_INFO("size err %d!\n", size); - return 0; - } - - // NRF_LOG_INFO("开始解码数据!\n"); - - // 迭代数据的次数,每次 +5 个bit - uint8_t iteration = 0; - // 当前合并的数据的存放位置 - uint8_t merge_pos = 0; - - // 快速校验头部 - uint8_t head_check = 1; - for (int i = 0; i < 9; i++) - { - head_check &= getbit(pData[i / 8], i % 8); - } - // 一起快速校验尾部 - if ((!head_check) || getbit(pData[7], 7)) - { - //NRF_LOG_INFO("head or tail err!\n"); - return 0; - } - - // NRF_LOG_INFO("头部与尾部检测通过!\n"); - - // 先校验X轴的数据 - // X轴校验,每隔 5个bit 校验一次, - // 校验完成后保存为 半个byte - for (int i = 9; i < size * 8 - 5; i += 5) - { - uint8_t count_bit_x = 0; - - for (int j = i; j < i + 5; j++) - { - - // 收集偶数据个数 - if (getbit(pData[j / 8], j % 8) == 1) - { - count_bit_x += 1; - } - - if (j != i + 4) - { - // 合并bit数据到 uint8缓冲区中 - // 需要加上左对齐坐标,如果是高位部分 - uint8_t first_merge_offset = (iteration % 2) ? 0 : 4; - uint8_t finally_offset = first_merge_offset + ((i + 5 - 1) - j - 1); - // NRF_LOG_INFO("需要左移 %d 位。\n", finally_offset); - getbit(pData[j / 8], j % 8) ? (pOut[merge_pos] |= 1 << finally_offset) : (pOut[merge_pos] &= ~(1 << finally_offset)); - } - - // 如果在第一行,我们还可以直接去校验 Y 轴的校验位 - if (iteration == 0 && j != i + 4) - { - uint8_t count_bit_y = 0; - for (int m = j; m < j + 51; m += 5) - { - // NRF_LOG_INFO("当前的m坐标是 %d, 数据是 %d\n", m, pData[m]); - if (getbit(pData[m / 8], m % 8) == 1) - { - count_bit_y += 1; - } - } - if (count_bit_y % 2) - { - //NRF_LOG_INFO("bit even parity err at Y-axis from %d to %d!\n", j, j + 51); - return 0; - } - } // 否则的话,就直接进入下一轮校验 - } - - // 经过一轮校验后,下次就不要校验 Y 轴 - iteration += 1; - - // 如果取余数不为0 - // 说明进入了新的数据处理循环 - // 我们需要递增存放合并字节需要的下标 - if (!(iteration % 2)) - { - merge_pos += 1; - // NRF_LOG_INFO("\n"); - } - - if (count_bit_x % 2) - { - //NRF_LOG_INFO("bit even parity err at X-axis from %d to %d!\n", i, i + 5); - return 0; - } - } - return 1; + if (size != 8) + { + //NRF_LOG_INFO("size err %d!\n", size); + return 0; + } + + // NRF_LOG_INFO("开始解码数据!\n"); + + // 迭代数据的次数,每次 +5 个bit + uint8_t iteration = 0; + // 当前合并的数据的存放位置 + uint8_t merge_pos = 0; + + // 快速校验头部 + uint8_t head_check = 1; + for (int i = 0; i < 9; i++) + { + head_check &= getbit(pData[i / 8], i % 8); + } + // 一起快速校验尾部 + if ((!head_check) || getbit(pData[7], 7)) + { + //NRF_LOG_INFO("head or tail err!\n"); + return 0; + } + + // NRF_LOG_INFO("头部与尾部检测通过!\n"); + + // 先校验X轴的数据 + // X轴校验,每隔 5个bit 校验一次, + // 校验完成后保存为 半个byte + for (int i = 9; i < size * 8 - 5; i += 5) + { + uint8_t count_bit_x = 0; + + for (int j = i; j < i + 5; j++) + { + + // 收集偶数据个数 + if (getbit(pData[j / 8], j % 8) == 1) + { + count_bit_x += 1; + } + + if (j != i + 4) + { + // 合并bit数据到 uint8缓冲区中 + // 需要加上左对齐坐标,如果是高位部分 + uint8_t first_merge_offset = (iteration % 2) ? 0 : 4; + uint8_t finally_offset = first_merge_offset + ((i + 5 - 1) - j - 1); + // NRF_LOG_INFO("需要左移 %d 位。\n", finally_offset); + getbit(pData[j / 8], j % 8) ? (pOut[merge_pos] |= 1 << finally_offset) : (pOut[merge_pos] &= ~(1 << finally_offset)); + } + + // 如果在第一行,我们还可以直接去校验 Y 轴的校验位 + if (iteration == 0 && j != i + 4) + { + uint8_t count_bit_y = 0; + for (int m = j; m < j + 51; m += 5) + { + // NRF_LOG_INFO("当前的m坐标是 %d, 数据是 %d\n", m, pData[m]); + if (getbit(pData[m / 8], m % 8) == 1) + { + count_bit_y += 1; + } + } + if (count_bit_y % 2) + { + //NRF_LOG_INFO("bit even parity err at Y-axis from %d to %d!\n", j, j + 51); + return 0; + } + } // 否则的话,就直接进入下一轮校验 + } + + // 经过一轮校验后,下次就不要校验 Y 轴 + iteration += 1; + + // 如果取余数不为0 + // 说明进入了新的数据处理循环 + // 我们需要递增存放合并字节需要的下标 + if (!(iteration % 2)) + { + merge_pos += 1; + // NRF_LOG_INFO("\n"); + } + + if (count_bit_x % 2) + { + //NRF_LOG_INFO("bit even parity err at X-axis from %d to %d!\n", i, i + 5); + return 0; + } + } + return 1; } /** @@ -190,231 +190,231 @@ uint8_t em410x_decoder(uint8_t *pData, uint8_t size, uint8_t *pOut) */ void em410x_encoder(uint8_t *pData, uint8_t *pOut) { - //#define EM410X_Encoder_NRF_LOG_INFO - - // 为了节省代码空间,我们可以在规律内限制死数据长度 - // 也就是说,总体循环次数不可以超过 0 - 127 个bit - // 当然,对于正经的EM410来说,这个循环的次数足够了 - int8_t i, j; - - // 某些数据其实可以通过时间换空间 - // 但是这点空间太小了,还不如留着换时间 - // 所以就不要改了。 - uint8_t pos, bit, count1; - - pOut[0] = 0xFF; // 前导码有9个1,所以我们先给第一个字节限定为 11111111 - pOut[1] = 0x80; // 没啥好说的,第二个Byte的msb也要是一个 1 ,这样就凑够了 1 * 9 的前导码 - - //重置数据为空 - for(i = 2;i < 8;i++){ - pOut[i] = 0x00; - } - - // bit置位为9,因为有 0 - 8 总共 9 个前导码 ( 1 * 9 ) - pos = 9; - // 重置bit计数 - count1 = 0; - - // X轴 迭代 5个Byte的卡号,拼凑bit到缓冲区中并且计算奇偶校验位 - for (i = 0; i < 5; i++) - { - // 迭代处理每个bit - for (j = 7; j >= 0; j--) - { - // 取出单个bit - bit = ((pData[i] >> j) & 0x01); + //#define EM410X_Encoder_NRF_LOG_INFO + + // 为了节省代码空间,我们可以在规律内限制死数据长度 + // 也就是说,总体循环次数不可以超过 0 - 127 个bit + // 当然,对于正经的EM410来说,这个循环的次数足够了 + int8_t i, j; + + // 某些数据其实可以通过时间换空间 + // 但是这点空间太小了,还不如留着换时间 + // 所以就不要改了。 + uint8_t pos, bit, count1; + + pOut[0] = 0xFF; // 前导码有9个1,所以我们先给第一个字节限定为 11111111 + pOut[1] = 0x80; // 没啥好说的,第二个Byte的msb也要是一个 1 ,这样就凑够了 1 * 9 的前导码 + + //重置数据为空 + for(i = 2;i < 8;i++){ + pOut[i] = 0x00; + } + + // bit置位为9,因为有 0 - 8 总共 9 个前导码 ( 1 * 9 ) + pos = 9; + // 重置bit计数 + count1 = 0; + + // X轴 迭代 5个Byte的卡号,拼凑bit到缓冲区中并且计算奇偶校验位 + for (i = 0; i < 5; i++) + { + // 迭代处理每个bit + for (j = 7; j >= 0; j--) + { + // 取出单个bit + bit = ((pData[i] >> j) & 0x01); #ifdef EM410X_Encoder_NRF_LOG_INFO - NRF_LOG_INFO("%d ", bit); + NRF_LOG_INFO("%d ", bit); #endif // EM410X_Encoder_NRF_LOG_INFO - // 原生数据放入到输出缓冲区 - pOut[pos / 8] |= (bit << (7 - pos % 8)); - pos += 1; + // 原生数据放入到输出缓冲区 + pOut[pos / 8] |= (bit << (7 - pos % 8)); + pos += 1; - // 统计偶校验计数 - if (bit) - { - count1 += 1; - } + // 统计偶校验计数 + if (bit) + { + count1 += 1; + } - // 奇偶校验位放入到输出缓冲区 - if (j == 4 || j == 0) - { + // 奇偶校验位放入到输出缓冲区 + if (j == 4 || j == 0) + { #ifdef EM410X_Encoder_NRF_LOG_INFO - NRF_LOG_INFO(" <- 比特RAW : 奇偶校验 -> %d\n", count1 % 2); + NRF_LOG_INFO(" <- 比特RAW : 奇偶校验 -> %d\n", count1 % 2); #endif // EM410X_Encoder_NRF_LOG_INFO - // 不用说了,肯定是放入一个bit的奇偶校验位啊 - pOut[pos / 8] |= ((count1 % 2) << (7 - pos % 8)); - pos += 1; - count1 = 0; - } - } - } + // 不用说了,肯定是放入一个bit的奇偶校验位啊 + pOut[pos / 8] |= ((count1 % 2) << (7 - pos % 8)); + pos += 1; + count1 = 0; + } + } + } #ifdef EM410X_Encoder_NRF_LOG_INFO - NRF_LOG_INFO("\n"); + NRF_LOG_INFO("\n"); #endif // EM410X_Encoder_NRF_LOG_INFO - // Y轴 迭代 5个byte的卡号,生成4个bit的奇偶校验位 - for (i = 0; i < 4; i++) - { - count1 = 0; - for (j = 0; j < 5; j++) - { - // 高位计数 - bit = ((pData[j] >> (7 - i)) & 0x01); - if (bit) - { - count1 += 1; - } - // 低位计数 - bit = ((pData[j] >> (3 - i)) & 0x01); - if (bit) - { - count1 += 1; - } - } - - // Y轴计算完成,放到最终的bit输出缓冲区中 - pOut[pos / 8] |= ((count1 % 2) << (7 - pos % 8)); - pos += 1; + // Y轴 迭代 5个byte的卡号,生成4个bit的奇偶校验位 + for (i = 0; i < 4; i++) + { + count1 = 0; + for (j = 0; j < 5; j++) + { + // 高位计数 + bit = ((pData[j] >> (7 - i)) & 0x01); + if (bit) + { + count1 += 1; + } + // 低位计数 + bit = ((pData[j] >> (3 - i)) & 0x01); + if (bit) + { + count1 += 1; + } + } + + // Y轴计算完成,放到最终的bit输出缓冲区中 + pOut[pos / 8] |= ((count1 % 2) << (7 - pos % 8)); + pos += 1; #ifdef EM410X_Encoder_NRF_LOG_INFO - NRF_LOG_INFO("%d ", count1 % 2); + NRF_LOG_INFO("%d ", count1 % 2); #endif // EM410X_Encoder_NRF_LOG_INFO - } + } #ifdef EM410X_Encoder_NRF_LOG_INFO - NRF_LOG_INFO(" <- 奇偶校验 : 尾导码 -> 0\n\n"); + NRF_LOG_INFO(" <- 奇偶校验 : 尾导码 -> 0\n\n"); #endif // EM410X_Encoder_NRF_LOG_INFO } //读卡函数,需要不停调用,返回0为没读到卡,1为读到了 uint8_t em410x_acquire(void) { - if (dataindex >= rawbufsize * 8) - { + if (dataindex >= rawbufsize * 8) + { #ifdef debug410x - { - for (int i = 0; i < rawbufsize * 8; i++) - { - NRF_LOG_INFO("%d ", readbit(carddata.rawa, carddata.rawb, i)); - } - NRF_LOG_INFO("///raw data\r\n"); - for (int i = 0; i < rawbufsize * 8; i++) - { - NRF_LOG_INFO("%d ", datatest[i]); - } - NRF_LOG_INFO("///time data\r\n"); - } + { + for (int i = 0; i < rawbufsize * 8; i++) + { + NRF_LOG_INFO("%d ", readbit(carddata.rawa, carddata.rawb, i)); + } + NRF_LOG_INFO("///raw data\r\n"); + for (int i = 0; i < rawbufsize * 8; i++) + { + NRF_LOG_INFO("%d ", datatest[i]); + } + NRF_LOG_INFO("///time data\r\n"); + } #endif - //寻找目标0 1111 1111 - carddata.startbit = 255; - for (int i = 0; i < (rawbufsize * 8) - 8; i++) - { - if (readbit(carddata.rawa, carddata.rawb, i) == 1) - { - carddata.startbit = 0; - for (int j = 1; j < 8; j++) - { - carddata.startbit += (uint8_t)readbit(carddata.rawa, carddata.rawb, i + j); - } - if (carddata.startbit == 0) - { - carddata.startbit = i; - break; - } - else - { - carddata.startbit = 255; - } - } - } - // 如果找到了合适的开头,进行处理 - if (carddata.startbit != 255 && carddata.startbit < (rawbufsize * 8) - 64) - { //保证卡片数据可以完整解析 - //NRF_LOG_INFO("do mac,start: %d\r\n",startbit); - if (mcst(&carddata) == 1) - { //卡片正常解析 + //寻找目标0 1111 1111 + carddata.startbit = 255; + for (int i = 0; i < (rawbufsize * 8) - 8; i++) + { + if (readbit(carddata.rawa, carddata.rawb, i) == 1) + { + carddata.startbit = 0; + for (int j = 1; j < 8; j++) + { + carddata.startbit += (uint8_t)readbit(carddata.rawa, carddata.rawb, i + j); + } + if (carddata.startbit == 0) + { + carddata.startbit = i; + break; + } + else + { + carddata.startbit = 255; + } + } + } + // 如果找到了合适的开头,进行处理 + if (carddata.startbit != 255 && carddata.startbit < (rawbufsize * 8) - 64) + { //保证卡片数据可以完整解析 + //NRF_LOG_INFO("do mac,start: %d\r\n",startbit); + if (mcst(&carddata) == 1) + { //卡片正常解析 #ifdef debug410x - { - for (int i = 0; i < cardbufsize; i++) - { - NRF_LOG_INFO("%02X", carddata.hexbuf[i]); - } - NRF_LOG_INFO("///card data\r\n"); - } + { + for (int i = 0; i < cardbufsize; i++) + { + NRF_LOG_INFO("%02X", carddata.hexbuf[i]); + } + NRF_LOG_INFO("///card data\r\n"); + } #endif - if (em410x_decoder(carddata.hexbuf, cardbufsize, cardbufbyte)) - { //卡片数据检查通过 + if (em410x_decoder(carddata.hexbuf, cardbufsize, cardbufbyte)) + { //卡片数据检查通过 #ifdef debug410x - for (int i = 0; i < 5; i++) - { - NRF_LOG_INFO("%02X", (int)cardbufbyte[i]); - } - NRF_LOG_INFO("///card dataBYTE\r\n"); + for (int i = 0; i < 5; i++) + { + NRF_LOG_INFO("%02X", (int)cardbufbyte[i]); + } + NRF_LOG_INFO("///card dataBYTE\r\n"); #endif - dataindex = 0; - return 1; - } - } - } - // 启动新的一个周期 - dataindex = 0; - } - return 0; + dataindex = 0; + return 1; + } + } + } + // 启动新的一个周期 + dataindex = 0; + } + return 0; } //gpio中断回调函数,用于检测下降沿 void GPIO_INT0_callback(void) { - static uint32_t thistimelen = 0; + static uint32_t thistimelen = 0; thistimelen = get_lf_counter_value(); - if (thistimelen > 47) - { - static uint8_t cons_temp = 0; - if (dataindex < rawbufsize * 8) - { - if (48 <= thistimelen && thistimelen <= 80) - { - cons_temp = 0; - } - else if (80 <= thistimelen && thistimelen <= 112) - { - cons_temp = 1; - } - else if (112 <= thistimelen && thistimelen <= 144) - { - cons_temp = 2; - } - else - { - cons_temp = 3; - } - writebit(carddata.rawa, carddata.rawb, dataindex, cons_temp); + if (thistimelen > 47) + { + static uint8_t cons_temp = 0; + if (dataindex < rawbufsize * 8) + { + if (48 <= thistimelen && thistimelen <= 80) + { + cons_temp = 0; + } + else if (80 <= thistimelen && thistimelen <= 112) + { + cons_temp = 1; + } + else if (112 <= thistimelen && thistimelen <= 144) + { + cons_temp = 2; + } + else + { + cons_temp = 3; + } + writebit(carddata.rawa, carddata.rawb, dataindex, cons_temp); #ifdef debug410x - datatest[dataindex] = thistimelen; + datatest[dataindex] = thistimelen; #endif - dataindex++; - } + dataindex++; + } clear_lf_counter_value(); - } + } - uint16_t counter = 0; - do - { - __NOP(); - } while (counter++ > 1000); + uint16_t counter = 0; + do + { + __NOP(); + } while (counter++ > 1000); } //启动定时器和初始化相关外设,启动低频读卡 void init_em410x_hw(void) { - //注册读卡器io中断回调 - register_rio_callback(GPIO_INT0_callback); + //注册读卡器io中断回调 + register_rio_callback(GPIO_INT0_callback); } /** @@ -422,37 +422,37 @@ void init_em410x_hw(void) */ uint8_t em410x_read(uint8_t *uid, uint32_t timeout_ms) { - uint8_t ret = 0; + uint8_t ret = 0; init_em410x_hw(); // 初始化下降沿采样回调函数 - start_lf_125khz_radio(); // 启动125khz调制 - - // 在超时中读卡 - autotimer* p_at = bsp_obtain_timer(0); - // NO_TIMEOUT_1MS(p_at, timeout_ms) - while(NO_TIMEOUT_1MS(p_at, timeout_ms)) { - //执行读卡,读到就退出 - if (em410x_acquire()) - { + start_lf_125khz_radio(); // 启动125khz调制 + + // 在超时中读卡 + autotimer* p_at = bsp_obtain_timer(0); + // NO_TIMEOUT_1MS(p_at, timeout_ms) + while(NO_TIMEOUT_1MS(p_at, timeout_ms)) { + //执行读卡,读到就退出 + if (em410x_acquire()) + { stop_lf_125khz_radio(); - uid[0] = cardbufbyte[0]; - uid[1] = cardbufbyte[1]; - uid[2] = cardbufbyte[2]; - uid[3] = cardbufbyte[3]; - uid[4] = cardbufbyte[4]; - ret = 1; - break; - } - } + uid[0] = cardbufbyte[0]; + uid[1] = cardbufbyte[1]; + uid[2] = cardbufbyte[2]; + uid[3] = cardbufbyte[3]; + uid[4] = cardbufbyte[4]; + ret = 1; + break; + } + } if (ret != 1) { // 如果没有搜索到卡,说明超时了,我们这里要手动结束读卡器 - stop_lf_125khz_radio(); - } + stop_lf_125khz_radio(); + } dataindex = 0; // 结束后谨记重置采集的数据的索引 - bsp_return_timer(p_at); - p_at = NULL; + bsp_return_timer(p_at); + p_at = NULL; - return ret; + return ret; } diff --git a/firmware/application/src/rfid/reader/lf/lf_em410x_data.h b/firmware/application/src/rfid/reader/lf/lf_em410x_data.h index 2a9b527e..b1a00915 100644 --- a/firmware/application/src/rfid/reader/lf/lf_em410x_data.h +++ b/firmware/application/src/rfid/reader/lf/lf_em410x_data.h @@ -10,17 +10,17 @@ extern "C" { #endif -#define cardbufbytesize 5 // 卡片字节buffer大小 +#define cardbufbytesize 5 // 卡片字节buffer大小 -#define rawbufsize 24 // 最大记录buffer -#define cardbufsize 8 // 卡片大小 +#define rawbufsize 24 // 最大记录buffer +#define cardbufsize 8 // 卡片大小 typedef struct { - uint8_t rawa[rawbufsize]; // 记录变化沿之间的时间差 - uint8_t rawb[rawbufsize]; // 记录变化沿之间的时间差 - uint8_t hexbuf[cardbufsize]; // 解析后的卡数据 - uint8_t startbit; + uint8_t rawa[rawbufsize]; // 记录变化沿之间的时间差 + uint8_t rawb[rawbufsize]; // 记录变化沿之间的时间差 + uint8_t hexbuf[cardbufsize]; // 解析后的卡数据 + uint8_t startbit; } RAWBUF_TYPE_S; //卡片数据 diff --git a/firmware/application/src/rfid/reader/lf/lf_reader_data.c b/firmware/application/src/rfid/reader/lf/lf_reader_data.c index aa9fadd3..a0539be4 100644 --- a/firmware/application/src/rfid/reader/lf/lf_reader_data.c +++ b/firmware/application/src/rfid/reader/lf/lf_reader_data.c @@ -2,32 +2,32 @@ #include "nrf_drv_timer.h" -RIO_CALLBACK_S RIO_callback; // 创建实例 -uint8_t RIO_callback_state; // 记录状态 +RIO_CALLBACK_S RIO_callback; // 创建实例 +uint8_t RIO_callback_state; // 记录状态 void register_rio_callback(RIO_CALLBACK_S P) // 注册回调函数 { - RIO_callback = P; - RIO_callback_state = 1; + RIO_callback = P; + RIO_callback_state = 1; } void blank_function(void) { - // 这就是一个空的函数, - // 啥都不用做 + // 这就是一个空的函数, + // 啥都不用做 } void unregister_rio_callback(void) { - RIO_callback_state = 0; - RIO_callback = blank_function; + RIO_callback_state = 0; + RIO_callback = blank_function; } // GPIO中断,就是RIO引脚 void GPIO_INT0_IRQHandler(void) { - if(RIO_callback_state == 1){ - RIO_callback(); - } + if(RIO_callback_state == 1){ + RIO_callback(); + } } diff --git a/firmware/application/src/rfid/reader/lf/lf_reader_main.c b/firmware/application/src/rfid/reader/lf/lf_reader_main.c index 50642772..6a8b478e 100644 --- a/firmware/application/src/rfid/reader/lf/lf_reader_main.c +++ b/firmware/application/src/rfid/reader/lf/lf_reader_main.c @@ -19,96 +19,96 @@ uint32_t g_timeout_readem_ms = 500; * 搜索EM410X标签 */ uint8_t PcdScanEM410X(uint8_t* uid) { - uint8_t ret = EM410X_TAG_NO_FOUND; - init_em410x_hw(); - if (em410x_read(uid, g_timeout_readem_ms) == 1) { - ret = LF_TAG_OK; - } - return ret; + uint8_t ret = EM410X_TAG_NO_FOUND; + init_em410x_hw(); + if (em410x_read(uid, g_timeout_readem_ms) == 1) { + ret = LF_TAG_OK; + } + return ret; } /** * 检测当前的场内是否有指定的UID的标签 */ uint8_t check_write_ok(uint8_t* uid, uint8_t* newuid, uint8_t on_uid_diff_return) { - // 写卡完成后,我们需要进行一次回读, - // 如果回读的数据不正确,说明写入失败 - if(PcdScanEM410X(newuid) != LF_TAG_OK) { - return EM410X_TAG_NO_FOUND; - } - // 如果回读到的卡号一样 - // 说明写入成功了(或许吧) - if( - uid[0] == newuid[0] && - uid[1] == newuid[1] && - uid[2] == newuid[2] && - uid[3] == newuid[3] && - uid[4] == newuid[4] ) { - return LF_TAG_OK; - } - // 如果发现卡,但是卡号不对, - // 那我们就将传入的异常值返回 - return on_uid_diff_return; + // 写卡完成后,我们需要进行一次回读, + // 如果回读的数据不正确,说明写入失败 + if(PcdScanEM410X(newuid) != LF_TAG_OK) { + return EM410X_TAG_NO_FOUND; + } + // 如果回读到的卡号一样 + // 说明写入成功了(或许吧) + if( + uid[0] == newuid[0] && + uid[1] == newuid[1] && + uid[2] == newuid[2] && + uid[3] == newuid[3] && + uid[4] == newuid[4] ) { + return LF_TAG_OK; + } + // 如果发现卡,但是卡号不对, + // 那我们就将传入的异常值返回 + return on_uid_diff_return; } /** * 写T55XX标签 */ uint8_t PcdWriteT55XX(uint8_t* uid, uint8_t* newkey, uint8_t* old_keys, uint8_t old_key_count) { - uint8_t datas[8] = { 255 }; - uint8_t i; + uint8_t datas[8] = { 255 }; + uint8_t i; - init_t55xx_hw(); - start_lf_125khz_radio(); + init_t55xx_hw(); + start_lf_125khz_radio(); bsp_delay_ms(1); // 启动场后延迟一段时间 - // keys 至少需要两个,一个newkey,一个oldkey - // 一个 key 的长度是 4 个字节 - // uid newkey oldkeys * n - - // 迭代传输进来的密钥, - // 进行T55XX标签重置 - // printf("The old keys count: %d\r\n", old_key_count); - for (i = 0; i < old_key_count; i++) { - T55xx_Reset_Passwd(old_keys + (i * 4), newkey); - /* - printf("oldkey is: %02x%02x%02x%02x\r\n", - (old_keys + (i * 4))[0], - (old_keys + (i * 4))[1], - (old_keys + (i * 4))[2], - (old_keys + (i * 4))[3] - );*/ - } - - // 为了避免遇到特殊的控制区的标签, - // 我们这里用新密钥来重置一下控制区 - T55xx_Reset_Passwd(newkey, newkey); - - // 编码410x的数据为block数据,为写卡做准备 - em410x_encoder(uid, datas); - - // 密钥重置完成后,进行写卡操作 - /* - printf("newkey is: %02x%02x%02x%02x\r\n", - newkey[0], - newkey[1], - newkey[2], - newkey[3] - ); - */ - T55xx_Write_data(newkey, datas); - - stop_lf_125khz_radio(); - - // 回读验证并且返回写卡结果 - // 此处不回读,由上位机校验 - return LF_TAG_OK; + // keys 至少需要两个,一个newkey,一个oldkey + // 一个 key 的长度是 4 个字节 + // uid newkey oldkeys * n + + // 迭代传输进来的密钥, + // 进行T55XX标签重置 + // printf("The old keys count: %d\r\n", old_key_count); + for (i = 0; i < old_key_count; i++) { + T55xx_Reset_Passwd(old_keys + (i * 4), newkey); + /* + printf("oldkey is: %02x%02x%02x%02x\r\n", + (old_keys + (i * 4))[0], + (old_keys + (i * 4))[1], + (old_keys + (i * 4))[2], + (old_keys + (i * 4))[3] + );*/ + } + + // 为了避免遇到特殊的控制区的标签, + // 我们这里用新密钥来重置一下控制区 + T55xx_Reset_Passwd(newkey, newkey); + + // 编码410x的数据为block数据,为写卡做准备 + em410x_encoder(uid, datas); + + // 密钥重置完成后,进行写卡操作 + /* + printf("newkey is: %02x%02x%02x%02x\r\n", + newkey[0], + newkey[1], + newkey[2], + newkey[3] + ); + */ + T55xx_Write_data(newkey, datas); + + stop_lf_125khz_radio(); + + // 回读验证并且返回写卡结果 + // 此处不回读,由上位机校验 + return LF_TAG_OK; } /** * 设置EM卡的寻卡超时的时间值 */ void SetEMScanTagTimeout(uint32_t ms) { - g_timeout_readem_ms = ms; + g_timeout_readem_ms = ms; } diff --git a/firmware/application/src/rfid/reader/lf/lf_t55xx_data.c b/firmware/application/src/rfid/reader/lf/lf_t55xx_data.c index 21c85350..3b32ad13 100644 --- a/firmware/application/src/rfid/reader/lf/lf_t55xx_data.c +++ b/firmware/application/src/rfid/reader/lf/lf_t55xx_data.c @@ -26,7 +26,7 @@ NRF_LOG_MODULE_REGISTER(); 01 1 00010100010010010000110110010010 000 00000000000000000000000000000 000 011 01 1 00010100010010010000110110010110 000 - 01010001001001000011011001011000 51243658 + 01010001001001000011011001011000 51243658 10 01010001001001000011011001001000 0 01010001001001000011011001001000 111 @@ -34,14 +34,14 @@ NRF_LOG_MODULE_REGISTER(); | 70bit Password write found | |--------------------------------------------------------------------------| |OP|PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP|L|DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD|AAA| -|10|01010001001001000011011001001000|0|01010001001001000011011001001000|111| 0区 7块 用当前密码写当前密码(密码) -|10|01010001001001000011011001001000|0|01010001001001000111011001001000|111| 0区 7块 用当前密码写当前密码(密码) -|10|01010001001001000011011001001000|0|00000000000101001000000001010000|000| 0区 0块 用当前密码写00148050(控制区) -|10|01010001001001000011011001001000|0|11111111101001010010000000000100|001| 0区 1块 用当前密码写FFA52004(数据) -|11|01010001001001000011011001001000|0|11111111101001010010000000000100|001| 1区 1块 用当前密码写FFA52004(数据) -|10|01010001001001000011011001001000|0|10100101011100011001011101101010|010| 0区 2块 用当前密码写A571976A(数据) -|11|01010001001001000011011001001000|0|10100101011100011001011101101010|010| 1区 2块 用当前密码写A571976A(数据) -|11|01010001001001000011011001001000|0|01100000000000000000100000000000|011| 1区 3块 用当前密码写60000800(射频参数) +|10|01010001001001000011011001001000|0|01010001001001000011011001001000|111| 0区 7块 用当前密码写当前密码(密码) +|10|01010001001001000011011001001000|0|01010001001001000111011001001000|111| 0区 7块 用当前密码写当前密码(密码) +|10|01010001001001000011011001001000|0|00000000000101001000000001010000|000| 0区 0块 用当前密码写00148050(控制区) +|10|01010001001001000011011001001000|0|11111111101001010010000000000100|001| 0区 1块 用当前密码写FFA52004(数据) +|11|01010001001001000011011001001000|0|11111111101001010010000000000100|001| 1区 1块 用当前密码写FFA52004(数据) +|10|01010001001001000011011001001000|0|10100101011100011001011101101010|010| 0区 2块 用当前密码写A571976A(数据) +|11|01010001001001000011011001001000|0|10100101011100011001011101101010|010| 1区 2块 用当前密码写A571976A(数据) +|11|01010001001001000011011001001000|0|01100000000000000000100000000000|011| 1区 3块 用当前密码写60000800(射频参数) |--------------------------------------------------------------------------| RESET Pack received |-----------------------------------------| @@ -94,45 +94,45 @@ void empty_callback() { } //启动定时器和初始化相关外设,启动低频读卡 void init_t55xx_hw(void) { - //注册读卡器io中断回调 - register_rio_callback(empty_callback); + //注册读卡器io中断回调 + register_rio_callback(empty_callback); } void T55xx_SendGap(unsigned int tm) { - stop_lf_125khz_radio(); // 关闭pwm输出 - bsp_delay_us(tm); - start_lf_125khz_radio(); // 启动pwm输出 + stop_lf_125khz_radio(); // 关闭pwm输出 + bsp_delay_us(tm); + start_lf_125khz_radio(); // 启动pwm输出 } void TxBitRfid(uint8_t data) { - if (data & 1) - bsp_delay_us(54 * 8); - else - bsp_delay_us(24 * 8); - T55xx_SendGap(9 * 8); //write gap + if (data & 1) + bsp_delay_us(54 * 8); + else + bsp_delay_us(24 * 8); + T55xx_SendGap(9 * 8); //write gap } void TxByteRfid(uint8_t data) { - for (uint8_t n_bit = 0; n_bit < 8; n_bit++) - { - TxBitRfid(data & 1); - data = data >> 1; - } + for (uint8_t n_bit = 0; n_bit < 8; n_bit++) + { + TxBitRfid(data & 1); + data = data >> 1; + } } // T55XX高精度时序控制函数 void T55XX_Timeslot_Callback() { T55xx_SendGap(30 * 8); // start gap - //先发送指令 - TxBitRfid(t55xx_cmd.opcode >> 1); - TxBitRfid(t55xx_cmd.opcode & 1); + //先发送指令 + TxBitRfid(t55xx_cmd.opcode >> 1); + TxBitRfid(t55xx_cmd.opcode & 1); - //指令为00时不需要发送后面的东西了 - if (t55xx_cmd.opcode != 0) { + //指令为00时不需要发送后面的东西了 + if (t55xx_cmd.opcode != 0) { //指令后如果有需要才发密码 if (t55xx_cmd.usepassword) { @@ -180,16 +180,16 @@ void T55XX_Timeslot_Callback() { */ void T55xx_Send_Cmd(uint8_t opcode, uint8_t usepassword, uint32_t password, uint8_t lockBit, uint8_t usedata, uint32_t data, uint8_t blokAddr) { - //密码读取模式, 2op(1+bck) 32pw 1(0) 3addr - //密码写入模式, 2op(1+bck) 32pw 1l 32data 3addr - //密码唤醒模式, 2op(1+0) 32pw + //密码读取模式, 2op(1+bck) 32pw 1(0) 3addr + //密码写入模式, 2op(1+bck) 32pw 1l 32data 3addr + //密码唤醒模式, 2op(1+0) 32pw - //直接读取模式, 2op(1+bck) 1(0) 3addr - //标准写入模式, 2op(1+bck) 1l 32data 3addr + //直接读取模式, 2op(1+bck) 1(0) 3addr + //标准写入模式, 2op(1+bck) 1l 32data 3addr - //这个不实现//标准读取页模式, 2op(1+bck) + //这个不实现//标准读取页模式, 2op(1+bck) - //重置模式, 2op(0+0) + //重置模式, 2op(0+0) t55xx_cmd.opcode = opcode; t55xx_cmd.usepassword = usepassword; @@ -201,7 +201,7 @@ void T55xx_Send_Cmd(uint8_t opcode, uint8_t usepassword, uint32_t password, uint // 请求时序,并且等待时序操作完成 - request_timeslot(37 * 1000, T55XX_Timeslot_Callback, true); + request_timeslot(37 * 1000, T55XX_Timeslot_Callback, true); if (opcode != 0) { bsp_delay_ms(6); // 可能继续下次写卡,需要多等一会儿 @@ -218,39 +218,39 @@ void T55xx_Send_Cmd(uint8_t opcode, uint8_t usepassword, uint32_t password, uint */ void T55xx_Write_data(uint8_t *passwd, uint8_t *datas) { - uint32_t blk1data = 0, blk2data = 0, u32passwd = 0; - //提取两个block的数据和密码 - for (uint8_t dataindex = 0; dataindex < 4; dataindex++) - { - blk1data = blk1data << 8; - blk1data |= (uint8_t)datas[dataindex]; - u32passwd = u32passwd << 8; - u32passwd |= (uint8_t)passwd[dataindex]; - } - for (uint8_t dataindex = 4; dataindex < 8; dataindex++) - { - blk2data = blk2data << 8; - blk2data |= (uint8_t)datas[dataindex]; - } - //先写入密码区 - T55xx_Send_Cmd(2, 1, u32passwd, 0, 1, u32passwd, 7); //0区 7块 用当前密码写当前密码(密码) - T55xx_Send_Cmd(2, 1, u32passwd, 0, 1, u32passwd, 7); //0区 7块 用当前密码写当前密码(密码) - //然后写入控制区 - T55xx_Send_Cmd(2, 1, u32passwd, 0, 1, 0X00148050, 0); //0区 0块 用当前密码写00148050(控制区) - //然后写入数据 - T55xx_Send_Cmd(2, 1, u32passwd, 0, 1, blk1data, 1); //0区 1块 用当前密码写blk1data(数据) - T55xx_Send_Cmd(3, 1, u32passwd, 0, 1, blk1data, 1); //1区 1块 用当前密码写blk1data(数据) - T55xx_Send_Cmd(2, 1, u32passwd, 0, 1, blk2data, 2); //0区 2块 用当前密码写blk2data(数据) - T55xx_Send_Cmd(3, 1, u32passwd, 0, 1, blk2data, 2); //1区 2块 用当前密码写blk2data(数据) - //然后写入射频参数 - // 2021-12-15 fix:写此数据会导致小卡无法重复写 - // T55xx_Send_Cmd(3, 1, u32passwd, 0, 1, 0X60000800, 3); //1区 3块 用当前密码写60000800(射频参数) - - //然后用无密码指令再写一遍 - T55xx_Send_Cmd(2, 0, 0, 0, 1, 0X00148050, 0); //0区 0块 写00148050(控制区) - T55xx_Send_Cmd(2, 0, 0, 0, 1, blk1data, 1); //0区 1块 写blk1data(数据) - T55xx_Send_Cmd(2, 0, 0, 0, 1, blk2data, 2); //0区 2块 写blk2data(数据) - T55xx_Send_Cmd(0, 0, 0, 0, 0, 0, 0); //重启卡片 + uint32_t blk1data = 0, blk2data = 0, u32passwd = 0; + //提取两个block的数据和密码 + for (uint8_t dataindex = 0; dataindex < 4; dataindex++) + { + blk1data = blk1data << 8; + blk1data |= (uint8_t)datas[dataindex]; + u32passwd = u32passwd << 8; + u32passwd |= (uint8_t)passwd[dataindex]; + } + for (uint8_t dataindex = 4; dataindex < 8; dataindex++) + { + blk2data = blk2data << 8; + blk2data |= (uint8_t)datas[dataindex]; + } + //先写入密码区 + T55xx_Send_Cmd(2, 1, u32passwd, 0, 1, u32passwd, 7); //0区 7块 用当前密码写当前密码(密码) + T55xx_Send_Cmd(2, 1, u32passwd, 0, 1, u32passwd, 7); //0区 7块 用当前密码写当前密码(密码) + //然后写入控制区 + T55xx_Send_Cmd(2, 1, u32passwd, 0, 1, 0X00148050, 0); //0区 0块 用当前密码写00148050(控制区) + //然后写入数据 + T55xx_Send_Cmd(2, 1, u32passwd, 0, 1, blk1data, 1); //0区 1块 用当前密码写blk1data(数据) + T55xx_Send_Cmd(3, 1, u32passwd, 0, 1, blk1data, 1); //1区 1块 用当前密码写blk1data(数据) + T55xx_Send_Cmd(2, 1, u32passwd, 0, 1, blk2data, 2); //0区 2块 用当前密码写blk2data(数据) + T55xx_Send_Cmd(3, 1, u32passwd, 0, 1, blk2data, 2); //1区 2块 用当前密码写blk2data(数据) + //然后写入射频参数 + // 2021-12-15 fix:写此数据会导致小卡无法重复写 + // T55xx_Send_Cmd(3, 1, u32passwd, 0, 1, 0X60000800, 3); //1区 3块 用当前密码写60000800(射频参数) + + //然后用无密码指令再写一遍 + T55xx_Send_Cmd(2, 0, 0, 0, 1, 0X00148050, 0); //0区 0块 写00148050(控制区) + T55xx_Send_Cmd(2, 0, 0, 0, 1, blk1data, 1); //0区 1块 写blk1data(数据) + T55xx_Send_Cmd(2, 0, 0, 0, 1, blk2data, 2); //0区 2块 写blk2data(数据) + T55xx_Send_Cmd(0, 0, 0, 0, 0, 0, 0); //重启卡片 } /** @@ -260,17 +260,17 @@ void T55xx_Write_data(uint8_t *passwd, uint8_t *datas) * @param newpasswd 用于最后加密的密码(是一个指针,4字节宽度小端byte序存储) */ void T55xx_Reset_Passwd(uint8_t *oldpasswd, uint8_t *newpasswd){ - uint32_t u32oldpasswd = 0, u32newpasswd = 0; - //提取两个block的数据和密码 - for (uint8_t dataindex = 0; dataindex < 4; dataindex++) - { - u32oldpasswd = u32oldpasswd << 8; - u32oldpasswd |= (uint8_t)oldpasswd[dataindex]; - u32newpasswd = u32newpasswd << 8; - u32newpasswd |= (uint8_t)newpasswd[dataindex]; - } - - T55xx_Send_Cmd(2, 1, u32oldpasswd, 0, 1, u32newpasswd, 7); //0区 7块 用当前密码写新密码(密码) - T55xx_Send_Cmd(2, 1, u32oldpasswd, 0, 1, u32newpasswd, 7); //0区 7块 用当前密码写新密码(密码) - T55xx_Send_Cmd(0, 0, 0, 0, 0, 0, 0); //重启卡片 + uint32_t u32oldpasswd = 0, u32newpasswd = 0; + //提取两个block的数据和密码 + for (uint8_t dataindex = 0; dataindex < 4; dataindex++) + { + u32oldpasswd = u32oldpasswd << 8; + u32oldpasswd |= (uint8_t)oldpasswd[dataindex]; + u32newpasswd = u32newpasswd << 8; + u32newpasswd |= (uint8_t)newpasswd[dataindex]; + } + + T55xx_Send_Cmd(2, 1, u32oldpasswd, 0, 1, u32newpasswd, 7); //0区 7块 用当前密码写新密码(密码) + T55xx_Send_Cmd(2, 1, u32oldpasswd, 0, 1, u32newpasswd, 7); //0区 7块 用当前密码写新密码(密码) + T55xx_Send_Cmd(0, 0, 0, 0, 0, 0, 0); //重启卡片 } diff --git a/firmware/application/src/rgb_marquee.c b/firmware/application/src/rgb_marquee.c index 5ab3a1ba..f949a8b4 100644 --- a/firmware/application/src/rgb_marquee.c +++ b/firmware/application/src/rgb_marquee.c @@ -19,19 +19,19 @@ static nrf_drv_pwm_t pwm0_ins = NRF_DRV_PWM_INSTANCE(1); nrf_pwm_values_individual_t pwm_sequ_val;//独立模式下的PWM控制4通道的占空比 nrf_pwm_sequence_t const seq = //配置pwm输出用的结构体 { - .values.p_individual = &pwm_sequ_val, - .length = 4, - .repeats = 0, - .end_delay = 0 + .values.p_individual = &pwm_sequ_val, + .length = 4, + .repeats = 0, + .end_delay = 0 }; nrf_drv_pwm_config_t pwm_config = //PWM配置结构体 { - .irq_priority = APP_IRQ_PRIORITY_LOWEST, - .base_clock = NRF_PWM_CLK_1MHz, - .count_mode = NRF_PWM_MODE_UP, - .top_value = PWM_MAX, - .load_mode = NRF_PWM_LOAD_INDIVIDUAL,//4个通道用四个值 - .step_mode = NRF_PWM_STEP_AUTO + .irq_priority = APP_IRQ_PRIORITY_LOWEST, + .base_clock = NRF_PWM_CLK_1MHz, + .count_mode = NRF_PWM_MODE_UP, + .top_value = PWM_MAX, + .load_mode = NRF_PWM_LOAD_INDIVIDUAL,//4个通道用四个值 + .step_mode = NRF_PWM_STEP_AUTO }; static autotimer *timer; static uint8_t ledblink6_step = 0; @@ -44,16 +44,16 @@ void rgb_marquee_init(void){ } void rgb_marquee_stop(void){ - nrfx_pwm_stop(&pwm0_ins, true); - nrfx_pwm_uninit(&pwm0_ins); //关闭pwm输出 - ledblink6_step = 0; - ledblink1_step = 0; + nrfx_pwm_stop(&pwm0_ins, true); + nrfx_pwm_uninit(&pwm0_ins); //关闭pwm输出 + ledblink6_step = 0; + ledblink1_step = 0; } // reset RGB state machines to force a refresh of the LED color void rgb_marquee_reset(void){ - ledblink6_step = 0; - ledblink1_step = 0; + ledblink6_step = 0; + ledblink1_step = 0; } // 亮度转PWM值 @@ -64,139 +64,139 @@ uint16_t get_pwmduty(uint8_t light_level){ //4灯同亮度水平移动循环(不返回) //COLOR 0-R,1-G,2-B void ledblink1(uint8_t color, uint8_t dir){ - static uint8_t startled = 0; - static uint8_t setled = 0; - uint32_t* led_pins_arr; - - if (!g_usb_led_marquee_enable && ledblink1_step != 0) { - startled = 0; - setled = 0; - rgb_marquee_stop(); - return; - } - - //处理方向 - if(dir == 0){ - led_pins_arr = hw_get_led_array(); - } else{ - led_pins_arr = hw_get_led_reversal_array(); - } - - if (ledblink1_step == 0) { - //调整颜色 - set_slot_light_color(color); - pwm_sequ_val.channel_0 = 1; - pwm_sequ_val.channel_1 = 1; - pwm_sequ_val.channel_2 = 1; - pwm_sequ_val.channel_3 = 1; - bsp_set_timer(timer, 0); - ledblink1_step = 1; - - // 重置USB开启通信时的灯的状态 - ledblink6_step = 0; - } - - if (ledblink1_step == 1) { - setled = startled; - for(uint8_t i=0;i<4;i++){ - pwm_config.output_pins[i] = led_pins_arr[setled]; - setled++; - if(setled>7)setled=0; - } - startled++; - if(startled>7)startled = 0; - nrfx_pwm_uninit(&pwm0_ins); - nrf_drv_pwm_init(&pwm0_ins, &pwm_config, NULL); - nrf_drv_pwm_simple_playback(&pwm0_ins, &seq, 1,NRF_DRV_PWM_FLAG_LOOP); - - bsp_set_timer(timer, 0); - ledblink1_step = 2; - } - - if (ledblink1_step == 2) { - if (!(NO_TIMEOUT_1MS(timer, 80))) { - ledblink1_step = 1; - } - } + static uint8_t startled = 0; + static uint8_t setled = 0; + uint32_t* led_pins_arr; + + if (!g_usb_led_marquee_enable && ledblink1_step != 0) { + startled = 0; + setled = 0; + rgb_marquee_stop(); + return; + } + + //处理方向 + if(dir == 0){ + led_pins_arr = hw_get_led_array(); + } else{ + led_pins_arr = hw_get_led_reversal_array(); + } + + if (ledblink1_step == 0) { + //调整颜色 + set_slot_light_color(color); + pwm_sequ_val.channel_0 = 1; + pwm_sequ_val.channel_1 = 1; + pwm_sequ_val.channel_2 = 1; + pwm_sequ_val.channel_3 = 1; + bsp_set_timer(timer, 0); + ledblink1_step = 1; + + // 重置USB开启通信时的灯的状态 + ledblink6_step = 0; + } + + if (ledblink1_step == 1) { + setled = startled; + for(uint8_t i=0;i<4;i++){ + pwm_config.output_pins[i] = led_pins_arr[setled]; + setled++; + if(setled>7)setled=0; + } + startled++; + if(startled>7)startled = 0; + nrfx_pwm_uninit(&pwm0_ins); + nrf_drv_pwm_init(&pwm0_ins, &pwm_config, NULL); + nrf_drv_pwm_simple_playback(&pwm0_ins, &seq, 1,NRF_DRV_PWM_FLAG_LOOP); + + bsp_set_timer(timer, 0); + ledblink1_step = 2; + } + + if (ledblink1_step == 2) { + if (!(NO_TIMEOUT_1MS(timer, 80))) { + ledblink1_step = 1; + } + } } //4灯拖尾水平移动循环(不返回),包含尾部消失和头部缓入 //dir 0-从1卡槽到8卡槽,1-从8卡槽到1卡槽 (方向,结束点由end参数决定) //end 要扫描的灯数量,和方向一起决定最终动画区域 void ledblink2(uint8_t color,uint8_t dir, uint8_t end){ - uint8_t startled = 0; - uint8_t setled = 0; - uint8_t leds2turnon = 0; - uint8_t i = 0; - uint32_t * led_pins_arr; - //处理方向 - if(dir == 0){ - led_pins_arr = hw_get_led_array(); - } - else{ - led_pins_arr = hw_get_led_reversal_array(); - } - - //调整颜色 - set_slot_light_color(color); - pwm_sequ_val.channel_3 = 1; //最亮的 - pwm_sequ_val.channel_2 = 600; - pwm_sequ_val.channel_1 = 880; - pwm_sequ_val.channel_0 = 980;//最暗的 - while(1) { - //关闭所有通道 - pwm_config.output_pins[0] = NRF_DRV_PWM_PIN_NOT_USED; - pwm_config.output_pins[1] = NRF_DRV_PWM_PIN_NOT_USED; - pwm_config.output_pins[2] = NRF_DRV_PWM_PIN_NOT_USED; - pwm_config.output_pins[3] = NRF_DRV_PWM_PIN_NOT_USED; - - setled = startled; - if(setled<3){//正向期间,0,1,2的时候只能点亮前几个led - //首先确定能点亮几个灯 - leds2turnon = setled+1;//1,2,3 - //然后设置pwm输出通道 - for(i=0;i7&&setled<=10){//正向期间,8.9.10的时候只能点亮后几个led - //首先确定能点亮几个灯 - leds2turnon = 11-setled; - //然后设置pwm输出通道 - for(i=0;i=end){ - //计算需要隐藏几个灯 - leds2turnon = startled-end; - //把超出去的都隐藏了 - for(i=0;i=4)break; - if(startled>11)break; - } + uint8_t startled = 0; + uint8_t setled = 0; + uint8_t leds2turnon = 0; + uint8_t i = 0; + uint32_t * led_pins_arr; + //处理方向 + if(dir == 0){ + led_pins_arr = hw_get_led_array(); + } + else{ + led_pins_arr = hw_get_led_reversal_array(); + } + + //调整颜色 + set_slot_light_color(color); + pwm_sequ_val.channel_3 = 1; //最亮的 + pwm_sequ_val.channel_2 = 600; + pwm_sequ_val.channel_1 = 880; + pwm_sequ_val.channel_0 = 980;//最暗的 + while(1) { + //关闭所有通道 + pwm_config.output_pins[0] = NRF_DRV_PWM_PIN_NOT_USED; + pwm_config.output_pins[1] = NRF_DRV_PWM_PIN_NOT_USED; + pwm_config.output_pins[2] = NRF_DRV_PWM_PIN_NOT_USED; + pwm_config.output_pins[3] = NRF_DRV_PWM_PIN_NOT_USED; + + setled = startled; + if(setled<3){//正向期间,0,1,2的时候只能点亮前几个led + //首先确定能点亮几个灯 + leds2turnon = setled+1;//1,2,3 + //然后设置pwm输出通道 + for(i=0;i7&&setled<=10){//正向期间,8.9.10的时候只能点亮后几个led + //首先确定能点亮几个灯 + leds2turnon = 11-setled; + //然后设置pwm输出通道 + for(i=0;i=end){ + //计算需要隐藏几个灯 + leds2turnon = startled-end; + //把超出去的都隐藏了 + for(i=0;i=4)break; + if(startled>11)break; + } } //切换卡槽动画 @@ -206,68 +206,68 @@ void ledblink2(uint8_t color,uint8_t dir, uint8_t end){ //color_led_down 要熄灭的led的颜色 0-R,1-G,2-B volatile bool callback_waiting = 0; static void ledblink3_pwm_callback(nrfx_pwm_evt_type_t event_type){ - if (event_type == NRF_DRV_PWM_EVT_FINISHED) { - callback_waiting = 1; - } + if (event_type == NRF_DRV_PWM_EVT_FINISHED) { + callback_waiting = 1; + } } void ledblink3(uint8_t led_down,uint8_t color_led_down, uint8_t led_up, uint8_t color_led_up){ - int16_t light_level= 99;//led亮度值 - uint32_t* led_pins = hw_get_led_array(); - if(led_down>=0 &&led_down<=7){ - //先处理要熄灭的 - pwm_config.output_pins[0] = led_pins[led_down]; - pwm_config.output_pins[1] = NRF_DRV_PWM_PIN_NOT_USED; - pwm_config.output_pins[2] = NRF_DRV_PWM_PIN_NOT_USED; - pwm_config.output_pins[3] = NRF_DRV_PWM_PIN_NOT_USED; - while(light_level >= 0){ - //处理亮度 - pwm_sequ_val.channel_0 = get_pwmduty(light_level); - - nrfx_pwm_uninit(&pwm0_ins); //关闭pwm输出 - - if(led_up>=0 &&led_up<=7){ - nrf_gpio_pin_clear(led_pins[led_up]); - } - - set_slot_light_color(color_led_down); - - nrf_drv_pwm_init(&pwm0_ins, &pwm_config, ledblink3_pwm_callback); - nrf_drv_pwm_simple_playback(&pwm0_ins, &seq, 1,NRF_DRV_PWM_FLAG_LOOP); - - while(callback_waiting == 0);//等待pwm模块输出完成 - bsp_delay_us(1234); - callback_waiting = 0; - light_level --; - } - } - if(led_up>=0 &&led_up<=7){ - //处理要点亮的 - pwm_config.output_pins[0] = led_pins[led_up]; - pwm_config.output_pins[1] = NRF_DRV_PWM_PIN_NOT_USED; - pwm_config.output_pins[2] = NRF_DRV_PWM_PIN_NOT_USED; - pwm_config.output_pins[3] = NRF_DRV_PWM_PIN_NOT_USED; - light_level = 0; - while(light_level < 99){ - //处理亮度 - pwm_sequ_val.channel_0 = get_pwmduty(light_level); - - nrfx_pwm_uninit(&pwm0_ins); //关闭pwm输出 - - if(led_down>=0 &&led_down<=7){ - nrf_gpio_pin_clear(led_pins[led_down]); - } - - set_slot_light_color(color_led_up); - - nrf_drv_pwm_init(&pwm0_ins, &pwm_config, ledblink3_pwm_callback); - nrf_drv_pwm_simple_playback(&pwm0_ins, &seq, 1,NRF_DRV_PWM_FLAG_LOOP); - - while(callback_waiting == 0);//等待pwm模块输出完成 - bsp_delay_us(1234); - callback_waiting = 0; - light_level ++; - } - } + int16_t light_level= 99;//led亮度值 + uint32_t* led_pins = hw_get_led_array(); + if(led_down>=0 &&led_down<=7){ + //先处理要熄灭的 + pwm_config.output_pins[0] = led_pins[led_down]; + pwm_config.output_pins[1] = NRF_DRV_PWM_PIN_NOT_USED; + pwm_config.output_pins[2] = NRF_DRV_PWM_PIN_NOT_USED; + pwm_config.output_pins[3] = NRF_DRV_PWM_PIN_NOT_USED; + while(light_level >= 0){ + //处理亮度 + pwm_sequ_val.channel_0 = get_pwmduty(light_level); + + nrfx_pwm_uninit(&pwm0_ins); //关闭pwm输出 + + if(led_up>=0 &&led_up<=7){ + nrf_gpio_pin_clear(led_pins[led_up]); + } + + set_slot_light_color(color_led_down); + + nrf_drv_pwm_init(&pwm0_ins, &pwm_config, ledblink3_pwm_callback); + nrf_drv_pwm_simple_playback(&pwm0_ins, &seq, 1,NRF_DRV_PWM_FLAG_LOOP); + + while(callback_waiting == 0);//等待pwm模块输出完成 + bsp_delay_us(1234); + callback_waiting = 0; + light_level --; + } + } + if(led_up>=0 &&led_up<=7){ + //处理要点亮的 + pwm_config.output_pins[0] = led_pins[led_up]; + pwm_config.output_pins[1] = NRF_DRV_PWM_PIN_NOT_USED; + pwm_config.output_pins[2] = NRF_DRV_PWM_PIN_NOT_USED; + pwm_config.output_pins[3] = NRF_DRV_PWM_PIN_NOT_USED; + light_level = 0; + while(light_level < 99){ + //处理亮度 + pwm_sequ_val.channel_0 = get_pwmduty(light_level); + + nrfx_pwm_uninit(&pwm0_ins); //关闭pwm输出 + + if(led_down>=0 &&led_down<=7){ + nrf_gpio_pin_clear(led_pins[led_down]); + } + + set_slot_light_color(color_led_up); + + nrf_drv_pwm_init(&pwm0_ins, &pwm_config, ledblink3_pwm_callback); + nrf_drv_pwm_simple_playback(&pwm0_ins, &seq, 1,NRF_DRV_PWM_FLAG_LOOP); + + while(callback_waiting == 0);//等待pwm模块输出完成 + bsp_delay_us(1234); + callback_waiting = 0; + light_level ++; + } + } } //4灯拖尾水平移动循环(不返回),不包含尾部消失但是包含头部缓入(用于弹球类型动画) @@ -275,74 +275,74 @@ void ledblink3(uint8_t led_down,uint8_t color_led_down, uint8_t led_up, uint8_t //end 要扫描的灯数量,和方向一起决定最终动画区域 //start_light stop_light 0-99 表示渐变亮度 void ledblink4(uint8_t color,uint8_t dir, uint8_t end,uint8_t start_light,uint8_t stop_light){ - uint8_t startled = 0; - uint8_t setled = 0; - uint8_t leds2turnon = 0; - uint8_t i = 0; - uint32_t * led_pins_arr; - volatile double light_cnd; - //处理方向 - if(dir == 0){ - led_pins_arr = hw_get_led_array(); - } - else{ - led_pins_arr = hw_get_led_reversal_array(); - } - - //调整颜色 - set_slot_light_color(color); - while(1) { - //设置亮度 - //当前亮度系数 - //start经过end次数达到stop - light_cnd = (((double)stop_light-(double)start_light)/end)*startled+start_light; - pwm_sequ_val.channel_3 = get_pwmduty((uint8_t)(0.99*light_cnd));//1; //最亮的 - pwm_sequ_val.channel_2 = get_pwmduty((uint8_t)(0.60*light_cnd));//600; - pwm_sequ_val.channel_1 = get_pwmduty((uint8_t)(0.30*light_cnd));//880; - pwm_sequ_val.channel_0 = get_pwmduty((uint8_t)(0.01*light_cnd));//980;//最暗的 - //关闭所有通道 - pwm_config.output_pins[0] = NRF_DRV_PWM_PIN_NOT_USED; - pwm_config.output_pins[1] = NRF_DRV_PWM_PIN_NOT_USED; - pwm_config.output_pins[2] = NRF_DRV_PWM_PIN_NOT_USED; - pwm_config.output_pins[3] = NRF_DRV_PWM_PIN_NOT_USED; - - setled = startled; - if(setled<3){//正向期间,0,1,2的时候只能点亮前几个led - //首先确定能点亮几个灯 - leds2turnon = setled+1;//1,2,3 - //然后设置pwm输出通道 - for(i=0;i7&&setled<=10){//正向期间,8.9.10的时候只能点亮后几个led - //首先确定能点亮几个灯 - leds2turnon = 11-setled; - //然后设置pwm输出通道 - for(i=0;i=4)break; - if(startled>11)break; - } + uint8_t startled = 0; + uint8_t setled = 0; + uint8_t leds2turnon = 0; + uint8_t i = 0; + uint32_t * led_pins_arr; + volatile double light_cnd; + //处理方向 + if(dir == 0){ + led_pins_arr = hw_get_led_array(); + } + else{ + led_pins_arr = hw_get_led_reversal_array(); + } + + //调整颜色 + set_slot_light_color(color); + while(1) { + //设置亮度 + //当前亮度系数 + //start经过end次数达到stop + light_cnd = (((double)stop_light-(double)start_light)/end)*startled+start_light; + pwm_sequ_val.channel_3 = get_pwmduty((uint8_t)(0.99*light_cnd));//1; //最亮的 + pwm_sequ_val.channel_2 = get_pwmduty((uint8_t)(0.60*light_cnd));//600; + pwm_sequ_val.channel_1 = get_pwmduty((uint8_t)(0.30*light_cnd));//880; + pwm_sequ_val.channel_0 = get_pwmduty((uint8_t)(0.01*light_cnd));//980;//最暗的 + //关闭所有通道 + pwm_config.output_pins[0] = NRF_DRV_PWM_PIN_NOT_USED; + pwm_config.output_pins[1] = NRF_DRV_PWM_PIN_NOT_USED; + pwm_config.output_pins[2] = NRF_DRV_PWM_PIN_NOT_USED; + pwm_config.output_pins[3] = NRF_DRV_PWM_PIN_NOT_USED; + + setled = startled; + if(setled<3){//正向期间,0,1,2的时候只能点亮前几个led + //首先确定能点亮几个灯 + leds2turnon = setled+1;//1,2,3 + //然后设置pwm输出通道 + for(i=0;i7&&setled<=10){//正向期间,8.9.10的时候只能点亮后几个led + //首先确定能点亮几个灯 + leds2turnon = 11-setled; + //然后设置pwm输出通道 + for(i=0;i=4)break; + if(startled>11)break; + } } //单灯水平移动 @@ -350,28 +350,28 @@ void ledblink4(uint8_t color,uint8_t dir, uint8_t end,uint8_t start_light,uint8_ //start 启动灯位 //stop 停止灯位 void ledblink5(uint8_t color,uint8_t start, uint8_t stop){ - uint8_t setled = start; - uint32_t * led_pins = hw_get_led_array(); - //设置亮度 - pwm_sequ_val.channel_3 = 0; - pwm_sequ_val.channel_2 = 0; - pwm_sequ_val.channel_1 = 0; - pwm_sequ_val.channel_0 = get_pwmduty(99); - //调整颜色 - set_slot_light_color(color); - while(setled < (start < stop ? stop + 1 : stop - 1)) { - //关闭所有通道 - pwm_config.output_pins[0] = NRF_DRV_PWM_PIN_NOT_USED; - pwm_config.output_pins[1] = NRF_DRV_PWM_PIN_NOT_USED; - pwm_config.output_pins[2] = NRF_DRV_PWM_PIN_NOT_USED; - pwm_config.output_pins[3] = NRF_DRV_PWM_PIN_NOT_USED; - pwm_config.output_pins[0] = led_pins[setled]; - nrfx_pwm_uninit(&pwm0_ins); - nrf_drv_pwm_init(&pwm0_ins, &pwm_config, NULL); - nrf_drv_pwm_simple_playback(&pwm0_ins, &seq, 1,NRF_DRV_PWM_FLAG_LOOP); - bsp_delay_ms(50); - setled = start < stop ? setled + 1 : setled - 1; - } + uint8_t setled = start; + uint32_t * led_pins = hw_get_led_array(); + //设置亮度 + pwm_sequ_val.channel_3 = 0; + pwm_sequ_val.channel_2 = 0; + pwm_sequ_val.channel_1 = 0; + pwm_sequ_val.channel_0 = get_pwmduty(99); + //调整颜色 + set_slot_light_color(color); + while(setled < (start < stop ? stop + 1 : stop - 1)) { + //关闭所有通道 + pwm_config.output_pins[0] = NRF_DRV_PWM_PIN_NOT_USED; + pwm_config.output_pins[1] = NRF_DRV_PWM_PIN_NOT_USED; + pwm_config.output_pins[2] = NRF_DRV_PWM_PIN_NOT_USED; + pwm_config.output_pins[3] = NRF_DRV_PWM_PIN_NOT_USED; + pwm_config.output_pins[0] = led_pins[setled]; + nrfx_pwm_uninit(&pwm0_ins); + nrf_drv_pwm_init(&pwm0_ins, &pwm_config, NULL); + nrf_drv_pwm_simple_playback(&pwm0_ins, &seq, 1,NRF_DRV_PWM_FLAG_LOOP); + bsp_delay_ms(50); + setled = start < stop ? setled + 1 : setled - 1; + } } @@ -379,110 +379,110 @@ void ledblink5(uint8_t color,uint8_t start, uint8_t stop){ //perc 电池当前百分比 0-4 4代表满电呼吸灯 volatile bool callback_waiting6 = 0; void ledblink6_pwm_callback(nrfx_pwm_evt_type_t event_type){ - if (event_type == NRF_DRV_PWM_EVT_FINISHED) { - callback_waiting6 = 1; - } + if (event_type == NRF_DRV_PWM_EVT_FINISHED) { + callback_waiting6 = 1; + } } void ledblink6(void){ - uint32_t* led_array = hw_get_led_array(); - const uint16_t delay_time = 25; - static int16_t light_level = 99; //led亮度值 - - if (!g_usb_led_marquee_enable && ledblink6_step != 0) { - light_level = 99; - callback_waiting6 = 0; - rgb_marquee_stop(); - return; - } - - if (ledblink6_step == 0) { - set_slot_light_color(0); - for (uint8_t i = 0; i < RGB_LIST_NUM; i++) { - nrf_gpio_pin_clear(led_array[i]); - } - pwm_config.output_pins[0] = led_array[2]; - pwm_config.output_pins[1] = led_array[3]; - pwm_config.output_pins[2] = led_array[4]; - pwm_config.output_pins[3] = led_array[5]; - ledblink6_step = 1; - - // 重置USB未开启通信时的灯的状态 - ledblink1_step = 0; - } - - if (ledblink6_step == 1) { - light_level = 0; - ledblink6_step = 2; - } - - if (ledblink6_step == 2 || ledblink6_step == 3 || ledblink6_step == 4) { - if (light_level <= 99) { - if (ledblink6_step == 2) { - //处理亮度 - pwm_sequ_val.channel_0 = get_pwmduty(light_level); - pwm_sequ_val.channel_1 = pwm_sequ_val.channel_0; - pwm_sequ_val.channel_2 = pwm_sequ_val.channel_0; - pwm_sequ_val.channel_3 = pwm_sequ_val.channel_0; - nrfx_pwm_uninit(&pwm0_ins); //关闭pwm输出 - set_slot_light_color(1); - nrf_drv_pwm_init(&pwm0_ins, &pwm_config, ledblink6_pwm_callback); - nrf_drv_pwm_simple_playback(&pwm0_ins, &seq, 1,NRF_DRV_PWM_FLAG_LOOP); - ledblink6_step = 3; - } - if (ledblink6_step == 3) { //等待pwm模块输出完成 - if (callback_waiting6 != 0) { - ledblink6_step = 4; - bsp_set_timer(timer, 0); - } - } - if (ledblink6_step == 4) { - if (!NO_TIMEOUT_1MS(timer, delay_time)) { - callback_waiting = 0; - light_level++; - ledblink6_step = 2; - } - } - } else { - ledblink6_step = 5; - } - } - - if (ledblink6_step == 5) { - light_level = 99; - ledblink6_step = 6; - } - - if (ledblink6_step == 6 || ledblink6_step == 7 || ledblink6_step == 8) { - if (light_level >=0) { - if (ledblink6_step == 6) { - //处理亮度 - pwm_sequ_val.channel_0 = get_pwmduty(light_level); - pwm_sequ_val.channel_1 = pwm_sequ_val.channel_0; - pwm_sequ_val.channel_2 = pwm_sequ_val.channel_0; - pwm_sequ_val.channel_3 = pwm_sequ_val.channel_0; - nrfx_pwm_uninit(&pwm0_ins); //关闭pwm输出 - set_slot_light_color(1); - nrf_drv_pwm_init(&pwm0_ins, &pwm_config, ledblink6_pwm_callback); - nrf_drv_pwm_simple_playback(&pwm0_ins, &seq, 1,NRF_DRV_PWM_FLAG_LOOP); - ledblink6_step = 7; - } - if (ledblink6_step == 7) { //等待pwm模块输出完成 - if (callback_waiting6 != 0) { - ledblink6_step = 8; - bsp_set_timer(timer, 0); - } - } - if (ledblink6_step == 8) { - if (!NO_TIMEOUT_1MS(timer, delay_time)) { - callback_waiting = 0; - light_level--; - ledblink6_step = 6; - } - } - } else { - ledblink6_step = 0; - } - } + uint32_t* led_array = hw_get_led_array(); + const uint16_t delay_time = 25; + static int16_t light_level = 99; //led亮度值 + + if (!g_usb_led_marquee_enable && ledblink6_step != 0) { + light_level = 99; + callback_waiting6 = 0; + rgb_marquee_stop(); + return; + } + + if (ledblink6_step == 0) { + set_slot_light_color(0); + for (uint8_t i = 0; i < RGB_LIST_NUM; i++) { + nrf_gpio_pin_clear(led_array[i]); + } + pwm_config.output_pins[0] = led_array[2]; + pwm_config.output_pins[1] = led_array[3]; + pwm_config.output_pins[2] = led_array[4]; + pwm_config.output_pins[3] = led_array[5]; + ledblink6_step = 1; + + // 重置USB未开启通信时的灯的状态 + ledblink1_step = 0; + } + + if (ledblink6_step == 1) { + light_level = 0; + ledblink6_step = 2; + } + + if (ledblink6_step == 2 || ledblink6_step == 3 || ledblink6_step == 4) { + if (light_level <= 99) { + if (ledblink6_step == 2) { + //处理亮度 + pwm_sequ_val.channel_0 = get_pwmduty(light_level); + pwm_sequ_val.channel_1 = pwm_sequ_val.channel_0; + pwm_sequ_val.channel_2 = pwm_sequ_val.channel_0; + pwm_sequ_val.channel_3 = pwm_sequ_val.channel_0; + nrfx_pwm_uninit(&pwm0_ins); //关闭pwm输出 + set_slot_light_color(1); + nrf_drv_pwm_init(&pwm0_ins, &pwm_config, ledblink6_pwm_callback); + nrf_drv_pwm_simple_playback(&pwm0_ins, &seq, 1,NRF_DRV_PWM_FLAG_LOOP); + ledblink6_step = 3; + } + if (ledblink6_step == 3) { //等待pwm模块输出完成 + if (callback_waiting6 != 0) { + ledblink6_step = 4; + bsp_set_timer(timer, 0); + } + } + if (ledblink6_step == 4) { + if (!NO_TIMEOUT_1MS(timer, delay_time)) { + callback_waiting = 0; + light_level++; + ledblink6_step = 2; + } + } + } else { + ledblink6_step = 5; + } + } + + if (ledblink6_step == 5) { + light_level = 99; + ledblink6_step = 6; + } + + if (ledblink6_step == 6 || ledblink6_step == 7 || ledblink6_step == 8) { + if (light_level >=0) { + if (ledblink6_step == 6) { + //处理亮度 + pwm_sequ_val.channel_0 = get_pwmduty(light_level); + pwm_sequ_val.channel_1 = pwm_sequ_val.channel_0; + pwm_sequ_val.channel_2 = pwm_sequ_val.channel_0; + pwm_sequ_val.channel_3 = pwm_sequ_val.channel_0; + nrfx_pwm_uninit(&pwm0_ins); //关闭pwm输出 + set_slot_light_color(1); + nrf_drv_pwm_init(&pwm0_ins, &pwm_config, ledblink6_pwm_callback); + nrf_drv_pwm_simple_playback(&pwm0_ins, &seq, 1,NRF_DRV_PWM_FLAG_LOOP); + ledblink6_step = 7; + } + if (ledblink6_step == 7) { //等待pwm模块输出完成 + if (callback_waiting6 != 0) { + ledblink6_step = 8; + bsp_set_timer(timer, 0); + } + } + if (ledblink6_step == 8) { + if (!NO_TIMEOUT_1MS(timer, delay_time)) { + callback_waiting = 0; + light_level--; + ledblink6_step = 6; + } + } + } else { + ledblink6_step = 0; + } + } } /** @@ -492,5 +492,5 @@ void ledblink6(void){ * @return false 禁止状态,处于普通卡槽指示灯状态 */ bool is_rgb_marquee_enable(void) { - return g_usb_led_marquee_enable; + return g_usb_led_marquee_enable; } diff --git a/firmware/application/src/utils/timeslot.c b/firmware/application/src/utils/timeslot.c index 644dcc59..ecf77e61 100644 --- a/firmware/application/src/utils/timeslot.c +++ b/firmware/application/src/utils/timeslot.c @@ -120,12 +120,12 @@ void request_timeslot(uint32_t time_us, timeslot_callback_t callback, bool wait_ } // 进入临界点 - NVIC_DisableIRQ(RADIO_IRQn); - NVIC_DisableIRQ(TIMER0_IRQn); - NVIC_DisableIRQ(TIMER2_IRQn); - NVIC_DisableIRQ(GPIOTE_IRQn); - NVIC_DisableIRQ(MWU_IRQn); - NVIC_DisableIRQ(RTC1_IRQn); + NVIC_DisableIRQ(RADIO_IRQn); + NVIC_DisableIRQ(TIMER0_IRQn); + NVIC_DisableIRQ(TIMER2_IRQn); + NVIC_DisableIRQ(GPIOTE_IRQn); + NVIC_DisableIRQ(MWU_IRQn); + NVIC_DisableIRQ(RTC1_IRQn); // 请求时序成功,快处理任务 if (m_callback != NULL) { @@ -134,9 +134,9 @@ void request_timeslot(uint32_t time_us, timeslot_callback_t callback, bool wait_ } // 退出临界点 - NVIC_EnableIRQ(GPIOTE_IRQn); - NVIC_EnableIRQ(RTC1_IRQn); - NVIC_EnableIRQ(MWU_IRQn); + NVIC_EnableIRQ(GPIOTE_IRQn); + NVIC_EnableIRQ(RTC1_IRQn); + NVIC_EnableIRQ(MWU_IRQn); // 关闭会话并且等待关闭完成 err_code = sd_radio_session_close(); @@ -177,12 +177,12 @@ void timeslot_start(uint32_t time_us) { } // 进入临界点 - NVIC_DisableIRQ(RADIO_IRQn); - NVIC_DisableIRQ(TIMER0_IRQn); - NVIC_DisableIRQ(TIMER2_IRQn); - //NVIC_DisableIRQ(GPIOTE_IRQn); - NVIC_DisableIRQ(MWU_IRQn); - NVIC_DisableIRQ(RTC1_IRQn); + NVIC_DisableIRQ(RADIO_IRQn); + NVIC_DisableIRQ(TIMER0_IRQn); + NVIC_DisableIRQ(TIMER2_IRQn); + //NVIC_DisableIRQ(GPIOTE_IRQn); + NVIC_DisableIRQ(MWU_IRQn); + NVIC_DisableIRQ(RTC1_IRQn); //NRF_LOG_INFO("timeslot start."); } @@ -197,9 +197,9 @@ void timeslot_stop(void) { m_is_timeslot_running = false; // 退出临界点 - //NVIC_EnableIRQ(GPIOTE_IRQn); - NVIC_EnableIRQ(RTC1_IRQn); - NVIC_EnableIRQ(MWU_IRQn); + //NVIC_EnableIRQ(GPIOTE_IRQn); + NVIC_EnableIRQ(RTC1_IRQn); + NVIC_EnableIRQ(MWU_IRQn); // 关闭会话并且等待关闭完成 err_code = sd_radio_session_close(); diff --git a/software/src/darkside.c b/software/src/darkside.c index 1049c1b0..9efda7ac 100644 --- a/software/src/darkside.c +++ b/software/src/darkside.c @@ -9,127 +9,127 @@ #include "mfkey.h" typedef struct { - uint32_t nt; - uint32_t nr; - uint32_t ar; + uint32_t nt; + uint32_t nr; + uint32_t ar; - uint64_t par_list; - uint64_t ks_list; + uint64_t par_list; + uint64_t ks_list; } DarksideParam; // 转换字符串为U32类型 uint64_t atoui(const char* str) { - uint64_t result = 0; - for (int i = 0; str[i] != '\0'; ++i) { - if (str[i] >= '0' && str[i] <= '9') { - result = result * 10 + str[i] - '0'; - } - } - return result; + uint64_t result = 0; + for (int i = 0; str[i] != '\0'; ++i) { + if (str[i] >= '0' && str[i] <= '9') { + result = result * 10 + str[i] - '0'; + } + } + return result; } void num_to_bytes(uint64_t n, uint32_t len, uint8_t* dest) { - while (len--) { - dest[len] = (uint8_t)n; - n >>= 8; - } + while (len--) { + dest[len] = (uint8_t)n; + n >>= 8; + } } int main(int argc, char* argv[]) { - if (((argc - 2) % 5) != 0) { - printf("Unexcepted param count\n"); - return EXIT_FAILURE; - } - // 初始化UID + if (((argc - 2) % 5) != 0) { + printf("Unexcepted param count\n"); + return EXIT_FAILURE; + } + // 初始化UID uint32_t uid = (uint32_t)atoui(argv[1]); - uint32_t count = 0, i = 0; - uint32_t keycount = 0; - uint64_t* keylist = NULL, * last_keylist = NULL; - DarksideParam* dps = NULL; - bool no_key_recover = true; - - for (i = 1; i + 5 < argc;) { - void *pTmp = realloc(dps, sizeof(DarksideParam) * ++count); - if (pTmp == NULL) { - printf("Can't malloc at param construct."); - return EXIT_FAILURE; - } - dps = pTmp; - dps[count - 1].nt = (uint32_t)atoui(argv[++i]); - dps[count - 1].ks_list = atoui(argv[++i]); - dps[count - 1].par_list = atoui(argv[++i]); - dps[count - 1].nr = (uint32_t)atoui(argv[++i]); - dps[count - 1].ar = (uint32_t)atoui(argv[++i]); - } - - for (i = 0; i < count; i++) { - // 初始化NT, NR, AR - uint32_t nt = dps[i].nt; - uint32_t nr = dps[i].nr; - uint32_t ar = dps[i].ar; - - uint64_t par_list = dps[i].par_list; - uint64_t ks_list = dps[i].ks_list; - - /* - printf("UID = %"PRIu32"\r\n", uid); - printf("NT = %"PRIu32"\r\n", nt); - printf("KS = %"PRIu64"\r\n", ks_list); - printf("PAR = %"PRIu64"\r\n", par_list); - printf("NR = %"PRIu32"\r\n", nr); - printf("AR = %"PRIu32"\r\n", ar); - */ - - // 开始解密 - keycount = nonce2key(uid, nt, nr, ar, par_list, ks_list, &keylist); - - if (keycount == 0) { - continue; - } - - // only parity zero attack - if (par_list == 0) { - qsort(keylist, keycount, sizeof(*keylist), compare_uint64); - keycount = intersection(last_keylist, keylist); - if (keycount == 0) { - free(last_keylist); - last_keylist = keylist; - continue; - } - } - uint8_t key_tmp[6] = { 0 }; - if (keycount > 0) { - no_key_recover = false; - for (i = 0; i < keycount; i++) { - if (par_list == 0) { - num_to_bytes(last_keylist[i], 6, key_tmp); - } - else { - num_to_bytes(keylist[i], 6, key_tmp); - } - printf("Key%d: %02X%02X%02X%02X%02X%02X\r\n", i + 1, key_tmp[0], key_tmp[1], key_tmp[2], key_tmp[3], key_tmp[4], key_tmp[5]); - } - } - } - - if (no_key_recover) { - printf("key not found\r\n"); - } - - if (last_keylist == keylist && last_keylist != NULL) { - free(keylist); - } - else { - if (last_keylist) { - free(last_keylist); - } - if (keylist) { - free(keylist); - } - } - free(dps); + uint32_t count = 0, i = 0; + uint32_t keycount = 0; + uint64_t* keylist = NULL, * last_keylist = NULL; + DarksideParam* dps = NULL; + bool no_key_recover = true; + + for (i = 1; i + 5 < argc;) { + void *pTmp = realloc(dps, sizeof(DarksideParam) * ++count); + if (pTmp == NULL) { + printf("Can't malloc at param construct."); + return EXIT_FAILURE; + } + dps = pTmp; + dps[count - 1].nt = (uint32_t)atoui(argv[++i]); + dps[count - 1].ks_list = atoui(argv[++i]); + dps[count - 1].par_list = atoui(argv[++i]); + dps[count - 1].nr = (uint32_t)atoui(argv[++i]); + dps[count - 1].ar = (uint32_t)atoui(argv[++i]); + } + + for (i = 0; i < count; i++) { + // 初始化NT, NR, AR + uint32_t nt = dps[i].nt; + uint32_t nr = dps[i].nr; + uint32_t ar = dps[i].ar; + + uint64_t par_list = dps[i].par_list; + uint64_t ks_list = dps[i].ks_list; + + /* + printf("UID = %"PRIu32"\r\n", uid); + printf("NT = %"PRIu32"\r\n", nt); + printf("KS = %"PRIu64"\r\n", ks_list); + printf("PAR = %"PRIu64"\r\n", par_list); + printf("NR = %"PRIu32"\r\n", nr); + printf("AR = %"PRIu32"\r\n", ar); + */ + + // 开始解密 + keycount = nonce2key(uid, nt, nr, ar, par_list, ks_list, &keylist); + + if (keycount == 0) { + continue; + } + + // only parity zero attack + if (par_list == 0) { + qsort(keylist, keycount, sizeof(*keylist), compare_uint64); + keycount = intersection(last_keylist, keylist); + if (keycount == 0) { + free(last_keylist); + last_keylist = keylist; + continue; + } + } + uint8_t key_tmp[6] = { 0 }; + if (keycount > 0) { + no_key_recover = false; + for (i = 0; i < keycount; i++) { + if (par_list == 0) { + num_to_bytes(last_keylist[i], 6, key_tmp); + } + else { + num_to_bytes(keylist[i], 6, key_tmp); + } + printf("Key%d: %02X%02X%02X%02X%02X%02X\r\n", i + 1, key_tmp[0], key_tmp[1], key_tmp[2], key_tmp[3], key_tmp[4], key_tmp[5]); + } + } + } + + if (no_key_recover) { + printf("key not found\r\n"); + } + + if (last_keylist == keylist && last_keylist != NULL) { + free(keylist); + } + else { + if (last_keylist) { + free(last_keylist); + } + if (keylist) { + free(keylist); + } + } + free(dps); return EXIT_SUCCESS; } diff --git a/software/src/nested.c b/software/src/nested.c index ae2f044d..e77fa35e 100644 --- a/software/src/nested.c +++ b/software/src/nested.c @@ -19,254 +19,254 @@ typedef struct { - uint64_t key; - int count; + uint64_t key; + int count; } countKeys; typedef struct { - uint32_t ntp; - uint32_t ks1; + uint32_t ntp; + uint32_t ks1; } NtpKs1; typedef struct { - NtpKs1* pNK; - uint32_t authuid; + NtpKs1* pNK; + uint32_t authuid; - uint64_t* keys; - uint32_t keyCount; + uint64_t* keys; + uint32_t keyCount; - uint32_t startPos; - uint32_t endPos; + uint32_t startPos; + uint32_t endPos; } RecPar; int compar_int(const void* a, const void* b) { - return (*(uint64_t*)b - *(uint64_t*)a); + return (*(uint64_t*)b - *(uint64_t*)a); } // Compare countKeys structure int compar_special_int(const void* a, const void* b) { - return (((countKeys*)b)->count - ((countKeys*)a)->count); + return (((countKeys*)b)->count - ((countKeys*)a)->count); } // keys qsort and unique. countKeys* uniqsort(uint64_t* possibleKeys, uint32_t size) { - unsigned int i, j = 0; - int count = 0; - countKeys* our_counts; - - qsort(possibleKeys, size, sizeof(uint64_t), compar_int); - - our_counts = calloc(size, sizeof(countKeys)); - if (our_counts == NULL) { - printf("Memory allocation error for our_counts"); - exit(EXIT_FAILURE); - } - - for (i = 0; i < size; i++) { - if (possibleKeys[i + 1] == possibleKeys[i]) { - count++; - } - else { - our_counts[j].key = possibleKeys[i]; - our_counts[j].count = count; - j++; - count = 0; - } - } - qsort(our_counts, j, sizeof(countKeys), compar_special_int); - return (our_counts); + unsigned int i, j = 0; + int count = 0; + countKeys* our_counts; + + qsort(possibleKeys, size, sizeof(uint64_t), compar_int); + + our_counts = calloc(size, sizeof(countKeys)); + if (our_counts == NULL) { + printf("Memory allocation error for our_counts"); + exit(EXIT_FAILURE); + } + + for (i = 0; i < size; i++) { + if (possibleKeys[i + 1] == possibleKeys[i]) { + count++; + } + else { + our_counts[j].key = possibleKeys[i]; + our_counts[j].count = count; + j++; + count = 0; + } + } + qsort(our_counts, j, sizeof(countKeys), compar_special_int); + return (our_counts); } uint32_t atoui(const char* str) { - uint32_t result = 0; - for (int i = 0; str[i] != '\0'; ++i) { - if (str[i] >= '0' && str[i] <= '9') { - result = result * 10 + str[i] - '0'; - } - } - return result; + uint32_t result = 0; + for (int i = 0; str[i] != '\0'; ++i) { + if (str[i] >= '0' && str[i] <= '9') { + result = result * 10 + str[i] - '0'; + } + } + return result; } // nested decrypt static void nested_revover(RecPar* rp) { - struct Crypto1State* revstate, * revstate_start = NULL; - uint64_t lfsr = 0; - uint32_t i, kcount = 0; - - rp->keyCount = 0; - rp->keys = NULL; - - for (i = rp->startPos; i < rp->endPos; i++) { - uint32_t nt_probe = rp->pNK[i].ntp; - uint32_t ks1 = rp->pNK[i].ks1; - // And finally recover the first 32 bits of the key - revstate = lfsr_recovery32(ks1, nt_probe ^ rp->authuid); - if (revstate_start == NULL) { - revstate_start = revstate; - } - while ((revstate->odd != 0x0) || (revstate->even != 0x0)) { - lfsr_rollback_word(revstate, nt_probe ^ rp->authuid, 0); - crypto1_get_lfsr(revstate, &lfsr); - // Allocate a new space for keys - if (((kcount % MEM_CHUNK) == 0) || (kcount >= rp->keyCount)) { - rp->keyCount += MEM_CHUNK; - // printf("New chunk by %d, sizeof %lu\n", kcount, key_count * sizeof(uint64_t)); - void* tmp = realloc(rp->keys, rp->keyCount * sizeof(uint64_t)); - if (tmp == NULL) { - printf("Memory allocation error for pk->possibleKeys"); - // exit(EXIT_FAILURE); - rp->keyCount = 0; - return; - } - rp->keys = (uint64_t*)tmp; - } - rp->keys[kcount] = lfsr; - kcount++; - revstate++; - } - free(revstate_start); - revstate_start = NULL; - } - // Truncate - if (kcount != 0) { - rp->keyCount = --kcount; - void* tmp = (uint64_t*)realloc(rp->keys, rp->keyCount * sizeof(uint64_t)); - if (tmp == NULL) { - printf("Memory allocation error for pk->possibleKeys"); - // exit(EXIT_FAILURE); - rp->keyCount = 0; - return; - } - rp->keys = tmp; - return; - } - rp->keyCount = 0; - return; + struct Crypto1State* revstate, * revstate_start = NULL; + uint64_t lfsr = 0; + uint32_t i, kcount = 0; + + rp->keyCount = 0; + rp->keys = NULL; + + for (i = rp->startPos; i < rp->endPos; i++) { + uint32_t nt_probe = rp->pNK[i].ntp; + uint32_t ks1 = rp->pNK[i].ks1; + // And finally recover the first 32 bits of the key + revstate = lfsr_recovery32(ks1, nt_probe ^ rp->authuid); + if (revstate_start == NULL) { + revstate_start = revstate; + } + while ((revstate->odd != 0x0) || (revstate->even != 0x0)) { + lfsr_rollback_word(revstate, nt_probe ^ rp->authuid, 0); + crypto1_get_lfsr(revstate, &lfsr); + // Allocate a new space for keys + if (((kcount % MEM_CHUNK) == 0) || (kcount >= rp->keyCount)) { + rp->keyCount += MEM_CHUNK; + // printf("New chunk by %d, sizeof %lu\n", kcount, key_count * sizeof(uint64_t)); + void* tmp = realloc(rp->keys, rp->keyCount * sizeof(uint64_t)); + if (tmp == NULL) { + printf("Memory allocation error for pk->possibleKeys"); + // exit(EXIT_FAILURE); + rp->keyCount = 0; + return; + } + rp->keys = (uint64_t*)tmp; + } + rp->keys[kcount] = lfsr; + kcount++; + revstate++; + } + free(revstate_start); + revstate_start = NULL; + } + // Truncate + if (kcount != 0) { + rp->keyCount = --kcount; + void* tmp = (uint64_t*)realloc(rp->keys, rp->keyCount * sizeof(uint64_t)); + if (tmp == NULL) { + printf("Memory allocation error for pk->possibleKeys"); + // exit(EXIT_FAILURE); + rp->keyCount = 0; + return; + } + rp->keys = tmp; + return; + } + rp->keyCount = 0; + return; } uint64_t* nested(NtpKs1* pNK, uint32_t sizePNK, uint32_t authuid, uint32_t* keyCount) { - *keyCount = 0; - uint32_t i; - - RecPar* pRPs = malloc(sizeof(RecPar)); - if (pRPs == NULL) { - return NULL; - } - - pRPs->pNK = pNK; - pRPs->authuid = authuid; - pRPs->startPos = 0; - pRPs->endPos = sizePNK; - - // start recover - nested_revover(pRPs); - *keyCount = pRPs->keyCount; - - uint64_t* keys = NULL; - if (*keyCount != 0) { - keys = malloc(*keyCount * sizeof(uint64_t)); - if (keys != NULL) { - memcpy(keys, pRPs->keys, pRPs->keyCount * sizeof(uint64_t)); - free(pRPs->keys); - } - } - free(pRPs); - - countKeys* ck = uniqsort(keys, *keyCount); - free(keys); - keys = (uint64_t*)NULL; - *keyCount = 0; - - if (ck != NULL) { - for (i = 0; i < TRY_KEYS; i++) { - // We don't known this key, try to break it - // This key can be found here two or more times - if (ck[i].count > 0) { - *keyCount += 1; - void* tmp = realloc(keys, sizeof(uint64_t) * (*keyCount)); - if (tmp != NULL) { - keys = tmp; - keys[*keyCount - 1] = ck[i].key; - } - else { - printf("Cannot allocate memory for keys on merge."); - free(keys); - break; - } - } - } - } - else { - printf("Cannot allocate memory for ck on uniqsort."); - } - return keys; + *keyCount = 0; + uint32_t i; + + RecPar* pRPs = malloc(sizeof(RecPar)); + if (pRPs == NULL) { + return NULL; + } + + pRPs->pNK = pNK; + pRPs->authuid = authuid; + pRPs->startPos = 0; + pRPs->endPos = sizePNK; + + // start recover + nested_revover(pRPs); + *keyCount = pRPs->keyCount; + + uint64_t* keys = NULL; + if (*keyCount != 0) { + keys = malloc(*keyCount * sizeof(uint64_t)); + if (keys != NULL) { + memcpy(keys, pRPs->keys, pRPs->keyCount * sizeof(uint64_t)); + free(pRPs->keys); + } + } + free(pRPs); + + countKeys* ck = uniqsort(keys, *keyCount); + free(keys); + keys = (uint64_t*)NULL; + *keyCount = 0; + + if (ck != NULL) { + for (i = 0; i < TRY_KEYS; i++) { + // We don't known this key, try to break it + // This key can be found here two or more times + if (ck[i].count > 0) { + *keyCount += 1; + void* tmp = realloc(keys, sizeof(uint64_t) * (*keyCount)); + if (tmp != NULL) { + keys = tmp; + keys[*keyCount - 1] = ck[i].key; + } + else { + printf("Cannot allocate memory for keys on merge."); + free(keys); + break; + } + } + } + } + else { + printf("Cannot allocate memory for ck on uniqsort."); + } + return keys; } // Return 1 if the nonce is invalid else return 0 static uint8_t valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t* parity) { - return ( - (oddparity8((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity8((NtEnc >> 24) & 0xFF) ^ BIT(Ks1, 16))) && \ - (oddparity8((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity8((NtEnc >> 16) & 0xFF) ^ BIT(Ks1, 8))) && \ - (oddparity8((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity8((NtEnc >> 8) & 0xFF) ^ BIT(Ks1, 0))) - ) ? 1 : 0; + return ( + (oddparity8((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity8((NtEnc >> 24) & 0xFF) ^ BIT(Ks1, 16))) && \ + (oddparity8((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity8((NtEnc >> 16) & 0xFF) ^ BIT(Ks1, 8))) && \ + (oddparity8((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity8((NtEnc >> 8) & 0xFF) ^ BIT(Ks1, 0))) + ) ? 1 : 0; } int main(int argc, char* const argv[]) { - NtpKs1* pNK = NULL; - uint32_t i, j, m; - uint32_t nt1, nt2, nttest, ks1, dist; - uint8_t par_int; - uint8_t par_arr[3] = { 0x00 }; - - uint32_t authuid = atoui(argv[1]); // uid - dist = atoui(argv[2]); // dist - - // process all args. - for (i = 3, j = 0; i < argc; i += 3) { - // nt + par - nt1 = atoui(argv[i]); - nt2 = atoui(argv[i + 1]); - par_int = atoui(argv[i + 2]); - if (par_int != 0) { - for (m = 0; m < 3; m++) { - par_arr[m] = (par_int >> m) & 0x01; - } - } - else { - memset(par_arr, 0, 3); - } - // Try to recover the keystream1 - nttest = prng_successor(nt1, dist - 14); - for (m = dist - 14; m <= dist + 14; m += 1) { - ks1 = nt2 ^ nttest; - if (valid_nonce(nttest, nt2, ks1, par_arr)) { - ++j; - // append to list - void* tmp = realloc(pNK, sizeof(NtpKs1) * j); - if (tmp == NULL) { - goto error; - } - pNK = tmp; - pNK[j - 1].ntp = nttest; - pNK[j - 1].ks1 = ks1; - } - nttest = prng_successor(nttest, 1); - } - } - uint32_t keyCount = 0; - uint64_t* keys = nested(pNK, j, authuid, &keyCount); - - if (keyCount > 0) { - for (i = 0; i < keyCount; i++) { - printf("Key %d... %" PRIx64 " \r\n", i + 1, keys[i]); - fflush(stdout); - } - } - fflush(stdout); - free(keys); - exit(EXIT_SUCCESS); + NtpKs1* pNK = NULL; + uint32_t i, j, m; + uint32_t nt1, nt2, nttest, ks1, dist; + uint8_t par_int; + uint8_t par_arr[3] = { 0x00 }; + + uint32_t authuid = atoui(argv[1]); // uid + dist = atoui(argv[2]); // dist + + // process all args. + for (i = 3, j = 0; i < argc; i += 3) { + // nt + par + nt1 = atoui(argv[i]); + nt2 = atoui(argv[i + 1]); + par_int = atoui(argv[i + 2]); + if (par_int != 0) { + for (m = 0; m < 3; m++) { + par_arr[m] = (par_int >> m) & 0x01; + } + } + else { + memset(par_arr, 0, 3); + } + // Try to recover the keystream1 + nttest = prng_successor(nt1, dist - 14); + for (m = dist - 14; m <= dist + 14; m += 1) { + ks1 = nt2 ^ nttest; + if (valid_nonce(nttest, nt2, ks1, par_arr)) { + ++j; + // append to list + void* tmp = realloc(pNK, sizeof(NtpKs1) * j); + if (tmp == NULL) { + goto error; + } + pNK = tmp; + pNK[j - 1].ntp = nttest; + pNK[j - 1].ks1 = ks1; + } + nttest = prng_successor(nttest, 1); + } + } + uint32_t keyCount = 0; + uint64_t* keys = nested(pNK, j, authuid, &keyCount); + + if (keyCount > 0) { + for (i = 0; i < keyCount; i++) { + printf("Key %d... %" PRIx64 " \r\n", i + 1, keys[i]); + fflush(stdout); + } + } + fflush(stdout); + free(keys); + exit(EXIT_SUCCESS); error: - exit(EXIT_FAILURE); + exit(EXIT_FAILURE); }