project merge

This commit is contained in:
dxl
2022-12-22 12:43:05 +08:00
commit d866e6f962
4541 changed files with 2802266 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
.idea/
.vscode/
+359
View File
@@ -0,0 +1,359 @@
#include "fds_util.h"
#include "bsp_time.h"
#include "bsp_delay.h"
#include "usb_main.h"
#include "rfid_main.h"
#include "ble_main.h"
#include "syssleep.h"
#include "tag_emulation.h"
#include "hex_utils.h"
#include "data_cmd.h"
#include "app_cmd.h"
#define NRF_LOG_MODULE_NAME app_cmd
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
NRF_LOG_MODULE_REGISTER();
data_frame_tx_t* cmd_processor_get_version(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
uint32_t version = 0xDEADBEEF;
return data_frame_make(cmd, 0xDED1, 4, (uint8_t*)&version);
}
data_frame_tx_t* cmd_processor_change_device_mode(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
if (length == 1) {
if (data[0] == 1) {
reader_mode_enter();
} else {
tag_mode_enter();
}
} else {
return data_frame_make(cmd, STATUS_PAR_ERR, 0, NULL);
}
return data_frame_make(cmd, 0x0000, 0, NULL);
}
data_frame_tx_t* cmd_processor_get_device_mode(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
device_mode_t mode = get_device_mode();
if (mode == DEVICE_MODE_READER) {
status = 1;
} else {
status = 0;
}
return data_frame_make(cmd, 0x0000, 1, (uint8_t*)&status);
}
data_frame_tx_t* cmd_processor_14a_scan(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
picc_14a_tag_t taginfo;
status = pcd_14a_reader_scan_auto(&taginfo);
if (status == HF_TAG_OK) {
length = sizeof(picc_14a_tag_t);
data = (uint8_t*)&taginfo;
} else {
length = 0;
data = NULL;
}
return data_frame_make(cmd, status, length, data);
}
data_frame_tx_t* cmd_processor_detect_mf1_support(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
status = Check_STDMifareNT_Support();
return data_frame_make(cmd, status, 0, NULL);
}
data_frame_tx_t* cmd_processor_detect_mf1_nt_level(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
status = Check_WeakNested_Support();
return data_frame_make(cmd, status, 0, NULL);
}
data_frame_tx_t* cmd_processor_detect_mf1_darkside(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
status = Check_Darkside_Support();
return data_frame_make(cmd, status, 0, NULL);
}
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;
}
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;
}
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;
}
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;
}
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]);
pcd_14a_reader_mf1_unauth();
} 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) {
// 直接调用标准读取API去读取卡片
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) {
// 直接调用标准写入API去写入卡片
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);
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) {
// 写入T55XX的标签需要提供一个5个Byte长度的卡号
// 并且还需要提供至少一个新的密钥,与一个旧的密钥
if (length >= 13 && (length - 9) % 4 == 0) {
status = PcdWriteT55XX(
data, // 传入UID
data + 5, // 传入newkey
data + 9, // 传入oldkey
(length - 9) / 4 // 传入减去newkey + uid后的剩余的oldkey的密钥组数
);
} else {
status = STATUS_PAR_ERR;
}
return data_frame_make(cmd, status, 0, NULL);
}
data_frame_tx_t* cmd_processor_set_slot_activated(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
// 需要确保传过来的卡槽号码不要超过支持的上限
if (length == 1 && data[0] < TAG_MAX_SLOT_NUM) {
uint8_t slot = data[0];
device_mode_t mode = get_device_mode();
// 读卡器模式下不需要禁用模拟卡再进行切换
tag_emulation_change_slot(slot, mode != DEVICE_MODE_READER);
light_up_by_slot();
set_slot_ligth_color(0);
status = STATUS_DEVICE_SUCCESS;
} else {
status = STATUS_PAR_ERR;
}
return data_frame_make(cmd, status, 0, NULL);
}
data_frame_tx_t* cmd_processor_set_slot_tag_type(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
// 需要确保传过来的标签类型是有效的
if (length == 1 && data[0] != TAG_TYPE_UNKNOWN) {
// 取出上位机传过来的标签类型
tag_specific_type_t tag_type = data[0];
// 获得当前使能的卡槽
uint8_t slot_index_now = tag_emulation_get_slot();
// 将当前的卡槽切换到指定的模拟卡类型
tag_emulation_change_type(slot_index_now, tag_type);
status = STATUS_DEVICE_SUCCESS;
} else {
status = STATUS_PAR_ERR;
}
return data_frame_make(cmd, status, 0, NULL);
}
data_frame_tx_t* cmd_processor_set_slot_data_default(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
// 需要确保传过来的标签类型是有效的
if (length == 2 && data[0] < TAG_MAX_SLOT_NUM && data[1] != TAG_TYPE_UNKNOWN) {
uint8_t target_init_slot_num = data[0]; // 获得要操作的卡槽
tag_specific_type_t tag_type = data[1]; // 取出上位机传过来的标签类型
// 重置当前的卡槽为缺省数据,如果失败,则可能是并未实现此API的缺省
status = tag_emulation_factory_data(target_init_slot_num, tag_type) ? STATUS_DEVICE_SUCCESS : STATUS_NOT_IMPLEMENTED;
} else {
status = STATUS_PAR_ERR;
}
return data_frame_make(cmd, status, 0, NULL);
}
/**
* before reader run, reset reader and on antenna,
* we must to wait some time, to init picc(power).
*/
data_frame_tx_t* before_reader_run(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
device_mode_t mode = get_device_mode();
if (mode == DEVICE_MODE_READER) {
pcd_14a_reader_reset();
pcd_14a_reader_antenna_on();
bsp_delay_ms(8);
return NULL;
} else {
return data_frame_make(cmd, STATUS_DEVIEC_MODE_ERROR, 0, NULL);
}
}
/**
* after reader run, off antenna, to keep battery.
*/
data_frame_tx_t* after_reader_run(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
pcd_14a_reader_antenna_off();
return NULL;
}
/**
* (cmd -> process) function map, the map struct is:
* cmd code before process cmd processor after process
*/
static cmd_data_map_t m_data_cmd_map[] = {
{ DATA_CMD_GET_APP_VERSION, NULL, cmd_processor_get_version, NULL },
{ DATA_CMD_CHANGE_DEVICE_MODE, NULL, cmd_processor_change_device_mode, NULL },
{ DATA_CMD_GET_DEVICE_MODE, NULL, cmd_processor_get_device_mode, NULL },
{ DATA_CMD_SCAN_14A_TAG, before_reader_run, cmd_processor_14a_scan, after_reader_run },
{ DATA_CMD_MF1_SUPPORT_DETECT, before_reader_run, cmd_processor_detect_mf1_support, after_reader_run },
{ DATA_CMD_MF1_NT_LEVEL_DETECT, before_reader_run, cmd_processor_detect_mf1_nt_level, after_reader_run },
{ DATA_CMD_MF1_DARKSIDE_DETECT, before_reader_run, cmd_processor_detect_mf1_darkside, after_reader_run },
{ DATA_CMD_MF1_DARKSIDE_ACQUIRE, before_reader_run, cmd_processor_mf1_darkside_acquire, after_reader_run },
{ DATA_CMD_MF1_NT_DIST_DETECT, before_reader_run, cmd_processor_mf1_nt_distance, after_reader_run },
{ DATA_CMD_MF1_NESTED_ACQUIRE, before_reader_run, cmd_processor_mf1_nested_acquire, after_reader_run },
{ DATA_CMD_MF1_CHECK_ONE_KEY_BLOCK, before_reader_run, cmd_processor_mf1_auth_one_key_block, after_reader_run },
{ DATA_CMD_MF1_READ_ONE_BLOCK, before_reader_run, cmd_processor_mf1_read_one_block, after_reader_run },
{ DATA_CMD_MF1_WRITE_ONE_BLOCK, before_reader_run, cmd_processor_mf1_write_one_block, after_reader_run },
{ DATA_CMD_SCAN_EM410X_TAG, NULL, cmd_processor_em410x_scan, NULL },
{ DATA_CMD_WRITE_EM410X_TO_T5577, NULL, cmd_processor_write_em410x_2_t57, NULL },
{ DATA_CMD_SET_SLOT_ACTIVATED, NULL, cmd_processor_set_slot_activated, NULL },
{ DATA_CMD_SET_SLOT_TAG_TYPE, NULL, cmd_processor_set_slot_tag_type, NULL },
{ DATA_CMD_SET_SLOT_DATA_DEFAULT, NULL, cmd_processor_set_slot_data_default, NULL },
};
/**@brief Function for prcoess data frame(cmd)
*/
void on_data_frame_received(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
data_frame_tx_t* response = NULL;
bool is_cmd_support = false;
// print info
NRF_LOG_INFO("Data frame: cmd = %02x, status = %02x, length = %d", cmd, status, length);
NRF_LOG_HEXDUMP_INFO(data, length);
for (int i = 0; i < ARRAY_SIZE(m_data_cmd_map); i++) {
if (m_data_cmd_map[i].cmd == cmd) {
is_cmd_support = true;
if (m_data_cmd_map[i].cmd_before != NULL) {
data_frame_tx_t* before_resp = m_data_cmd_map[i].cmd_before(cmd, status, length, data);
if (before_resp != NULL) {
// some problem found before run cmd.
response = before_resp;
break;
}
}
if (m_data_cmd_map[i].cmd_processor != NULL) response = m_data_cmd_map[i].cmd_processor(cmd, status, length, data);
if (m_data_cmd_map[i].cmd_after != NULL) {
data_frame_tx_t* after_resp = m_data_cmd_map[i].cmd_after(cmd, status, length, data);
if (after_resp != NULL) {
// some problem found after run cmd.
response = after_resp;
break;
}
}
break;
}
}
if (is_cmd_support) {
// check and response
if (response != NULL) {
usb_cdc_write(response->buffer, response->length);
}
} else {
// response cmd unsupport.
response = data_frame_make(cmd, STATUS_INVALID_CMD, 0, NULL);
usb_cdc_write(response->buffer, response->length);
NRF_LOG_INFO("Data frame cmd invalid: %d,", cmd);
}
}
+19
View File
@@ -0,0 +1,19 @@
#ifndef APP_CMD_H
#define APP_CMD_H
#include <stdint.h>
#include "dataframe.h"
typedef data_frame_tx_t* (*cmd_processor)(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data);
typedef struct {
uint16_t cmd;
cmd_processor cmd_before;
cmd_processor cmd_processor;
cmd_processor cmd_after;
} cmd_data_map_t;
void on_data_frame_received(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data);
#endif
+431
View File
@@ -0,0 +1,431 @@
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "nordic_common.h"
#include "nrf.h"
#include "app_timer.h"
#include "app_usbd.h"
#include "app_util_platform.h"
#include "nrf_pwr_mgmt.h"
#include "nrf_power.h"
#include "nrfx_power.h"
#include "nrf_drv_rng.h"
#include "nrf_delay.h"
#include "nrf_drv_gpiote.h"
#include "nrfx_nfct.h"
#define NRF_LOG_MODULE_NAME app_main
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
NRF_LOG_MODULE_REGISTER();
#include "fds_util.h"
#include "bsp_time.h"
#include "bsp_delay.h"
#include "usb_main.h"
#include "rfid_main.h"
#include "ble_main.h"
#include "syssleep.h"
#include "tag_emulation.h"
#include "dataframe.h"
#include "hex_utils.h"
#include "app_cmd.h"
// 定义软定时器
APP_TIMER_DEF(m_button_check_timer); // 用于按钮防抖的定时器
static bool m_is_read_btn_press = false;
static bool m_is_write_btn_press = false;
/**@brief Function for assert macro callback.
*
* @details This function will be called in case of an assert in the SoftDevice.
*
* @warning This handler is an example only and does not fit a final product. You need to analyse
* how your product is supposed to react in case of Assert.
* @warning On assert from the SoftDevice, the system can only recover on reset.
*
* @param[in] line_num Line number of the failing ASSERT call.
* @param[in] p_file_name File name of the failing ASSERT call.
*/
void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name)
{
// /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */
app_error_handler(0xDEADBEEF, line_num, p_file_name);
}
/**@brief Function for initializing the timer module.
*/
static void app_timers_init(void)
{
ret_code_t err_code = app_timer_init();
APP_ERROR_CHECK(err_code);
}
/**@brief Function for putting the chip into sleep mode.
*
* @note This function will not return.
*/
static void sleep_mode_enter(void)
{
ret_code_t err_code;
// Go to system-off mode (this function will not return; wakeup will cause a reset).
// 注意,如果插着jlink或者开着debug,进入低功耗的函数可能会报错,
// 开启调试时我们应当禁用低功耗状态值检测,或者干脆不进入低功耗
err_code = sd_power_system_off();
// OK,此处非常重要,如果开启了日志输出并且使能了RTT,则不去检查低功耗模式的错误
#if !(NRF_LOG_ENABLED && NRF_LOG_BACKEND_RTT_ENABLED)
APP_ERROR_CHECK(err_code);
#else
UNUSED_VARIABLE(err_code);
#endif
}
/**@brief Function for initializing the nrf log module.
*/
static void log_init(void)
{
ret_code_t err_code = NRF_LOG_INIT(NULL);
APP_ERROR_CHECK(err_code);
NRF_LOG_DEFAULT_BACKENDS_INIT();
}
/**@brief Function for initializing power management.
*/
static void power_management_init(void)
{
ret_code_t err_code;
err_code = nrf_pwr_mgmt_init();
APP_ERROR_CHECK(err_code);
}
/**@brief Function for initializing power management.
*/
static void rng_drv_and_srand_init(void)
{
ret_code_t err_code;
uint8_t available;
uint32_t rand_int;
// 先初始化官方的rng管理驱动api
err_code = nrf_drv_rng_init(NULL);
APP_ERROR_CHECK(err_code);
// 等待随机数管理器生成足够的随机数放到队列里
do {
nrf_drv_rng_bytes_available(&available);
} while (available < 4);
// 注意,此处我们是将一个uint32_t的值的地址强制转换为uint8_t的地址
// 以获得uint32的首个字节的指针的指向
err_code = nrf_drv_rng_rand(((uint8_t *)(&rand_int)), 4);
APP_ERROR_CHECK(err_code);
// 最后初始化c标准库中的srand种子
srand(rand_int);
}
/**@brief 初始化GPIO矩阵库
*/
static void gpio_te_init(void) {
// 初始化GPIOTE
uint32_t err_code = nrf_drv_gpiote_init();
APP_ERROR_CHECK(err_code);
}
/**@brief 按钮矩阵事件
*/
static void button_pin_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
device_mode_t mode = get_device_mode();
// 暂时只允许模拟卡模式响应按钮的操作
if (mode == DEVICE_MODE_TAG) {
static nrf_drv_gpiote_pin_t pin_static; // 使用静态内部变量去存放当前发生事件的GPIO
pin_static = pin; // 缓存当前触发事件的按钮到内部变量中
app_timer_start(m_button_check_timer, APP_TIMER_TICKS(50), &pin_static); // 启动定时器防抖
}
}
/** @brief 按钮防抖定时器
* @param 无
* @return 无
*/
static void timer_button_event_handle(void *arg)
{
nrf_drv_gpiote_pin_t pin = *(nrf_drv_gpiote_pin_t*)arg;
// 在此处检查一下当前GPIO是否是处于按下的电平状态
if (nrf_gpio_pin_read(pin) == 1) {
// 然后给他在进行一次步进或者步退后,得到新的卡槽位置
switch(pin) {
case BUTTON_1:
NRF_LOG_INFO("BUTTON_LEFT");
m_is_read_btn_press = true;
break;
case BUTTON_2:
NRF_LOG_INFO("BUTTON_RIGHT");
m_is_write_btn_press = true;
break;
}
}
}
/**@brief Function for init button and led.
*/
static void button_init(void) {
ret_code_t err_code;
// 初始化按钮防抖的非精确的定时器
err_code = app_timer_create(&m_button_check_timer, APP_TIMER_MODE_SINGLE_SHOT, timer_button_event_handle);
APP_ERROR_CHECK(err_code);
// 配置SENSE模式,选择fales为sense配置
nrf_drv_gpiote_in_config_t in_config = NRFX_GPIOTE_CONFIG_IN_SENSE_LOTOHI(false);
in_config.pull = NRF_GPIO_PIN_PULLDOWN; // 下拉
// 配置按键绑定POTR
err_code = nrf_drv_gpiote_in_init(BUTTON_1, &in_config, button_pin_handler);
APP_ERROR_CHECK(err_code);
nrf_drv_gpiote_in_event_enable(BUTTON_1, true);
err_code = nrf_drv_gpiote_in_init(BUTTON_2, &in_config, button_pin_handler);
APP_ERROR_CHECK(err_code);
nrf_drv_gpiote_in_event_enable(BUTTON_2, true);
}
/**@brief 进入深度休眠的实现函数
*/
static void system_off_enter(void) {
// 先禁用掉HF NFC的事件
NRF_NFCT->INTENCLR = NRF_NFCT_DISABLE_ALL_INT;
// 然后再禁用掉LF LPCOMP的事件
NRF_LPCOMP->INTENCLR = LPCOMP_INTENCLR_CROSS_Msk | LPCOMP_INTENCLR_UP_Msk | LPCOMP_INTENCLR_DOWN_Msk | LPCOMP_INTENCLR_READY_Msk;
// 配置一下RAM休眠保持
ret_code_t ret;
uint32_t ram8_retention = // RAM8 每个 section 都有32KB的容量
//POWER_RAM_POWER_S0RETENTION_On << POWER_RAM_POWER_S0RETENTION_Pos ;
//POWER_RAM_POWER_S1RETENTION_On << POWER_RAM_POWER_S1RETENTION_Pos |
//POWER_RAM_POWER_S2RETENTION_On << POWER_RAM_POWER_S2RETENTION_Pos |
//POWER_RAM_POWER_S3RETENTION_On << POWER_RAM_POWER_S3RETENTION_Pos |
//POWER_RAM_POWER_S4RETENTION_On << POWER_RAM_POWER_S4RETENTION_Pos |
POWER_RAM_POWER_S5RETENTION_On << POWER_RAM_POWER_S5RETENTION_Pos ;
ret = sd_power_ram_power_set(8, ram8_retention);
APP_ERROR_CHECK(ret);
// 需要配置为浮空模拟输入且不上下拉的IO
uint32_t gpio_cfg_default_nopull[] = { HF_SPI_SELECT, HF_SPI_MISO, HF_SPI_MOSI, HF_SPI_MOSI, BAT_SENSE, LF_OA_OUT, };
for (int i = 0; i < ARRAY_SIZE(gpio_cfg_default_nopull); i++) {
nrf_gpio_cfg_default(gpio_cfg_default_nopull[i]);
}
// 需要配置为推挽输出且拉高的IO
uint32_t gpio_cfg_output_high[] = { HF_ANT_SEL, };
for (int i = 0; i < ARRAY_SIZE(gpio_cfg_output_high); i++) {
nrf_gpio_cfg_output(gpio_cfg_output_high[i]);
nrf_gpio_pin_set(gpio_cfg_output_high[i]);
}
// 需要配置为推挽输出且拉低的IO
uint32_t gpio_cfg_output_low[] = { LED_1, LED_2, LED_3, LED_4, LED_5, LED_6, LED_7, LED_8, LED_R, LED_G, LED_B, LF_MOD, READER_POWER, LF_ANT_DRIVER };
for (int i = 0; i < ARRAY_SIZE(gpio_cfg_output_low); i++) {
nrf_gpio_cfg_output(gpio_cfg_output_low[i]);
nrf_gpio_pin_clear(gpio_cfg_output_low[i]);
}
// 等一会儿再休眠,避免GPIO电路配置波动唤醒芯片
bsp_delay_ms(50);
// 然后把卡槽配置等数据进行保存
tag_emulation_save();
// 然后进行休眠
NRF_LOG_INFO("Sleep finally, Bye ^.^");
// 关闭所有的软定时器
app_timer_stop_all();
// 调用系统休眠
sleep_mode_enter();
// 本不应该进入这里,但是jlink调试模式下可以进入,顶多是无法正常休眠罢了
// jlink连接的时候,功耗会上升,并且休眠也会卡在这个步骤。
while(1) NRF_LOG_PROCESS();
}
/**
*@brief :检测唤醒源
*/
static void check_wakeup_src(void) {
// get cpu reset reason
uint32_t reset_source;
sd_power_reset_reason_get(&reset_source);
sd_power_reset_reason_clr(reset_source);
// get usb status
bool is_usb_attach = nrfx_power_usbstatus_get() != NRFX_POWER_USB_STATE_DISCONNECTED;
/*
* 注意:下方描述的休眠是深度休眠,停止任何非唤醒源的外设,停止CPU,达到最低功耗
*
* 如果唤醒源是按钮,那么需要开启BLE广播,直到按钮停止点击后一段时间后休眠
* 如果唤醒源是模拟卡的场,不需要开启BLE广播,直到模拟卡结束后休眠。
* 如果唤醒源是USB,那么就一直开启BLE,并且不进行休眠,直到USB拔掉
* 如果唤醒源是首次接入电池,则啥都不干,直接进入休眠
*
* 提示:上述;逻辑为唤醒阶段处理的逻辑,剩下的逻辑转换为运行时的处理阶段
*/
// WakeUp from button
if (reset_source & NRF_POWER_RESETREAS_OFF_MASK) { // 首次通过按钮唤醒设备
NRF_LOG_INFO("WakeUp from button");
advertising_start(); // 启动蓝牙广播
set_slot_ligth_color(0);
sleep_timer_start(SLEEP_DELAY_MS_BUTTON_WAKEUP); // 如果接下来无操作就等待超时后深度休眠
} else
// WakeUp from hf field or lf field
if (reset_source & (NRF_POWER_RESETREAS_NFC_MASK | NRF_POWER_RESETREAS_LPCOMP_MASK)) {
NRF_LOG_INFO("WakeUp from rfid field");
// 高频亮绿灯
if (reset_source & NRF_POWER_RESETREAS_NFC_MASK) {
set_slot_ligth_color(1);
}
// 低频亮蓝灯
if (reset_source & NRF_POWER_RESETREAS_LPCOMP_MASK) {
set_slot_ligth_color(2);
}
// We can only run tag emulation at field wakeup source.
sleep_timer_start(SLEEP_DELAY_MS_FIELD_WAKEUP);
} else
// WakeUp from power
if (reset_source & NRF_POWER_RESETREAS_VBUS_MASK) {
// nrfx_power_usbstatus_get() can check usb attach status
NRF_LOG_INFO("WakeUp from VBUS(USB)");
set_slot_ligth_color(0);
advertising_start(); // 启动蓝牙广播,USB插入的情况下,不需要进行深度休眠
} else
{
NRF_LOG_INFO("First power system");
// 重置一下noinit ram区域
uint32_t* noinit_addr = (uint32_t*)0x20038000;
memset(noinit_addr, 0xFF, 0x8000);
NRF_LOG_INFO("Reset noinit ram done.");
set_slot_ligth_color(0);
// 如果首次上电发现USB正插着,我们可以做一些相应的操作
if (is_usb_attach) {
NRF_LOG_INFO("USB Power found.");
// usb插着可以随便广播BLE
advertising_start();
} else {
sleep_timer_start(SLEEP_DELAY_MS_FRIST_POWER); // 等一会儿直接进入休眠,啥都不干
}
}
}
/**@brief button press event process
*/
static void button_press_process(void) {
// 确保AB按钮其中一个发生了点击事件
if (m_is_read_btn_press || m_is_write_btn_press) {
// 无论如何,发生了按钮事件,我们需先获得当前激活的卡槽
uint8_t slot_now = tag_emulation_get_slot();
uint8_t slot_new = slot_now;
// Button left press
if (m_is_read_btn_press) {
m_is_read_btn_press = false;
slot_new = find_prev_tag_emulation_slot(slot_now);
}
// Button right press
if (m_is_write_btn_press) {
m_is_write_btn_press = false;
slot_new = find_next_tag_emulation_slot(slot_now);
}
// 仅在新卡槽切换有效的情况下更新状态
if (slot_new != slot_now) {
tag_emulation_change_slot(slot_new, true); // 告诉模拟卡模块我们需要切换卡槽
light_up_by_slot(); // 切换了卡槽,我们需要重新亮灯
set_slot_ligth_color(0); // 然后重新切换灯的颜色
}
// 重新延迟进入休眠
sleep_timer_start(SLEEP_DELAY_MS_BUTTON_CLICK);
}
}
/**
* @brief Function for chameleon lite power controll
*/
int board_nrf52840_high_voltage_set(void) {
#ifdef SOFTDEVICE_PRESENT
sd_power_dcdc_mode_set(NRF_POWER_DCDC_ENABLE);
sd_power_dcdc0_mode_set(NRF_POWER_DCDC_ENABLE);
#else
NRF_POWER->DCDCEN = 1;
NRF_POWER->DCDCEN0 = 1;
#endif
// if the nrf52840_pca10059 board is powered from USB (high voltage mode), GPIO output voltage is set to 1.8 volts by
// default and that is not enough to turn the green and blue LEDs on. Increase GPIO voltage to 3.0 volts.
if (((NRF_UICR->REGOUT0 & UICR_REGOUT0_VOUT_Msk) == (UICR_REGOUT0_VOUT_DEFAULT << UICR_REGOUT0_VOUT_Pos))) {
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
NRF_UICR->REGOUT0 = (NRF_UICR->REGOUT0 & ~((uint32_t)UICR_REGOUT0_VOUT_Msk)) | (UICR_REGOUT0_VOUT_3V3 << UICR_REGOUT0_VOUT_Pos);
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy);
// a reset is required for changes to take effect
NVIC_SystemReset();
}
return 0;
}
/**@brief Application main function.
*/
int main(void)
{
log_init(); // 日志初始化
gpio_te_init(); // 初始化GPIO矩阵库
app_timers_init(); // 初始化软定时器
fds_util_init(); // 初始化fds工具封装
bsp_timer_init(); // 初始化超时定时器
bsp_timer_start(); // 启动BSP TIMER,准备用于处理业务逻辑
button_init(); // 按钮初始化
init_leds(); // LED初始化
sleep_timer_init(); // 休眠用的软定时器初始化
usb_cdc_init(); // USB cdc模拟初始化
rng_drv_and_srand_init(); // 随机数生成器初始化
power_management_init(); // 电源管理初始化
ble_slave_init(); // 蓝牙协议栈初始化
check_wakeup_src(); // 检测唤醒源,根据唤醒源决定BLE广播与后续休眠动作
tag_emulation_init(); // 模拟卡初始化
light_up_by_slot(); // 根据当前配置启用的卡槽亮起对应的灯
tag_mode_enter(); // 默认进入卡模拟模式
// cmd callback register
on_data_frame_complete(on_data_frame_received);
// Enter main loop.
NRF_LOG_INFO("NFC TAG & Reader Started!");
while(1) {
// Button event process
button_press_process();
// Data pack process
data_frame_process();
// Log print process
while(NRF_LOG_PROCESS());
// USB event process
while (app_usbd_event_queue_process());
// No task to process, system sleep enter.
sleep_system_run(
system_off_enter, // If system idle sometime, we can enter deep sleep state.
nrf_pwr_mgmt_run // Some task process done, we can enter cpu sleep state.
);
}
}
+44
View File
@@ -0,0 +1,44 @@
#ifndef STATUS_H
#define STATUS_H
/////////////////////////////////////////////////////////////////////
// 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卡奇偶校验错误
/////////////////////////////////////////////////////////////////////
// MIFARE status
/////////////////////////////////////////////////////////////////////
#define DARKSIDE_CANT_FIXED_NT (0x20) // Darkside,无法固定随机数,这个情况可能出现在UID卡上
#define DARKSIDE_LUCK_AUTH_OK (0x21) // Darkside,直接验证成功了,可能刚好密钥是空的
#define DARKSIDE_NACK_NO_SNED (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标签
/////////////////////////////////////////////////////////////////////
// other status
/////////////////////////////////////////////////////////////////////
#define STATUS_PAR_ERR (0x60) // BLE指令传递的参数错误,或者是调用某些函数传递的参数错误
#define STATUS_DEVIEC_MODE_ERROR (0x66) // 当前设备所处的模式错误,无法调用对应的API
#define STATUS_INVALID_CMD (0x67) // 无效的指令
#define STATUS_DEVICE_SUCCESS (0x68) // 设备相关操作成功执行
#define STATUS_NOT_IMPLEMENTED (0x69) // 调用了某些未实现的操作,属于开发者遗漏的错误
#endif
+410
View File
@@ -0,0 +1,410 @@
#include "ble_hci.h"
#include "ble_nus.h"
#include "ble_advdata.h"
#include "ble_advertising.h"
#include "ble_conn_params.h"
#include "nrf.h"
#include "nordic_common.h"
#include "nrf_sdh.h"
#include "nrf_ble_qwr.h"
#include "nrf_sdh_soc.h"
#include "nrf_sdh_ble.h"
#include "nrf_ble_gatt.h"
#include "app_timer.h"
#include "app_util_platform.h"
#include "syssleep.h"
#include "ble_main.h"
#define NRF_LOG_MODULE_NAME ble_main
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
NRF_LOG_MODULE_REGISTER();
#define APP_BLE_CONN_CFG_TAG 1 /**< A tag identifying the SoftDevice BLE configuration. */
#define DEVICE_NAME "Nordic_UART" /**< Name of device. Will be included in the advertising data. */
#define NUS_SERVICE_UUID_TYPE BLE_UUID_TYPE_VENDOR_BEGIN /**< UUID type for the Nordic UART Service (vendor specific). */
#define APP_BLE_OBSERVER_PRIO 3 /**< Application's BLE observer priority. You shouldn't need to modify this value. */
#define APP_ADV_INTERVAL 64 /**< The advertising interval (in units of 0.625 ms. This value corresponds to 40 ms). */
#define MIN_CONN_INTERVAL MSEC_TO_UNITS(20, UNIT_1_25_MS) /**< Minimum acceptable connection interval (20 ms), Connection interval uses 1.25 ms units. */
#define MAX_CONN_INTERVAL MSEC_TO_UNITS(75, UNIT_1_25_MS) /**< Maximum acceptable connection interval (75 ms), Connection interval uses 1.25 ms units. */
#define SLAVE_LATENCY 0 /**< Slave latency. */
#define CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) /**< Connection supervisory timeout (4 seconds), Supervision Timeout uses 10 ms units. */
#define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(5000) /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */
#define NEXT_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(30000) /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */
#define MAX_CONN_PARAMS_UPDATE_COUNT 3 /**< Number of attempts before giving up the connection parameter negotiation. */
BLE_NUS_DEF(m_nus, NRF_SDH_BLE_TOTAL_LINK_COUNT); /**< BLE NUS service instance. */
NRF_BLE_GATT_DEF(m_gatt); /**< GATT module instance. */
NRF_BLE_QWR_DEF(m_qwr); /**< Context for the Queued Write module.*/
BLE_ADVERTISING_DEF(m_advertising); /**< Advertising module instance. */
static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID; /**< Handle of the current connection. */
static uint16_t m_ble_nus_max_data_len = BLE_GATT_ATT_MTU_DEFAULT - 3; /**< Maximum length of data (in bytes) that can be transmitted to the peer by the Nordic UART service module. */
static ble_uuid_t m_adv_uuids[] = /**< Universally unique service identifier. */
{
{BLE_UUID_NUS_SERVICE, NUS_SERVICE_UUID_TYPE}
};
bool g_is_ble_connected = false;
/**@brief Function for the GAP initialization.
*
* @details This function will set up all the necessary GAP (Generic Access Profile) parameters of
* the device. It also sets the permissions and appearance.
*/
static void gap_params_init(void)
{
uint32_t err_code;
ble_gap_conn_params_t gap_conn_params;
ble_gap_conn_sec_mode_t sec_mode;
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
err_code = sd_ble_gap_device_name_set(&sec_mode,
(const uint8_t *) DEVICE_NAME,
strlen(DEVICE_NAME));
APP_ERROR_CHECK(err_code);
memset(&gap_conn_params, 0, sizeof(gap_conn_params));
gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL;
gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL;
gap_conn_params.slave_latency = SLAVE_LATENCY;
gap_conn_params.conn_sup_timeout = CONN_SUP_TIMEOUT;
err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
APP_ERROR_CHECK(err_code);
}
/**@brief Function for handling the data from the Nordic UART Service.
*
* @details This function will process the data received from the Nordic UART BLE Service and send
* it to the UART module.
*
* @param[in] p_evt Nordic UART Service event.
*/
/**@snippet [Handling the data received over BLE] */
static void nus_data_handler(ble_nus_evt_t * p_evt)
{
if (p_evt->type == BLE_NUS_EVT_RX_DATA)
{
uint32_t err_code;
NRF_LOG_DEBUG("Received data from BLE NUS. Writing data on UART.");
NRF_LOG_HEXDUMP_DEBUG(p_evt->params.rx_data.p_data, p_evt->params.rx_data.length);
for (uint32_t i = 0; i < p_evt->params.rx_data.length; i++)
{
do
{
// err_code = app_uart_put(p_evt->params.rx_data.p_data[i]);
if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_BUSY))
{
NRF_LOG_ERROR("Failed receiving NUS message. Error 0x%x. ", err_code);
APP_ERROR_CHECK(err_code);
}
} while (err_code == NRF_ERROR_BUSY);
}
if (p_evt->params.rx_data.p_data[p_evt->params.rx_data.length - 1] == '\r')
{
// while (app_uart_put('\n') == NRF_ERROR_BUSY);
}
}
}
/**@snippet [Handling the data received over BLE] */
/**@brief Function for handling Queued Write Module errors.
*
* @details A pointer to this function will be passed to each service which may need to inform the
* application about an error.
*
* @param[in] nrf_error Error code containing information about what went wrong.
*/
static void nrf_qwr_error_handler(uint32_t nrf_error)
{
APP_ERROR_HANDLER(nrf_error);
}
/**@brief Function for initializing services that will be used by the application.
*/
static void services_init(void)
{
uint32_t err_code;
ble_nus_init_t nus_init;
nrf_ble_qwr_init_t qwr_init = {0};
// Initialize Queued Write Module.
qwr_init.error_handler = nrf_qwr_error_handler;
err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init);
APP_ERROR_CHECK(err_code);
// Initialize NUS.
memset(&nus_init, 0, sizeof(nus_init));
nus_init.data_handler = nus_data_handler;
err_code = ble_nus_init(&m_nus, &nus_init);
APP_ERROR_CHECK(err_code);
}
/**@brief Function for handling an event from the Connection Parameters Module.
*
* @details This function will be called for all events in the Connection Parameters Module
* which are passed to the application.
*
* @note All this function does is to disconnect. This could have been done by simply setting
* the disconnect_on_fail config parameter, but instead we use the event handler
* mechanism to demonstrate its use.
*
* @param[in] p_evt Event received from the Connection Parameters Module.
*/
static void on_conn_params_evt(ble_conn_params_evt_t * p_evt)
{
uint32_t err_code;
if (p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED)
{
err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE);
APP_ERROR_CHECK(err_code);
}
}
/**@brief Function for handling errors from the Connection Parameters module.
*
* @param[in] nrf_error Error code containing information about what went wrong.
*/
static void conn_params_error_handler(uint32_t nrf_error)
{
APP_ERROR_HANDLER(nrf_error);
}
/**@brief Function for initializing the Connection Parameters module.
*/
static void conn_params_init(void)
{
uint32_t err_code;
ble_conn_params_init_t cp_init;
memset(&cp_init, 0, sizeof(cp_init));
cp_init.p_conn_params = NULL;
cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY;
cp_init.next_conn_params_update_delay = NEXT_CONN_PARAMS_UPDATE_DELAY;
cp_init.max_conn_params_update_count = MAX_CONN_PARAMS_UPDATE_COUNT;
cp_init.start_on_notify_cccd_handle = BLE_GATT_HANDLE_INVALID;
cp_init.disconnect_on_fail = false;
cp_init.evt_handler = on_conn_params_evt;
cp_init.error_handler = conn_params_error_handler;
err_code = ble_conn_params_init(&cp_init);
APP_ERROR_CHECK(err_code);
}
/**@brief Function for handling advertising events.
*
* @details This function will be called for advertising events which are passed to the application.
*
* @param[in] ble_adv_evt Advertising event.
*/
static void on_adv_evt(ble_adv_evt_t ble_adv_evt)
{
switch (ble_adv_evt)
{
case BLE_ADV_EVT_FAST:
NRF_LOG_INFO("BLE_ADV_EVT_FAST");
break;
case BLE_ADV_EVT_IDLE:
NRF_LOG_INFO("BLE_ADV_EVT_IDLE");
break;
default:
break;
}
}
/**@brief Function for handling BLE events.
*
* @param[in] p_ble_evt Bluetooth stack event.
* @param[in] p_context Unused.
*/
static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
{
ret_code_t err_code;
switch (p_ble_evt->header.evt_id)
{
case BLE_GAP_EVT_CONNECTED:
sleep_timer_stop();
NRF_LOG_INFO("Connected");
APP_ERROR_CHECK(err_code);
m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
APP_ERROR_CHECK(err_code);
g_is_ble_connected = true;
break;
case BLE_GAP_EVT_DISCONNECTED:
sleep_timer_start(SLEEP_DELAY_MS_BLE_DISCONNECTED);
NRF_LOG_INFO("Disconnected");
// LED indication will be changed when advertising starts.
m_conn_handle = BLE_CONN_HANDLE_INVALID;
g_is_ble_connected = false;
break;
case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
{
NRF_LOG_DEBUG("PHY update request.");
ble_gap_phys_t const phys =
{
.rx_phys = BLE_GAP_PHY_AUTO,
.tx_phys = BLE_GAP_PHY_AUTO,
};
err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
APP_ERROR_CHECK(err_code);
} break;
case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
// Pairing not supported
err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);
APP_ERROR_CHECK(err_code);
break;
case BLE_GATTS_EVT_SYS_ATTR_MISSING:
// No system attributes have been stored.
err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0);
APP_ERROR_CHECK(err_code);
break;
case BLE_GATTC_EVT_TIMEOUT:
// Disconnect on GATT Client timeout event.
err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
APP_ERROR_CHECK(err_code);
break;
case BLE_GATTS_EVT_TIMEOUT:
// Disconnect on GATT Server timeout event.
err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
APP_ERROR_CHECK(err_code);
break;
default:
// No implementation needed.
break;
}
}
/**@brief Function for the SoftDevice initialization.
*
* @details This function initializes the SoftDevice and the BLE event interrupt.
*/
static void ble_stack_init(void)
{
ret_code_t err_code;
err_code = nrf_sdh_enable_request();
APP_ERROR_CHECK(err_code);
// Configure the BLE stack using the default settings.
// Fetch the start address of the application RAM.
uint32_t ram_start = 0;
err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
APP_ERROR_CHECK(err_code);
// Enable BLE stack.
err_code = nrf_sdh_ble_enable(&ram_start);
APP_ERROR_CHECK(err_code);
// Register a handler for BLE events.
NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
}
/**@brief Function for handling events from the GATT library. */
void gatt_evt_handler(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_t const * p_evt)
{
if ((m_conn_handle == p_evt->conn_handle) && (p_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED))
{
m_ble_nus_max_data_len = p_evt->params.att_mtu_effective - OPCODE_LENGTH - HANDLE_LENGTH;
NRF_LOG_INFO("Data len is set to 0x%X(%d)", m_ble_nus_max_data_len, m_ble_nus_max_data_len);
}
NRF_LOG_DEBUG("ATT MTU exchange completed. central 0x%x peripheral 0x%x",
p_gatt->att_mtu_desired_central,
p_gatt->att_mtu_desired_periph);
}
/**@brief Function for initializing the GATT library. */
void gatt_init(void)
{
ret_code_t err_code;
err_code = nrf_ble_gatt_init(&m_gatt, gatt_evt_handler);
APP_ERROR_CHECK(err_code);
err_code = nrf_ble_gatt_att_mtu_periph_set(&m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE);
APP_ERROR_CHECK(err_code);
}
/**@brief Function for initializing the Advertising functionality.
*/
static void advertising_init(void)
{
uint32_t err_code;
ble_advertising_init_t init;
memset(&init, 0, sizeof(init));
init.advdata.name_type = BLE_ADVDATA_FULL_NAME;
init.advdata.include_appearance = false;
init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
init.srdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
init.srdata.uuids_complete.p_uuids = m_adv_uuids;
init.config.ble_adv_fast_enabled = true;
init.config.ble_adv_fast_interval = APP_ADV_INTERVAL;
init.config.ble_adv_fast_timeout = 0;
init.evt_handler = on_adv_evt;
err_code = ble_advertising_init(&m_advertising, &init);
APP_ERROR_CHECK(err_code);
ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
}
/**
* @brief Function for starting advertising.
*/
void advertising_start(void)
{
uint32_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
APP_ERROR_CHECK(err_code);
}
/**
* @brief Function for init ble slave.
*/
void ble_slave_init(void) {
ble_stack_init(); // BLE协议栈初始化
gap_params_init(); // GAP参数初始化
gatt_init(); // GATT协议初始化
services_init(); // 服务特征初始化
advertising_init(); // 广播参数初始化
conn_params_init(); // 连接参数初始化
}
+7
View File
@@ -0,0 +1,7 @@
#ifndef BLE_MAIN_H
#define BLE_MAIN_H
void ble_slave_init(void);
void advertising_start(void);
#endif
+23
View File
@@ -0,0 +1,23 @@
#include "bsp_delay.h"
#include "bsp_time.h"
#include "nrf_delay.h"
//初始化延迟函数
void bsp_delay_init(void)
{
}
//延时nms
//注意nms的范围
void bsp_delay_ms(uint16_t nms)
{
nrf_delay_us(nms * 1000);
}
//延时nus
//nus为要延时的us数.
void bsp_delay_us(uint32_t nus)
{
nrf_delay_us(nus);
}
+18
View File
@@ -0,0 +1,18 @@
#ifndef __DELAY_H__
#define __DELAY_H__
#include "stdint.h"
#ifdef __cplusplus
extern "C" {
#endif
void bsp_delay_init(void);
void bsp_delay_ms(uint16_t nms);
void bsp_delay_us(uint32_t nus);
#ifdef __cplusplus
}
#endif
#endif
+109
View File
@@ -0,0 +1,109 @@
#include "bsp_time.h"
#include "app_timer.h"
#define TICK_PERIOD APP_TIMER_TICKS(10) // 定时时间
// 定义一个软定时器
APP_TIMER_DEF(m_app_timer);
// 定时器池
autotimer bsptimers[TIMER_BSP_COUNT] = { 0 };
// 定时器迭代位置
static uint8_t g_timer_fori;
// 当前定时器运行状态
static volatile enum {
UNINIT,
INIT,
START,
STOP,
} bsp_timer_state = UNINIT;
/*
* 获取一个空闲的定时器,这个定时器
* 1、会自动跑滴答
* 2、是空闲的
*/
autotimer* bsp_obtain_timer(uint32_t start_value) {
uint8_t i;
for (i = 0; i < TIMER_BSP_COUNT; i++) {
if (bsptimers[i].busy == 0) {
bsptimers[i].time = start_value;
bsptimers[i].busy = 1;
break;
}
}
return &bsptimers[i];
}
/*
* 设置定时器,该操作会操作目标定时器,修改当前值
*/
inline uint8_t bsp_set_timer(autotimer* timer,uint32_t start_value) {
if(timer->busy == 0) return 0;
timer->time = start_value;
return 1;
}
/*
* 归还定时器,该操作会自动释放定时器
* 并且对定时器归零
*/
inline void bsp_return_timer(autotimer* timer) {
timer->busy = 0;
timer->time = 0;
}
/** @brief 测试定时器的回调函数
* @param arg 回调参数
* @return 无
*/
void timer_app_callback(void *arg)
{
UNUSED_PARAMETER(arg);
for (g_timer_fori = 0; g_timer_fori < TIMER_BSP_COUNT; g_timer_fori++) {
if (bsptimers[g_timer_fori].busy == 1) {
bsptimers[g_timer_fori].time += 10;
}
}
}
// 初始化定时器
void bsp_timer_init(void) {
if (bsp_timer_state == UNINIT) {
bsp_timer_state = INIT;
// 创建定时器
ret_code_t err_code = app_timer_create(&m_app_timer, APP_TIMER_MODE_REPEATED, timer_app_callback);
APP_ERROR_CHECK(err_code);
}
}
// 反初始化定时器
void bsp_timer_uninit(void) {
// 暂时无法反初始化软定时器,只能关闭
bsp_timer_stop();
}
// 启动定时器
void bsp_timer_start(void) {
if (bsp_timer_state != UNINIT) {
// 确保定时器没有被启动过
if (bsp_timer_state != START) {
app_timer_start(m_app_timer, TICK_PERIOD, NULL);
bsp_timer_state = START;
}
}
}
// 停止定时器
void bsp_timer_stop(void) {
if (bsp_timer_state != UNINIT) {
if (bsp_timer_state == START) {
// 停止定时器
app_timer_stop(m_app_timer);
bsp_timer_state = STOP;
}
}
}
+35
View File
@@ -0,0 +1,35 @@
#ifndef _DrvTime2_h_
#define _DrvTime2_h_
#include <stdint.h>
#ifndef NULL
#define NULL ((void *)0)
#endif
//定义可以同时使用的计时器的最多数量
#define TIMER_BSP_COUNT 10
// 定义一个结构体
// 这个结构体存放了基本的时钟信息
typedef struct {
// 当前定时器的滴答数
volatile uint32_t time;
// 是否繁忙
uint8_t busy;
} autotimer;
// 实现一个判断超时的宏定义
#define NO_TIMEOUT_1MS(timer, count) ((((autotimer*)timer)->time <= (count))? 1: 0)
void bsp_timer_init(void);
void bsp_timer_uninit(void);
void bsp_timer_start(void);
void bsp_timer_stop(void);
void bsp_return_timer(autotimer* timer);
autotimer* bsp_obtain_timer(uint32_t start_value);
uint8_t bsp_set_timer(autotimer* timer,uint32_t start_value);
#endif
+44
View File
@@ -0,0 +1,44 @@
#ifndef DATA_CMD_H
#define DATA_CMD_H
// ******************************************************************
// CMD for device
// Range from 1000 -> 1999
#define DATA_CMD_GET_APP_VERSION (1000)
#define DATA_CMD_CHANGE_DEVICE_MODE (1001)
#define DATA_CMD_GET_DEVICE_MODE (1002)
#define DATA_CMD_SET_SLOT_ACTIVATED (1003)
#define DATA_CMD_SET_SLOT_TAG_TYPE (1004)
#define DATA_CMD_SET_SLOT_DATA_DEFAULT (1005)
//
// ******************************************************************
// ******************************************************************
// CMD for hf reader
// Range from 2000 -> 2999
// #define DATA_CMD_XXXX (xxxx)
//
// ******************************************************************
#define DATA_CMD_SCAN_14A_TAG (2000)
#define DATA_CMD_MF1_SUPPORT_DETECT (2001)
#define DATA_CMD_MF1_NT_LEVEL_DETECT (2002)
#define DATA_CMD_MF1_DARKSIDE_DETECT (2003)
#define DATA_CMD_MF1_DARKSIDE_ACQUIRE (2004)
#define DATA_CMD_MF1_NT_DIST_DETECT (2005)
#define DATA_CMD_MF1_NESTED_ACQUIRE (2006)
#define DATA_CMD_MF1_CHECK_ONE_KEY_BLOCK (2007)
#define DATA_CMD_MF1_READ_ONE_BLOCK (2008)
#define DATA_CMD_MF1_WRITE_ONE_BLOCK (2009)
// ******************************************************************
// CMD for lf reader
// Range from 3000 -> 3999
// #define DATA_CMD_XXXX (xxxx)
//
// ******************************************************************
#define DATA_CMD_SCAN_EM410X_TAG (3000)
#define DATA_CMD_WRITE_EM410X_TO_T5577 (3001)
#endif
+54
View File
@@ -0,0 +1,54 @@
#include "crc_utils.h"
// 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,
};
/**
* @brief 在MCU上使用查表法计算14443a协议专用的CRCcrc16
* @param data 将被计算的CRC的原始数据
* @param length 数据的长度,不包括CRC
* @param output 输出缓冲区,长度必须是大于等于两个字节
*
*/
void calc_14a_crc_lut(uint8_t* data, int length, uint8_t* output) {
// 取巧,强制指针类型转换
uint16_t *crc = (uint16_t *)output;
// 赋予多项式初始值
*crc = 0x6363;
// 然后开始对每个字节进行查表
while (length--) *crc = (*crc >> 8) ^ crc_table[(*crc & 0xFF) ^ *data++];
}
@@ -0,0 +1,8 @@
#ifndef __CRC_UTILS_H
#define __CRC_UTILS_H
#include <stdint.h>
void calc_14a_crc_lut(uint8_t* data, int length, uint8_t* output);
#endif
+36
View File
@@ -0,0 +1,36 @@
#include "hex_utils.h"
/**
* @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;
}
}
/**
* @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;
}
+10
View File
@@ -0,0 +1,10 @@
#ifndef __HEX_UTILS_H
#define __HEX_UTILS_H
#include <stdint.h>
// num & bytes
void num_to_bytes(uint64_t n, uint8_t len, uint8_t* dest);
uint64_t bytes_to_num(uint8_t* src, uint8_t len);
#endif
+154
View File
@@ -0,0 +1,154 @@
/* crypto1.c
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, US
Copyright (C) 2008-2008 bla <blapost@gmail.com>
*/
#include <stdlib.h>
#include "mf1_crapto1.h"
#include "parity.h"
#ifdef __OPTIMIZE_SIZE__
uint32_t filter(uint32_t const x) {
uint32_t f;
f = 0xf22c0 >> (x & 0xf) & 16;
f |= 0x6c9c0 >> (x >> 4 & 0xf) & 8;
f |= 0x3c8b0 >> (x >> 8 & 0xf) & 4;
f |= 0x1e458 >> (x >> 12 & 0xf) & 2;
f |= 0x0d938 >> (x >> 16 & 0xf) & 1;
return BIT(0xEC57E80A, f);
}
#endif
#define SWAPENDIAN(x)\
(x = (x >> 8 & 0xff00ff) | (x & 0xff00ff) << 8, x = x >> 16 | x << 16)
void crypto1_init(struct Crypto1State *state, uint64_t key) {
if (state == NULL)
return;
state->odd = 0;
state->even = 0;
for (int i = 47; i > 0; i -= 2) {
state->odd = state->odd << 1 | BIT(key, (i - 1) ^ 7);
state->even = state->even << 1 | BIT(key, i ^ 7);
}
}
void inline crypto1_deinit(struct Crypto1State *state) {
state->odd = 0;
state->even = 0;
}
#if defined(__arm__) || defined(__linux__) || defined(_WIN32) || defined(__APPLE__) // bare metal ARM Proxmark lacks calloc()/free()
struct Crypto1State *crypto1_create(uint64_t key) {
struct Crypto1State *state = calloc(sizeof(*state), sizeof(uint8_t));
if (!state) return NULL;
crypto1_init(state, key);
return state;
}
void crypto1_destroy(struct Crypto1State *state) {
free(state);
}
#endif
void crypto1_get_lfsr(struct Crypto1State *state, uint64_t *lfsr) {
int i;
for (*lfsr = 0, i = 23; i >= 0; --i) {
*lfsr = *lfsr << 1 | BIT(state->odd, i ^ 3);
*lfsr = *lfsr << 1 | BIT(state->even, i ^ 3);
}
}
uint8_t crypto1_bit(struct Crypto1State *s, uint8_t in, int is_encrypted) {
uint32_t feedin, t;
uint8_t ret = filter(s->odd);
feedin = ret & (!!is_encrypted);
feedin ^= !!in;
feedin ^= LF_POLY_ODD & s->odd;
feedin ^= LF_POLY_EVEN & s->even;
s->even = s->even << 1 | (evenparity32(feedin));
t = s->odd;
s->odd = s->even;
s->even = t;
return ret;
}
uint8_t crypto1_byte(struct Crypto1State *s, uint8_t in, int is_encrypted) {
uint8_t ret = 0;
ret |= crypto1_bit(s, BIT(in, 0), is_encrypted) << 0;
ret |= crypto1_bit(s, BIT(in, 1), is_encrypted) << 1;
ret |= crypto1_bit(s, BIT(in, 2), is_encrypted) << 2;
ret |= crypto1_bit(s, BIT(in, 3), is_encrypted) << 3;
ret |= crypto1_bit(s, BIT(in, 4), is_encrypted) << 4;
ret |= crypto1_bit(s, BIT(in, 5), is_encrypted) << 5;
ret |= crypto1_bit(s, BIT(in, 6), is_encrypted) << 6;
ret |= crypto1_bit(s, BIT(in, 7), is_encrypted) << 7;
return ret;
}
uint32_t crypto1_word(struct Crypto1State *s, uint32_t in, int is_encrypted) {
uint32_t ret = 0;
// note: xor args have been swapped because some compilers emit a warning
// for 10^x and 2^x as possible misuses for exponentiation. No comment.
ret |= crypto1_bit(s, BEBIT(in, 0), is_encrypted) << (24 ^ 0);
ret |= crypto1_bit(s, BEBIT(in, 1), is_encrypted) << (24 ^ 1);
ret |= crypto1_bit(s, BEBIT(in, 2), is_encrypted) << (24 ^ 2);
ret |= crypto1_bit(s, BEBIT(in, 3), is_encrypted) << (24 ^ 3);
ret |= crypto1_bit(s, BEBIT(in, 4), is_encrypted) << (24 ^ 4);
ret |= crypto1_bit(s, BEBIT(in, 5), is_encrypted) << (24 ^ 5);
ret |= crypto1_bit(s, BEBIT(in, 6), is_encrypted) << (24 ^ 6);
ret |= crypto1_bit(s, BEBIT(in, 7), is_encrypted) << (24 ^ 7);
ret |= crypto1_bit(s, BEBIT(in, 8), is_encrypted) << (24 ^ 8);
ret |= crypto1_bit(s, BEBIT(in, 9), is_encrypted) << (24 ^ 9);
ret |= crypto1_bit(s, BEBIT(in, 10), is_encrypted) << (24 ^ 10);
ret |= crypto1_bit(s, BEBIT(in, 11), is_encrypted) << (24 ^ 11);
ret |= crypto1_bit(s, BEBIT(in, 12), is_encrypted) << (24 ^ 12);
ret |= crypto1_bit(s, BEBIT(in, 13), is_encrypted) << (24 ^ 13);
ret |= crypto1_bit(s, BEBIT(in, 14), is_encrypted) << (24 ^ 14);
ret |= crypto1_bit(s, BEBIT(in, 15), is_encrypted) << (24 ^ 15);
ret |= crypto1_bit(s, BEBIT(in, 16), is_encrypted) << (24 ^ 16);
ret |= crypto1_bit(s, BEBIT(in, 17), is_encrypted) << (24 ^ 17);
ret |= crypto1_bit(s, BEBIT(in, 18), is_encrypted) << (24 ^ 18);
ret |= crypto1_bit(s, BEBIT(in, 19), is_encrypted) << (24 ^ 19);
ret |= crypto1_bit(s, BEBIT(in, 20), is_encrypted) << (24 ^ 20);
ret |= crypto1_bit(s, BEBIT(in, 21), is_encrypted) << (24 ^ 21);
ret |= crypto1_bit(s, BEBIT(in, 22), is_encrypted) << (24 ^ 22);
ret |= crypto1_bit(s, BEBIT(in, 23), is_encrypted) << (24 ^ 23);
ret |= crypto1_bit(s, BEBIT(in, 24), is_encrypted) << (24 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 25), is_encrypted) << (24 ^ 25);
ret |= crypto1_bit(s, BEBIT(in, 26), is_encrypted) << (24 ^ 26);
ret |= crypto1_bit(s, BEBIT(in, 27), is_encrypted) << (24 ^ 27);
ret |= crypto1_bit(s, BEBIT(in, 28), is_encrypted) << (24 ^ 28);
ret |= crypto1_bit(s, BEBIT(in, 29), is_encrypted) << (24 ^ 29);
ret |= crypto1_bit(s, BEBIT(in, 30), is_encrypted) << (24 ^ 30);
ret |= crypto1_bit(s, BEBIT(in, 31), is_encrypted) << (24 ^ 31);
return ret;
}
/* prng_successor
* helper used to obscure the keystream during authentication
*/
uint32_t prng_successor(uint32_t x, uint32_t n) {
// SWAPENDIAN(x);
x = __rev(x);
while (n--)
x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21) << 31;
// return SWAPENDIAN(x);
return __rev(x);
}
@@ -0,0 +1,69 @@
/* crapto1.h
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, US$
Copyright (C) 2008-2014 bla <blapost@gmail.com>
*/
#ifndef CRAPTO1_INCLUDED
#define CRAPTO1_INCLUDED
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
struct Crypto1State {uint32_t odd, even;};
void crypto1_init(struct Crypto1State *state, uint64_t key);
void crypto1_deinit(struct Crypto1State *);
#if defined(__arm__) || defined(__linux__) || defined(_WIN32) || defined(__APPLE__) // bare metal ARM Proxmark lacks malloc()/free()
struct Crypto1State *crypto1_create(uint64_t key);
void crypto1_destroy(struct Crypto1State *);
#endif
void crypto1_get_lfsr(struct Crypto1State *, uint64_t *);
uint8_t crypto1_bit(struct Crypto1State *, uint8_t, int);
uint8_t crypto1_byte(struct Crypto1State *, uint8_t, int);
uint32_t crypto1_word(struct Crypto1State *, uint32_t, int);
uint32_t prng_successor(uint32_t x, uint32_t n);
uint8_t lfsr_rollback_bit(struct Crypto1State *s, uint32_t in, int fb);
uint8_t lfsr_rollback_byte(struct Crypto1State *s, uint32_t in, int fb);
uint32_t lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb);
#define FOREACH_VALID_NONCE(N, FILTER, FSIZE)\
uint32_t __n = 0,__M = 0, N = 0;\
int __i;\
for(; __n < 1 << 16; N = prng_successor(__M = ++__n, 16))\
for(__i = FSIZE - 1; __i >= 0; __i--)\
if(BIT(FILTER, __i) ^ evenparity32(__M & 0xFF01))\
break;\
else if(__i)\
__M = prng_successor(__M, (__i == 7) ? 48 : 8);\
else
#define LF_POLY_ODD (0x29CE5C)
#define LF_POLY_EVEN (0x870804)
#define BIT(x, n) ((x) >> (n) & 1)
#define BEBIT(x, n) BIT(x, (n) ^ 24)
#ifdef __OPTIMIZE_SIZE__
int filter(uint32_t const x);
#else
static inline int filter(uint32_t const x) {
uint32_t f;
f = 0xf22c0 >> (x & 0xf) & 16;
f |= 0x6c9c0 >> (x >> 4 & 0xf) & 8;
f |= 0x3c8b0 >> (x >> 8 & 0xf) & 4;
f |= 0x1e458 >> (x >> 12 & 0xf) & 2;
f |= 0x0d938 >> (x >> 16 & 0xf) & 1;
return BIT(0xEC57E80A, f);
}
#endif
#endif
@@ -0,0 +1,45 @@
#include "crypto1_helper.h"
// crypto1 helpers
void mf_crypto1_decryptEx(struct Crypto1State *pcs, uint8_t *data_in, int len, uint8_t *data_out) {
if (len != 1) {
for (int i = 0; i < len; i++)
data_out[i] = crypto1_byte(pcs, 0x00, 0) ^ data_in[i];
} else {
uint8_t bt = 0;
bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data_in[0], 0)) << 0;
bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data_in[0], 1)) << 1;
bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data_in[0], 2)) << 2;
bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data_in[0], 3)) << 3;
data_out[0] = bt;
}
return;
}
void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len) {
mf_crypto1_decryptEx(pcs, data, len, data);
}
void mf_crypto1_encryptEx(struct Crypto1State *pcs, uint8_t *data_in, uint8_t *keystream, uint8_t *data_out, uint16_t len, uint8_t *par) {
int i;
for (i = 0; i < len; i++) {
uint8_t bt = data_in[i];
// 加密字节流
data_out[i] = crypto1_byte(pcs, keystream ? keystream[i] : 0x00, 0) ^ data_in[i];
// 生成奇偶校验位
par[i] = filter(pcs->odd) ^ oddparity8(bt);
}
}
void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par) {
mf_crypto1_encryptEx(pcs, data, NULL, data, len, par);
}
uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data) {
uint8_t bt = 0;
bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data, 0)) << 0;
bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data, 1)) << 1;
bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data, 2)) << 2;
bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data, 3)) << 3;
return bt;
}
@@ -0,0 +1,13 @@
#ifndef CRYPTO1_HELPER_H
#define CRYPTO1_HELPER_H
#include "mf1_crapto1.h"
#include "parity.h"
void mf_crypto1_decryptEx(struct Crypto1State *pcs, uint8_t *data_in, int len, uint8_t *data_out);
inline void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len);
void mf_crypto1_encryptEx(struct Crypto1State *pcs, uint8_t *data_in, uint8_t *keystream, uint8_t *data_out, uint16_t len, uint8_t *par);
inline void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par);
uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data);
#endif

Some files were not shown because too many files have changed in this diff Show More