Implement LF RFID emulation (#208)

* migrate code from old repo, not work
* fix emulation
* disable irq handling while RFID emulating
* add testcase
This commit is contained in:
coreglitch 2020-10-28 14:38:04 +06:00 committed by GitHub
parent 665f6d7d9c
commit de968b13b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 130 additions and 3 deletions

View File

@ -4,7 +4,7 @@
#include <flipper_v2.h>
#ifdef APP_NFC
void st25r3916Isr(void);
void nfc_isr(void);
#endif
static volatile bool initialized = false;
@ -104,7 +104,7 @@ void input_task(void* p) {
void HAL_GPIO_EXTI_Callback(uint16_t pin) {
#ifdef APP_NFC
if(pin == RFID_PULL_Pin) {
st25r3916Isr();
nfc_isr();
return;
}
#endif

View File

@ -0,0 +1,68 @@
#include "flipper_v2.h"
void prepare_data(uint32_t ID, uint32_t VENDOR, uint8_t* data) {
uint8_t value[10];
// vendor rows (4 bit in a row)
value[0] = (VENDOR >> 4) & 0xF;
value[1] = VENDOR & 0xF;
const uint8_t ROW_SIZE = 4;
const uint8_t HEADER_SIZE = 9;
// ID rows (4 bit in a row)
for(int i = 0; i < 8; i++) {
value[i + 2] = (ID >> (28 - i * ROW_SIZE)) & 0xF;
}
for(uint8_t i = 0; i < HEADER_SIZE; i++) {
data[i] = 1; // header
}
for(uint8_t i = 0; i < 10; i++) { // data
for(uint8_t j = 0; j < ROW_SIZE; j++) {
data[HEADER_SIZE + i * (ROW_SIZE + 1) + j] = (value[i] >> ((ROW_SIZE - 1) - j)) & 1;
}
// row parity
data[HEADER_SIZE + i * (ROW_SIZE + 1) + ROW_SIZE] =
(data[HEADER_SIZE + i * (ROW_SIZE + 1) + 0] +
data[HEADER_SIZE + i * (ROW_SIZE + 1) + 1] +
data[HEADER_SIZE + i * (ROW_SIZE + 1) + 2] +
data[HEADER_SIZE + i * (ROW_SIZE + 1) + 3]) %
2;
}
for(uint8_t i = 0; i < ROW_SIZE; i++) { //checksum
uint8_t checksum = 0;
for(uint8_t j = 0; j < 10; j++) {
checksum += data[HEADER_SIZE + i + j * (ROW_SIZE + 1)];
}
data[i + 59] = checksum % 2;
}
data[63] = 0; // stop bit
printf("em data: ");
for(uint8_t i = 0; i < 64; i++) {
printf("%d ", data[i]);
}
printf("\n");
}
void em4100_emulation(uint8_t* data, GpioPin* pin) {
taskENTER_CRITICAL();
gpio_write(pin, true);
for(uint8_t i = 0; i < 8; i++) {
for(uint8_t j = 0; j < 64; j++) {
delay_us(270);
gpio_write(pin, data[j]);
delay_us(270);
gpio_write(pin, !data[j]);
}
}
gpio_write(pin, false);
taskEXIT_CRITICAL();
}

View File

@ -44,10 +44,22 @@ static void input_callback(InputEvent* input_event, void* ctx) {
}
extern TIM_HandleTypeDef htim15;
void em4100_emulation(uint8_t* data, GpioPin* pin);
void prepare_data(uint32_t ID, uint32_t VENDOR, uint8_t* data);
void lf_rfid_workaround(void* p) {
osMessageQueueId_t event_queue = osMessageQueueNew(1, sizeof(AppEvent), NULL);
// create pin
GpioPin pull_pin = {.pin = GPIO_PIN_15, .port = GPIOB};
// TODO open record
GpioPin* pull_pin_record = &pull_pin;
gpio_init(pull_pin_record, GpioModeOutputPushPull);
uint8_t emulation_data[64];
prepare_data(4378151, 01, emulation_data);
State _state;
_state.freq_khz = 125;
_state.on = false;
@ -73,7 +85,7 @@ void lf_rfid_workaround(void* p) {
AppEvent event;
while(1) {
osStatus_t event_status = osMessageQueueGet(event_queue, &event, NULL, 10000);
osStatus_t event_status = osMessageQueueGet(event_queue, &event, NULL, 100);
State* state = (State*)acquire_mutex_block(&state_mutex);
if(event_status == osOK) {
@ -81,6 +93,7 @@ void lf_rfid_workaround(void* p) {
// press events
if(event.value.input.state && event.value.input.input == InputBack) {
hal_pwmn_stop(&htim15, TIM_CHANNEL_1); // TODO: move to furiac_onexit
gpio_init(pull_pin_record, GpioModeInput);
// TODO remove all widgets create by app
widget_enabled_set(widget, false);
furiac_exit(NULL);
@ -111,6 +124,12 @@ void lf_rfid_workaround(void* p) {
hal_pwmn_set(
state->on ? 0.5 : 0.0, (float)(state->freq_khz * 1000), &htim15, TIM_CHANNEL_1);
if(!state->on) {
em4100_emulation(emulation_data, pull_pin_record);
} else {
gpio_write(pull_pin_record, false);
}
// common code, for example, force update UI
widget_update(widget);

View File

@ -48,6 +48,15 @@ struct Nfc {
#define EXAMPLE_NFCA_DEVICES 5
// TODO replace with pubsub
static bool isr_enabled = false;
void nfc_isr() {
if(isr_enabled) {
st25r3916Isr();
}
}
void nfc_worker_task(void* context) {
Nfc* nfc = context;
ReturnCode err;
@ -61,6 +70,8 @@ void nfc_worker_task(void* context) {
nfc->ticker = 0;
isr_enabled = true;
while(widget_is_enabled(nfc->widget)) {
rfalFieldOff();
platformDelay(1000);
@ -132,6 +143,7 @@ void nfc_worker_task(void* context) {
widget_update(nfc->widget);
}
isr_enabled = false;
rfalFieldOff();
rfalLowPowerModeStart();
nfc->ret = ERR_NONE;

View File

@ -3,6 +3,7 @@
* **[Bootloader testcase](Bootloader-test)**
* **[Input testcase](Input-test)**
* **[General testcase](General-building-test)**
* **[NFC and LF RFID testcase](NFC-LF-RFID-test)**
# Unit testing

View File

@ -0,0 +1,27 @@
## Check LF RFID
1. Go to LF RFID workaround app
2. See "LF RFID/OFF/125 kHz" on the screen
3. Read Flipper by EM4100 reader
4. Press ok
5. See "ON" on the screen
6. Check 125 kHz signal on RFID antenna by oscilloscope
7. Take EM4100 tag, place 20 mm from antenna
8. Get signal on demodulator output (RFID_IN)
9. Exit LF RFID app
## Check NFC
1. Go to NFC app
2. See "NFC timeout" on the screen
3. Place NFC tag directly on the antenna
4. See "NFC device found" and check type
5. Exit NFC app
For compatibility check:
1. make LF RFID test
2. make NFC test
3. Reboot device (issue with app loader don't allow run many apps)
4. make NFC test
5. make LF RFID test