mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-07-10 23:28:10 -07:00
Merge remote-tracking branch 'origin/dev' into electra
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
class TextStore {
|
||||
public:
|
||||
TextStore(uint8_t text_size);
|
||||
~TextStore();
|
||||
~TextStore(void);
|
||||
|
||||
void set(const char* text...);
|
||||
const uint8_t text_size;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
class ByteInputVM : public GenericViewModule {
|
||||
public:
|
||||
ByteInputVM();
|
||||
ByteInputVM(void);
|
||||
~ByteInputVM() final;
|
||||
View* get_view() final;
|
||||
void clean() final;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
class DialogExVM : public GenericViewModule {
|
||||
public:
|
||||
DialogExVM();
|
||||
DialogExVM(void);
|
||||
~DialogExVM() final;
|
||||
View* get_view() final;
|
||||
void clean() final;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
class PopupVM : public GenericViewModule {
|
||||
public:
|
||||
PopupVM();
|
||||
PopupVM(void);
|
||||
~PopupVM() final;
|
||||
View* get_view() final;
|
||||
void clean() final;
|
||||
@@ -56,12 +56,12 @@ public:
|
||||
/**
|
||||
* Enable popup timeout
|
||||
*/
|
||||
void enable_timeout();
|
||||
void enable_timeout(void);
|
||||
|
||||
/**
|
||||
* Disable popup timeout
|
||||
*/
|
||||
void disable_timeout();
|
||||
void disable_timeout(void);
|
||||
|
||||
private:
|
||||
Popup* popup;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
class SubmenuVM : public GenericViewModule {
|
||||
public:
|
||||
SubmenuVM();
|
||||
SubmenuVM(void);
|
||||
~SubmenuVM() final;
|
||||
View* get_view() final;
|
||||
void clean() final;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
class TextInputVM : public GenericViewModule {
|
||||
public:
|
||||
TextInputVM();
|
||||
TextInputVM(void);
|
||||
~TextInputVM() final;
|
||||
View* get_view() final;
|
||||
void clean() final;
|
||||
@@ -34,7 +34,7 @@ public:
|
||||
|
||||
void set_validator(TextInputValidatorCallback callback, void* callback_context);
|
||||
|
||||
void* get_validator_callback_context();
|
||||
void* get_validator_callback_context(void);
|
||||
|
||||
private:
|
||||
TextInput* text_input;
|
||||
|
||||
+10
-10
@@ -418,8 +418,8 @@ uint16_t bit_lib_crc16(
|
||||
}
|
||||
|
||||
void bit_lib_num_to_bytes_be(uint64_t src, uint8_t len, uint8_t* dest) {
|
||||
furi_assert(dest);
|
||||
furi_assert(len <= 8);
|
||||
furi_check(dest);
|
||||
furi_check(len <= 8);
|
||||
|
||||
while(len--) {
|
||||
dest[len] = (uint8_t)src;
|
||||
@@ -428,8 +428,8 @@ void bit_lib_num_to_bytes_be(uint64_t src, uint8_t len, uint8_t* dest) {
|
||||
}
|
||||
|
||||
void bit_lib_num_to_bytes_le(uint64_t src, uint8_t len, uint8_t* dest) {
|
||||
furi_assert(dest);
|
||||
furi_assert(len <= 8);
|
||||
furi_check(dest);
|
||||
furi_check(len <= 8);
|
||||
|
||||
for(int i = 0; i < len; i++) {
|
||||
dest[i] = (uint8_t)(src >> (8 * i));
|
||||
@@ -437,8 +437,8 @@ void bit_lib_num_to_bytes_le(uint64_t src, uint8_t len, uint8_t* dest) {
|
||||
}
|
||||
|
||||
uint64_t bit_lib_bytes_to_num_be(const uint8_t* src, uint8_t len) {
|
||||
furi_assert(src);
|
||||
furi_assert(len <= 8);
|
||||
furi_check(src);
|
||||
furi_check(len <= 8);
|
||||
|
||||
uint64_t res = 0;
|
||||
while(len--) {
|
||||
@@ -449,8 +449,8 @@ uint64_t bit_lib_bytes_to_num_be(const uint8_t* src, uint8_t len) {
|
||||
}
|
||||
|
||||
uint64_t bit_lib_bytes_to_num_le(const uint8_t* src, uint8_t len) {
|
||||
furi_assert(src);
|
||||
furi_assert(len <= 8);
|
||||
furi_check(src);
|
||||
furi_check(len <= 8);
|
||||
|
||||
uint64_t res = 0;
|
||||
uint8_t shift = 0;
|
||||
@@ -462,8 +462,8 @@ uint64_t bit_lib_bytes_to_num_le(const uint8_t* src, uint8_t len) {
|
||||
}
|
||||
|
||||
uint64_t bit_lib_bytes_to_num_bcd(const uint8_t* src, uint8_t len, bool* is_bcd) {
|
||||
furi_assert(src);
|
||||
furi_assert(len <= 9);
|
||||
furi_check(src);
|
||||
furi_check(len <= 9);
|
||||
|
||||
uint64_t res = 0;
|
||||
uint8_t nibble_1, nibble_2;
|
||||
|
||||
@@ -380,8 +380,8 @@ static GapConfig template_config = {
|
||||
.pairing_method = GapPairingPinCodeVerifyYesNo,
|
||||
.conn_param =
|
||||
{
|
||||
.conn_int_min = 0x18, // 30 ms
|
||||
.conn_int_max = 0x24, // 45 ms
|
||||
.conn_int_min = 0x18, // AN5289: 4.7, we need at least 25ms + advertisement, which is 30 ms
|
||||
.conn_int_max = 0x18, // 30 ms
|
||||
.slave_latency = 0,
|
||||
.supervisor_timeout = 0,
|
||||
},
|
||||
|
||||
@@ -169,7 +169,7 @@ static BleEventAckStatus ble_svc_hid_event_handler(void* event, void* context) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
BleServiceHid* ble_svc_hid_start() {
|
||||
BleServiceHid* ble_svc_hid_start(void) {
|
||||
BleServiceHid* hid_svc = malloc(sizeof(BleServiceHid));
|
||||
|
||||
// Register event handler
|
||||
|
||||
@@ -9,7 +9,7 @@ extern "C" {
|
||||
|
||||
typedef struct BleServiceHid BleServiceHid;
|
||||
|
||||
BleServiceHid* ble_svc_hid_start();
|
||||
BleServiceHid* ble_svc_hid_start(void);
|
||||
|
||||
void ble_svc_hid_stop(BleServiceHid* service);
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "datetime.h"
|
||||
#include <furi.h>
|
||||
|
||||
#define TAG "DateTime"
|
||||
|
||||
@@ -37,6 +38,8 @@ bool datetime_validate_datetime(DateTime* datetime) {
|
||||
}
|
||||
|
||||
uint32_t datetime_datetime_to_timestamp(DateTime* datetime) {
|
||||
furi_check(datetime);
|
||||
|
||||
uint32_t timestamp = 0;
|
||||
uint8_t years = 0;
|
||||
uint8_t leap_years = 0;
|
||||
@@ -67,10 +70,12 @@ uint32_t datetime_datetime_to_timestamp(DateTime* datetime) {
|
||||
}
|
||||
|
||||
void datetime_timestamp_to_datetime(uint32_t timestamp, DateTime* datetime) {
|
||||
furi_check(datetime);
|
||||
uint32_t days = timestamp / SECONDS_PER_DAY;
|
||||
uint32_t seconds_in_day = timestamp % SECONDS_PER_DAY;
|
||||
|
||||
datetime->year = EPOCH_START_YEAR;
|
||||
datetime->weekday = ((days + 3) % 7) + 1;
|
||||
|
||||
while(days >= datetime_get_days_per_year(datetime->year)) {
|
||||
days -= datetime_get_days_per_year(datetime->year);
|
||||
|
||||
@@ -115,17 +115,17 @@ void digital_sequence_register_signal(
|
||||
DigitalSequence* sequence,
|
||||
uint8_t signal_index,
|
||||
const DigitalSignal* signal) {
|
||||
furi_assert(sequence);
|
||||
furi_assert(signal);
|
||||
furi_assert(signal_index < DIGITAL_SEQUENCE_BANK_SIZE);
|
||||
furi_check(sequence);
|
||||
furi_check(signal);
|
||||
furi_check(signal_index < DIGITAL_SEQUENCE_BANK_SIZE);
|
||||
|
||||
sequence->signals[signal_index] = signal;
|
||||
}
|
||||
|
||||
void digital_sequence_add_signal(DigitalSequence* sequence, uint8_t signal_index) {
|
||||
furi_assert(sequence);
|
||||
furi_assert(signal_index < DIGITAL_SEQUENCE_BANK_SIZE);
|
||||
furi_assert(sequence->size < sequence->max_size);
|
||||
furi_check(sequence);
|
||||
furi_check(signal_index < DIGITAL_SEQUENCE_BANK_SIZE);
|
||||
furi_check(sequence->size < sequence->max_size);
|
||||
|
||||
sequence->data[sequence->size++] = signal_index;
|
||||
}
|
||||
@@ -140,14 +140,14 @@ static inline void digital_sequence_start_dma(DigitalSequence* sequence) {
|
||||
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2);
|
||||
}
|
||||
|
||||
static inline void digital_sequence_stop_dma() {
|
||||
static inline void digital_sequence_stop_dma(void) {
|
||||
LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_1);
|
||||
LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_2);
|
||||
LL_DMA_ClearFlag_TC1(DMA1);
|
||||
LL_DMA_ClearFlag_TC2(DMA1);
|
||||
}
|
||||
|
||||
static inline void digital_sequence_start_timer() {
|
||||
static inline void digital_sequence_start_timer(void) {
|
||||
furi_hal_bus_enable(FuriHalBusTIM2);
|
||||
|
||||
LL_TIM_SetCounterMode(TIM2, LL_TIM_COUNTERMODE_UP);
|
||||
@@ -162,7 +162,7 @@ static inline void digital_sequence_start_timer() {
|
||||
LL_TIM_GenerateEvent_UPDATE(TIM2);
|
||||
}
|
||||
|
||||
static void digital_sequence_stop_timer() {
|
||||
static void digital_sequence_stop_timer(void) {
|
||||
LL_TIM_DisableCounter(TIM2);
|
||||
LL_TIM_DisableUpdateEvent(TIM2);
|
||||
LL_TIM_DisableDMAReq_UPDATE(TIM2);
|
||||
@@ -280,9 +280,9 @@ static inline void digital_sequence_timer_buffer_reset(DigitalSequence* sequence
|
||||
}
|
||||
|
||||
void digital_sequence_transmit(DigitalSequence* sequence) {
|
||||
furi_assert(sequence);
|
||||
furi_assert(sequence->size);
|
||||
furi_assert(sequence->state == DigitalSequenceStateIdle);
|
||||
furi_check(sequence);
|
||||
furi_check(sequence->size);
|
||||
furi_check(sequence->state == DigitalSequenceStateIdle);
|
||||
|
||||
FURI_CRITICAL_ENTER();
|
||||
|
||||
|
||||
@@ -15,33 +15,33 @@ DigitalSignal* digital_signal_alloc(uint32_t max_size) {
|
||||
}
|
||||
|
||||
void digital_signal_free(DigitalSignal* signal) {
|
||||
furi_assert(signal);
|
||||
furi_check(signal);
|
||||
|
||||
free(signal->data);
|
||||
free(signal);
|
||||
}
|
||||
|
||||
bool digital_signal_get_start_level(const DigitalSignal* signal) {
|
||||
furi_assert(signal);
|
||||
furi_check(signal);
|
||||
|
||||
return signal->start_level;
|
||||
}
|
||||
|
||||
void digital_signal_set_start_level(DigitalSignal* signal, bool level) {
|
||||
furi_assert(signal);
|
||||
furi_check(signal);
|
||||
|
||||
signal->start_level = level;
|
||||
}
|
||||
|
||||
uint32_t digital_signal_get_size(const DigitalSignal* signal) {
|
||||
furi_assert(signal);
|
||||
furi_check(signal);
|
||||
|
||||
return signal->size;
|
||||
}
|
||||
|
||||
void digital_signal_add_period(DigitalSignal* signal, uint32_t ticks) {
|
||||
furi_assert(signal);
|
||||
furi_assert(signal->size < signal->max_size);
|
||||
furi_check(signal);
|
||||
furi_check(signal->size < signal->max_size);
|
||||
|
||||
const uint32_t duration = ticks + signal->remainder;
|
||||
|
||||
@@ -80,7 +80,7 @@ static void digital_signal_extend_last_period(DigitalSignal* signal, uint32_t ti
|
||||
}
|
||||
|
||||
void digital_signal_add_period_with_level(DigitalSignal* signal, uint32_t ticks, bool level) {
|
||||
furi_assert(signal);
|
||||
furi_check(signal);
|
||||
|
||||
if(signal->size == 0) {
|
||||
signal->start_level = level;
|
||||
|
||||
+37
-37
@@ -34,7 +34,7 @@ static void st25r3916_reg_tx_byte(FuriHalSpiBusHandle* handle, uint8_t byte) {
|
||||
}
|
||||
|
||||
void st25r3916_read_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t* val) {
|
||||
furi_assert(handle);
|
||||
furi_check(handle);
|
||||
st25r3916_read_burst_regs(handle, reg, val, 1);
|
||||
}
|
||||
|
||||
@@ -43,9 +43,9 @@ void st25r3916_read_burst_regs(
|
||||
uint8_t reg_start,
|
||||
uint8_t* values,
|
||||
uint8_t length) {
|
||||
furi_assert(handle);
|
||||
furi_assert(values);
|
||||
furi_assert(length);
|
||||
furi_check(handle);
|
||||
furi_check(values);
|
||||
furi_check(length);
|
||||
|
||||
furi_hal_gpio_write(handle->cs, false);
|
||||
|
||||
@@ -60,7 +60,7 @@ void st25r3916_read_burst_regs(
|
||||
}
|
||||
|
||||
void st25r3916_write_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t val) {
|
||||
furi_assert(handle);
|
||||
furi_check(handle);
|
||||
uint8_t reg_val = val;
|
||||
st25r3916_write_burst_regs(handle, reg, ®_val, 1);
|
||||
}
|
||||
@@ -70,9 +70,9 @@ void st25r3916_write_burst_regs(
|
||||
uint8_t reg_start,
|
||||
const uint8_t* values,
|
||||
uint8_t length) {
|
||||
furi_assert(handle);
|
||||
furi_assert(values);
|
||||
furi_assert(length);
|
||||
furi_check(handle);
|
||||
furi_check(values);
|
||||
furi_check(length);
|
||||
|
||||
furi_hal_gpio_write(handle->cs, false);
|
||||
|
||||
@@ -87,10 +87,10 @@ void st25r3916_write_burst_regs(
|
||||
}
|
||||
|
||||
void st25r3916_reg_write_fifo(FuriHalSpiBusHandle* handle, const uint8_t* buff, size_t length) {
|
||||
furi_assert(handle);
|
||||
furi_assert(buff);
|
||||
furi_assert(length);
|
||||
furi_assert(length <= ST25R3916_FIFO_DEPTH);
|
||||
furi_check(handle);
|
||||
furi_check(buff);
|
||||
furi_check(length);
|
||||
furi_check(length <= ST25R3916_FIFO_DEPTH);
|
||||
|
||||
furi_hal_gpio_write(handle->cs, false);
|
||||
st25r3916_reg_tx_byte(handle, ST25R3916_FIFO_LOAD);
|
||||
@@ -99,10 +99,10 @@ void st25r3916_reg_write_fifo(FuriHalSpiBusHandle* handle, const uint8_t* buff,
|
||||
}
|
||||
|
||||
void st25r3916_reg_read_fifo(FuriHalSpiBusHandle* handle, uint8_t* buff, size_t length) {
|
||||
furi_assert(handle);
|
||||
furi_assert(buff);
|
||||
furi_assert(length);
|
||||
furi_assert(length <= ST25R3916_FIFO_DEPTH);
|
||||
furi_check(handle);
|
||||
furi_check(buff);
|
||||
furi_check(length);
|
||||
furi_check(length <= ST25R3916_FIFO_DEPTH);
|
||||
|
||||
furi_hal_gpio_write(handle->cs, false);
|
||||
st25r3916_reg_tx_byte(handle, ST25R3916_FIFO_READ);
|
||||
@@ -111,10 +111,10 @@ void st25r3916_reg_read_fifo(FuriHalSpiBusHandle* handle, uint8_t* buff, size_t
|
||||
}
|
||||
|
||||
void st25r3916_write_pta_mem(FuriHalSpiBusHandle* handle, const uint8_t* values, size_t length) {
|
||||
furi_assert(handle);
|
||||
furi_assert(values);
|
||||
furi_assert(length);
|
||||
furi_assert(length <= ST25R3916_PTM_LEN);
|
||||
furi_check(handle);
|
||||
furi_check(values);
|
||||
furi_check(length);
|
||||
furi_check(length <= ST25R3916_PTM_LEN);
|
||||
|
||||
furi_hal_gpio_write(handle->cs, false);
|
||||
st25r3916_reg_tx_byte(handle, ST25R3916_PT_A_CONFIG_LOAD);
|
||||
@@ -123,10 +123,10 @@ void st25r3916_write_pta_mem(FuriHalSpiBusHandle* handle, const uint8_t* values,
|
||||
}
|
||||
|
||||
void st25r3916_read_pta_mem(FuriHalSpiBusHandle* handle, uint8_t* buff, size_t length) {
|
||||
furi_assert(handle);
|
||||
furi_assert(buff);
|
||||
furi_assert(length);
|
||||
furi_assert(length <= ST25R3916_PTM_LEN);
|
||||
furi_check(handle);
|
||||
furi_check(buff);
|
||||
furi_check(length);
|
||||
furi_check(length <= ST25R3916_PTM_LEN);
|
||||
|
||||
uint8_t tmp_buff[ST25R3916_PTM_LEN + 1];
|
||||
furi_hal_gpio_write(handle->cs, false);
|
||||
@@ -137,8 +137,8 @@ void st25r3916_read_pta_mem(FuriHalSpiBusHandle* handle, uint8_t* buff, size_t l
|
||||
}
|
||||
|
||||
void st25r3916_write_ptf_mem(FuriHalSpiBusHandle* handle, const uint8_t* values, size_t length) {
|
||||
furi_assert(handle);
|
||||
furi_assert(values);
|
||||
furi_check(handle);
|
||||
furi_check(values);
|
||||
|
||||
furi_hal_gpio_write(handle->cs, false);
|
||||
st25r3916_reg_tx_byte(handle, ST25R3916_PT_F_CONFIG_LOAD);
|
||||
@@ -147,8 +147,8 @@ void st25r3916_write_ptf_mem(FuriHalSpiBusHandle* handle, const uint8_t* values,
|
||||
}
|
||||
|
||||
void st25r3916_write_pttsn_mem(FuriHalSpiBusHandle* handle, uint8_t* buff, size_t length) {
|
||||
furi_assert(handle);
|
||||
furi_assert(buff);
|
||||
furi_check(handle);
|
||||
furi_check(buff);
|
||||
|
||||
furi_hal_gpio_write(handle->cs, false);
|
||||
st25r3916_reg_tx_byte(handle, ST25R3916_PT_TSN_DATA_LOAD);
|
||||
@@ -157,7 +157,7 @@ void st25r3916_write_pttsn_mem(FuriHalSpiBusHandle* handle, uint8_t* buff, size_
|
||||
}
|
||||
|
||||
void st25r3916_direct_cmd(FuriHalSpiBusHandle* handle, uint8_t cmd) {
|
||||
furi_assert(handle);
|
||||
furi_check(handle);
|
||||
|
||||
furi_hal_gpio_write(handle->cs, false);
|
||||
st25r3916_reg_tx_byte(handle, cmd | ST25R3916_CMD_MODE);
|
||||
@@ -165,7 +165,7 @@ void st25r3916_direct_cmd(FuriHalSpiBusHandle* handle, uint8_t cmd) {
|
||||
}
|
||||
|
||||
void st25r3916_read_test_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t* val) {
|
||||
furi_assert(handle);
|
||||
furi_check(handle);
|
||||
|
||||
furi_hal_gpio_write(handle->cs, false);
|
||||
st25r3916_reg_tx_byte(handle, ST25R3916_CMD_TEST_ACCESS);
|
||||
@@ -175,7 +175,7 @@ void st25r3916_read_test_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t*
|
||||
}
|
||||
|
||||
void st25r3916_write_test_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t val) {
|
||||
furi_assert(handle);
|
||||
furi_check(handle);
|
||||
|
||||
furi_hal_gpio_write(handle->cs, false);
|
||||
st25r3916_reg_tx_byte(handle, ST25R3916_CMD_TEST_ACCESS);
|
||||
@@ -185,7 +185,7 @@ void st25r3916_write_test_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t
|
||||
}
|
||||
|
||||
void st25r3916_clear_reg_bits(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t clr_mask) {
|
||||
furi_assert(handle);
|
||||
furi_check(handle);
|
||||
|
||||
uint8_t reg_val = 0;
|
||||
st25r3916_read_reg(handle, reg, ®_val);
|
||||
@@ -196,7 +196,7 @@ void st25r3916_clear_reg_bits(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t
|
||||
}
|
||||
|
||||
void st25r3916_set_reg_bits(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t set_mask) {
|
||||
furi_assert(handle);
|
||||
furi_check(handle);
|
||||
|
||||
uint8_t reg_val = 0;
|
||||
st25r3916_read_reg(handle, reg, ®_val);
|
||||
@@ -211,7 +211,7 @@ void st25r3916_change_reg_bits(
|
||||
uint8_t reg,
|
||||
uint8_t mask,
|
||||
uint8_t value) {
|
||||
furi_assert(handle);
|
||||
furi_check(handle);
|
||||
|
||||
st25r3916_modify_reg(handle, reg, mask, (mask & value));
|
||||
}
|
||||
@@ -221,7 +221,7 @@ void st25r3916_modify_reg(
|
||||
uint8_t reg,
|
||||
uint8_t clr_mask,
|
||||
uint8_t set_mask) {
|
||||
furi_assert(handle);
|
||||
furi_check(handle);
|
||||
|
||||
uint8_t reg_val = 0;
|
||||
uint8_t new_val = 0;
|
||||
@@ -237,7 +237,7 @@ void st25r3916_change_test_reg_bits(
|
||||
uint8_t reg,
|
||||
uint8_t mask,
|
||||
uint8_t value) {
|
||||
furi_assert(handle);
|
||||
furi_check(handle);
|
||||
|
||||
uint8_t reg_val = 0;
|
||||
uint8_t new_val = 0;
|
||||
@@ -249,7 +249,7 @@ void st25r3916_change_test_reg_bits(
|
||||
}
|
||||
|
||||
bool st25r3916_check_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t mask, uint8_t val) {
|
||||
furi_assert(handle);
|
||||
furi_check(handle);
|
||||
|
||||
uint8_t reg_val = 0;
|
||||
st25r3916_read_reg(handle, reg, ®_val);
|
||||
|
||||
@@ -9,6 +9,10 @@ bool elf_resolve_from_hashtable(
|
||||
const ElfApiInterface* interface,
|
||||
uint32_t hash,
|
||||
Elf32_Addr* address) {
|
||||
|
||||
furi_check(interface);
|
||||
furi_check(address);
|
||||
|
||||
bool result = false;
|
||||
const HashtableApiInterface* hashtable_interface =
|
||||
static_cast<const HashtableApiInterface*>(interface);
|
||||
@@ -33,5 +37,6 @@ bool elf_resolve_from_hashtable(
|
||||
}
|
||||
|
||||
uint32_t elf_symbolname_hash(const char* s) {
|
||||
furi_check(s);
|
||||
return elf_gnu_hash(s);
|
||||
}
|
||||
@@ -1,8 +1,11 @@
|
||||
#include "application_manifest.h"
|
||||
|
||||
#include <furi_hal_version.h>
|
||||
#include <furi.h>
|
||||
|
||||
bool flipper_application_manifest_is_valid(const FlipperApplicationManifest* manifest) {
|
||||
furi_check(manifest);
|
||||
|
||||
if((manifest->base.manifest_magic != FAP_MANIFEST_MAGIC) ||
|
||||
(manifest->base.manifest_version != FAP_MANIFEST_SUPPORTED_VERSION)) {
|
||||
return false;
|
||||
@@ -14,6 +17,9 @@ bool flipper_application_manifest_is_valid(const FlipperApplicationManifest* man
|
||||
bool flipper_application_manifest_is_too_old(
|
||||
const FlipperApplicationManifest* manifest,
|
||||
const ElfApiInterface* api_interface) {
|
||||
furi_check(manifest);
|
||||
furi_check(api_interface);
|
||||
|
||||
if(manifest->base.api_version.major < api_interface->api_version_major /* ||
|
||||
manifest->base.api_version.minor > app->api_interface->api_version_minor */) {
|
||||
return false;
|
||||
@@ -25,6 +31,9 @@ bool flipper_application_manifest_is_too_old(
|
||||
bool flipper_application_manifest_is_too_new(
|
||||
const FlipperApplicationManifest* manifest,
|
||||
const ElfApiInterface* api_interface) {
|
||||
furi_check(manifest);
|
||||
furi_check(api_interface);
|
||||
|
||||
if(manifest->base.api_version.major > api_interface->api_version_major /* ||
|
||||
manifest->base.api_version.minor > app->api_interface->api_version_minor */) {
|
||||
return false;
|
||||
@@ -34,6 +43,8 @@ bool flipper_application_manifest_is_too_new(
|
||||
}
|
||||
|
||||
bool flipper_application_manifest_is_target_compatible(const FlipperApplicationManifest* manifest) {
|
||||
furi_check(manifest);
|
||||
|
||||
const Version* version = furi_hal_version_get_firmware_version();
|
||||
return version_get_target(version) == manifest->base.hardware_target_id;
|
||||
}
|
||||
@@ -98,8 +98,7 @@ bool elf_file_is_init_complete(ELFFile* elf);
|
||||
/**
|
||||
* @brief Get actual entry point for ELF file
|
||||
* @param elf_file
|
||||
* @param args
|
||||
* @return int32_t
|
||||
* @return void*
|
||||
*/
|
||||
void* elf_file_get_entry_point(ELFFile* elf_file);
|
||||
|
||||
@@ -148,4 +147,4 @@ ElfProcessSectionResult elf_process_section(
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -24,7 +24,7 @@ FlipperApplicationList_t flipper_application_loaded_app_list = {0};
|
||||
static bool flipper_application_loaded_app_list_initialized = false;
|
||||
|
||||
static void flipper_application_list_add_app(const FlipperApplication* app) {
|
||||
furi_assert(app);
|
||||
furi_check(app);
|
||||
|
||||
if(!flipper_application_loaded_app_list_initialized) {
|
||||
FlipperApplicationList_init(flipper_application_loaded_app_list);
|
||||
@@ -34,8 +34,8 @@ static void flipper_application_list_add_app(const FlipperApplication* app) {
|
||||
}
|
||||
|
||||
static void flipper_application_list_remove_app(const FlipperApplication* app) {
|
||||
furi_assert(flipper_application_loaded_app_list_initialized);
|
||||
furi_assert(app);
|
||||
furi_check(flipper_application_loaded_app_list_initialized);
|
||||
furi_check(app);
|
||||
|
||||
FlipperApplicationList_it_t it;
|
||||
for(FlipperApplicationList_it(it, flipper_application_loaded_app_list);
|
||||
@@ -52,19 +52,24 @@ static void flipper_application_list_remove_app(const FlipperApplication* app) {
|
||||
|
||||
FlipperApplication*
|
||||
flipper_application_alloc(Storage* storage, const ElfApiInterface* api_interface) {
|
||||
furi_check(storage);
|
||||
furi_check(api_interface);
|
||||
|
||||
FlipperApplication* app = malloc(sizeof(FlipperApplication));
|
||||
app->elf = elf_file_alloc(storage, api_interface);
|
||||
app->thread = NULL;
|
||||
app->ep_thread_args = NULL;
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
bool flipper_application_is_plugin(FlipperApplication* app) {
|
||||
furi_check(app);
|
||||
return app->manifest.stack_size == 0;
|
||||
}
|
||||
|
||||
void flipper_application_free(FlipperApplication* app) {
|
||||
furi_assert(app);
|
||||
furi_check(app);
|
||||
|
||||
if(app->thread) {
|
||||
furi_thread_join(app->thread);
|
||||
@@ -184,20 +189,29 @@ static FlipperApplicationPreloadStatus
|
||||
/* Parse headers, load manifest */
|
||||
FlipperApplicationPreloadStatus
|
||||
flipper_application_preload_manifest(FlipperApplication* app, const char* path) {
|
||||
furi_check(app);
|
||||
furi_check(path);
|
||||
|
||||
return flipper_application_load(app, path, false);
|
||||
}
|
||||
|
||||
/* Parse headers, load full file */
|
||||
FlipperApplicationPreloadStatus
|
||||
flipper_application_preload(FlipperApplication* app, const char* path) {
|
||||
furi_check(app);
|
||||
furi_check(path);
|
||||
|
||||
return flipper_application_load(app, path, true);
|
||||
}
|
||||
|
||||
const FlipperApplicationManifest* flipper_application_get_manifest(FlipperApplication* app) {
|
||||
furi_check(app);
|
||||
return &app->manifest;
|
||||
}
|
||||
|
||||
FlipperApplicationLoadStatus flipper_application_map_to_memory(FlipperApplication* app) {
|
||||
furi_check(app);
|
||||
|
||||
ELFFileLoadStatus status = elf_file_load_sections(app->elf);
|
||||
|
||||
switch(status) {
|
||||
@@ -215,7 +229,7 @@ FlipperApplicationLoadStatus flipper_application_map_to_memory(FlipperApplicatio
|
||||
}
|
||||
|
||||
static int32_t flipper_application_thread(void* context) {
|
||||
furi_assert(context);
|
||||
furi_check(context);
|
||||
FlipperApplication* app = (FlipperApplication*)context;
|
||||
|
||||
elf_file_call_init(app->elf);
|
||||
@@ -237,6 +251,7 @@ static int32_t flipper_application_thread(void* context) {
|
||||
}
|
||||
|
||||
FuriThread* flipper_application_alloc_thread(FlipperApplication* app, const char* args) {
|
||||
furi_check(app);
|
||||
furi_check(app->thread == NULL);
|
||||
furi_check(!flipper_application_is_plugin(app));
|
||||
|
||||
@@ -290,6 +305,8 @@ const char* flipper_application_load_status_to_string(FlipperApplicationLoadStat
|
||||
|
||||
const FlipperAppPluginDescriptor*
|
||||
flipper_application_plugin_get_descriptor(FlipperApplication* app) {
|
||||
furi_check(app);
|
||||
|
||||
if(!flipper_application_is_plugin(app)) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -318,6 +335,11 @@ bool flipper_application_load_name_and_icon(
|
||||
Storage* storage,
|
||||
uint8_t** icon_ptr,
|
||||
FuriString* item_name) {
|
||||
furi_check(path);
|
||||
furi_check(storage);
|
||||
furi_check(icon_ptr);
|
||||
furi_check(item_name);
|
||||
|
||||
FlipperApplication* app = flipper_application_alloc(storage, firmware_api_interface);
|
||||
|
||||
FlipperApplicationPreloadStatus preload_res =
|
||||
|
||||
@@ -33,15 +33,13 @@ typedef enum {
|
||||
FlipperApplicationLoadStatusMissingImports,
|
||||
} FlipperApplicationLoadStatus;
|
||||
|
||||
/**
|
||||
* @brief Get text description of preload status
|
||||
/** Get text description of preload status
|
||||
* @param status Status code
|
||||
* @return String pointer to description
|
||||
*/
|
||||
const char* flipper_application_preload_status_to_string(FlipperApplicationPreloadStatus status);
|
||||
|
||||
/**
|
||||
* @brief Get text description of load status
|
||||
/** Get text description of load status
|
||||
* @param status Status code
|
||||
* @return String pointer to description
|
||||
*/
|
||||
@@ -61,8 +59,7 @@ typedef struct {
|
||||
uint8_t* debug_link;
|
||||
} FlipperApplicationState;
|
||||
|
||||
/**
|
||||
* @brief Initialize FlipperApplication object
|
||||
/** Initialize FlipperApplication object
|
||||
* @param storage Storage instance
|
||||
* @param api_interface ELF API interface to use for pre-loading and symbol resolving
|
||||
* @return Application instance
|
||||
@@ -70,44 +67,44 @@ typedef struct {
|
||||
FlipperApplication*
|
||||
flipper_application_alloc(Storage* storage, const ElfApiInterface* api_interface);
|
||||
|
||||
/**
|
||||
* @brief Destroy FlipperApplication object
|
||||
/** Destroy FlipperApplication object
|
||||
* @param app Application pointer
|
||||
*/
|
||||
void flipper_application_free(FlipperApplication* app);
|
||||
|
||||
/**
|
||||
* @brief Validate elf file and load application metadata
|
||||
* @param app Application pointer
|
||||
* @return Preload result code
|
||||
/** Validate elf file and load application metadata
|
||||
*
|
||||
* @param app Application pointer
|
||||
* @param[in] path The path to fap file
|
||||
*
|
||||
* @return Preload result code
|
||||
*/
|
||||
FlipperApplicationPreloadStatus
|
||||
flipper_application_preload(FlipperApplication* app, const char* path);
|
||||
|
||||
/**
|
||||
* @brief Validate elf file and load application manifest
|
||||
* @param app Application pointer
|
||||
* @return Preload result code
|
||||
/** Validate elf file and load application manifest
|
||||
*
|
||||
* @param app Application pointer
|
||||
* @param[in] path The path to fap file
|
||||
*
|
||||
* @return Preload result code
|
||||
*/
|
||||
FlipperApplicationPreloadStatus
|
||||
flipper_application_preload_manifest(FlipperApplication* app, const char* path);
|
||||
|
||||
/**
|
||||
* @brief Get pointer to application manifest for preloaded application
|
||||
/** Get pointer to application manifest for preloaded application
|
||||
* @param app Application pointer
|
||||
* @return Pointer to application manifest
|
||||
*/
|
||||
const FlipperApplicationManifest* flipper_application_get_manifest(FlipperApplication* app);
|
||||
|
||||
/**
|
||||
* @brief Load sections and process relocations for already pre-loaded application
|
||||
/** Load sections and process relocations for already pre-loaded application
|
||||
* @param app Application pointer
|
||||
* @return Load result code
|
||||
*/
|
||||
FlipperApplicationLoadStatus flipper_application_map_to_memory(FlipperApplication* app);
|
||||
|
||||
/**
|
||||
* @brief Allocate application thread at entry point address, using app name and
|
||||
/** Allocate application thread at entry point address, using app name and
|
||||
* stack size from metadata. Returned thread isn't started yet.
|
||||
* Can be only called once for application instance.
|
||||
* @param app Applicaiton pointer
|
||||
@@ -116,20 +113,17 @@ FlipperApplicationLoadStatus flipper_application_map_to_memory(FlipperApplicatio
|
||||
*/
|
||||
FuriThread* flipper_application_alloc_thread(FlipperApplication* app, const char* args);
|
||||
|
||||
/**
|
||||
* @brief Check if application is a plugin (not a runnable standalone app)
|
||||
/** Check if application is a plugin (not a runnable standalone app)
|
||||
* @param app Application pointer
|
||||
* @return true if application is a plugin, false otherwise
|
||||
*/
|
||||
bool flipper_application_is_plugin(FlipperApplication* app);
|
||||
|
||||
/**
|
||||
* @brief Entry point prototype for standalone applications
|
||||
/** Entry point prototype for standalone applications
|
||||
*/
|
||||
typedef int32_t (*FlipperApplicationEntryPoint)(void*);
|
||||
|
||||
/**
|
||||
* @brief An object that describes a plugin - must be returned by plugin's entry point
|
||||
/** An object that describes a plugin - must be returned by plugin's entry point
|
||||
*/
|
||||
typedef struct {
|
||||
const char* appid;
|
||||
@@ -137,21 +131,18 @@ typedef struct {
|
||||
const void* entry_point;
|
||||
} FlipperAppPluginDescriptor;
|
||||
|
||||
/**
|
||||
* @brief Entry point prototype for plugins
|
||||
/** Entry point prototype for plugins
|
||||
*/
|
||||
typedef const FlipperAppPluginDescriptor* (*FlipperApplicationPluginEntryPoint)(void);
|
||||
|
||||
/**
|
||||
* @brief Get plugin descriptor for preloaded plugin
|
||||
/** Get plugin descriptor for preloaded plugin
|
||||
* @param app Application pointer
|
||||
* @return Pointer to plugin descriptor
|
||||
*/
|
||||
const FlipperAppPluginDescriptor*
|
||||
flipper_application_plugin_get_descriptor(FlipperApplication* app);
|
||||
|
||||
/**
|
||||
* @brief Load name and icon from FAP file.
|
||||
/** Load name and icon from FAP file.
|
||||
*
|
||||
* @param path Path to FAP file.
|
||||
* @param storage Storage instance.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "composite_resolver.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include <m-list.h>
|
||||
#include <m-algo.h>
|
||||
|
||||
@@ -25,21 +26,28 @@ static bool composite_api_resolver_callback(
|
||||
return false;
|
||||
}
|
||||
|
||||
CompositeApiResolver* composite_api_resolver_alloc() {
|
||||
CompositeApiResolver* composite_api_resolver_alloc(void) {
|
||||
CompositeApiResolver* resolver = malloc(sizeof(CompositeApiResolver));
|
||||
|
||||
resolver->api_interface.api_version_major = 0;
|
||||
resolver->api_interface.api_version_minor = 0;
|
||||
resolver->api_interface.resolver_callback = &composite_api_resolver_callback;
|
||||
ElfApiInterfaceList_init(resolver->interfaces);
|
||||
|
||||
return resolver;
|
||||
}
|
||||
|
||||
void composite_api_resolver_free(CompositeApiResolver* resolver) {
|
||||
furi_check(resolver);
|
||||
|
||||
ElfApiInterfaceList_clear(resolver->interfaces);
|
||||
free(resolver);
|
||||
}
|
||||
|
||||
void composite_api_resolver_add(CompositeApiResolver* resolver, const ElfApiInterface* interface) {
|
||||
furi_check(resolver);
|
||||
furi_check(interface);
|
||||
|
||||
if(ElfApiInterfaceList_empty_p(resolver->interfaces)) {
|
||||
resolver->api_interface.api_version_major = interface->api_version_major;
|
||||
resolver->api_interface.api_version_minor = interface->api_version_minor;
|
||||
@@ -48,5 +56,6 @@ void composite_api_resolver_add(CompositeApiResolver* resolver, const ElfApiInte
|
||||
}
|
||||
|
||||
const ElfApiInterface* composite_api_resolver_get(CompositeApiResolver* resolver) {
|
||||
furi_check(resolver);
|
||||
return &resolver->api_interface;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ typedef struct CompositeApiResolver CompositeApiResolver;
|
||||
* @brief Allocate composite API resolver
|
||||
* @return CompositeApiResolver* instance
|
||||
*/
|
||||
CompositeApiResolver* composite_api_resolver_alloc();
|
||||
CompositeApiResolver* composite_api_resolver_alloc(void);
|
||||
|
||||
/**
|
||||
* @brief Free composite API resolver
|
||||
|
||||
@@ -36,6 +36,8 @@ PluginManager* plugin_manager_alloc(
|
||||
}
|
||||
|
||||
void plugin_manager_free(PluginManager* manager) {
|
||||
furi_check(manager);
|
||||
|
||||
for
|
||||
M_EACH(loaded_lib, manager->libs, FlipperApplicationList_t) {
|
||||
flipper_application_free(*loaded_lib);
|
||||
@@ -46,6 +48,7 @@ void plugin_manager_free(PluginManager* manager) {
|
||||
}
|
||||
|
||||
PluginManagerError plugin_manager_load_single(PluginManager* manager, const char* path) {
|
||||
furi_check(manager);
|
||||
FlipperApplication* lib = flipper_application_alloc(manager->storage, manager->api_interface);
|
||||
|
||||
PluginManagerError error = PluginManagerErrorNone;
|
||||
@@ -103,6 +106,7 @@ PluginManagerError plugin_manager_load_single(PluginManager* manager, const char
|
||||
}
|
||||
|
||||
PluginManagerError plugin_manager_load_all(PluginManager* manager, const char* path) {
|
||||
furi_check(manager);
|
||||
File* directory = storage_file_alloc(manager->storage);
|
||||
char file_name_buffer[256];
|
||||
FuriString* file_name = furi_string_alloc();
|
||||
@@ -139,15 +143,21 @@ PluginManagerError plugin_manager_load_all(PluginManager* manager, const char* p
|
||||
}
|
||||
|
||||
uint32_t plugin_manager_get_count(PluginManager* manager) {
|
||||
furi_check(manager);
|
||||
|
||||
return FlipperApplicationList_size(manager->libs);
|
||||
}
|
||||
|
||||
const FlipperAppPluginDescriptor* plugin_manager_get(PluginManager* manager, uint32_t index) {
|
||||
furi_check(manager);
|
||||
|
||||
FlipperApplication* app = *FlipperApplicationList_get(manager->libs, index);
|
||||
return flipper_application_plugin_get_descriptor(app);
|
||||
}
|
||||
|
||||
const void* plugin_manager_get_ep(PluginManager* manager, uint32_t index) {
|
||||
furi_check(manager);
|
||||
|
||||
const FlipperAppPluginDescriptor* lib_descr = plugin_manager_get(manager, index);
|
||||
furi_check(lib_descr);
|
||||
return lib_descr->entry_point;
|
||||
|
||||
@@ -23,7 +23,7 @@ Stream* flipper_format_get_raw_stream(FlipperFormat* flipper_format) {
|
||||
|
||||
/********************************** Public **********************************/
|
||||
|
||||
FlipperFormat* flipper_format_string_alloc() {
|
||||
FlipperFormat* flipper_format_string_alloc(void) {
|
||||
FlipperFormat* flipper_format = malloc(sizeof(FlipperFormat));
|
||||
flipper_format->stream = string_stream_alloc();
|
||||
flipper_format->strict_mode = false;
|
||||
@@ -45,18 +45,18 @@ FlipperFormat* flipper_format_buffered_file_alloc(Storage* storage) {
|
||||
}
|
||||
|
||||
bool flipper_format_file_open_existing(FlipperFormat* flipper_format, const char* path) {
|
||||
furi_assert(flipper_format);
|
||||
furi_check(flipper_format);
|
||||
return file_stream_open(flipper_format->stream, path, FSAM_READ_WRITE, FSOM_OPEN_EXISTING);
|
||||
}
|
||||
|
||||
bool flipper_format_buffered_file_open_existing(FlipperFormat* flipper_format, const char* path) {
|
||||
furi_assert(flipper_format);
|
||||
furi_check(flipper_format);
|
||||
return buffered_file_stream_open(
|
||||
flipper_format->stream, path, FSAM_READ_WRITE, FSOM_OPEN_EXISTING);
|
||||
}
|
||||
|
||||
bool flipper_format_file_open_append(FlipperFormat* flipper_format, const char* path) {
|
||||
furi_assert(flipper_format);
|
||||
furi_check(flipper_format);
|
||||
|
||||
bool result =
|
||||
file_stream_open(flipper_format->stream, path, FSAM_READ_WRITE, FSOM_OPEN_APPEND);
|
||||
@@ -87,33 +87,33 @@ bool flipper_format_file_open_append(FlipperFormat* flipper_format, const char*
|
||||
}
|
||||
|
||||
bool flipper_format_file_open_always(FlipperFormat* flipper_format, const char* path) {
|
||||
furi_assert(flipper_format);
|
||||
furi_check(flipper_format);
|
||||
return file_stream_open(flipper_format->stream, path, FSAM_READ_WRITE, FSOM_CREATE_ALWAYS);
|
||||
}
|
||||
|
||||
bool flipper_format_buffered_file_open_always(FlipperFormat* flipper_format, const char* path) {
|
||||
furi_assert(flipper_format);
|
||||
furi_check(flipper_format);
|
||||
return buffered_file_stream_open(
|
||||
flipper_format->stream, path, FSAM_READ_WRITE, FSOM_CREATE_ALWAYS);
|
||||
}
|
||||
|
||||
bool flipper_format_file_open_new(FlipperFormat* flipper_format, const char* path) {
|
||||
furi_assert(flipper_format);
|
||||
furi_check(flipper_format);
|
||||
return file_stream_open(flipper_format->stream, path, FSAM_READ_WRITE, FSOM_CREATE_NEW);
|
||||
}
|
||||
|
||||
bool flipper_format_file_close(FlipperFormat* flipper_format) {
|
||||
furi_assert(flipper_format);
|
||||
furi_check(flipper_format);
|
||||
return file_stream_close(flipper_format->stream);
|
||||
}
|
||||
|
||||
bool flipper_format_buffered_file_close(FlipperFormat* flipper_format) {
|
||||
furi_assert(flipper_format);
|
||||
furi_check(flipper_format);
|
||||
return buffered_file_stream_close(flipper_format->stream);
|
||||
}
|
||||
|
||||
void flipper_format_free(FlipperFormat* flipper_format) {
|
||||
furi_assert(flipper_format);
|
||||
furi_check(flipper_format);
|
||||
stream_free(flipper_format->stream);
|
||||
free(flipper_format);
|
||||
}
|
||||
@@ -123,12 +123,12 @@ void flipper_format_set_strict_mode(FlipperFormat* flipper_format, bool strict_m
|
||||
}
|
||||
|
||||
bool flipper_format_rewind(FlipperFormat* flipper_format) {
|
||||
furi_assert(flipper_format);
|
||||
furi_check(flipper_format);
|
||||
return stream_rewind(flipper_format->stream);
|
||||
}
|
||||
|
||||
bool flipper_format_seek_to_end(FlipperFormat* flipper_format) {
|
||||
furi_assert(flipper_format);
|
||||
furi_check(flipper_format);
|
||||
return stream_seek(flipper_format->stream, 0, StreamOffsetFromEnd);
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ bool flipper_format_read_header(
|
||||
FlipperFormat* flipper_format,
|
||||
FuriString* filetype,
|
||||
uint32_t* version) {
|
||||
furi_assert(flipper_format);
|
||||
furi_check(flipper_format);
|
||||
return flipper_format_read_string(flipper_format, flipper_format_filetype_key, filetype) &&
|
||||
flipper_format_read_uint32(flipper_format, flipper_format_version_key, version, 1);
|
||||
}
|
||||
@@ -154,7 +154,7 @@ bool flipper_format_write_header(
|
||||
FlipperFormat* flipper_format,
|
||||
FuriString* filetype,
|
||||
const uint32_t version) {
|
||||
furi_assert(flipper_format);
|
||||
furi_check(flipper_format);
|
||||
return flipper_format_write_header_cstr(
|
||||
flipper_format, furi_string_get_cstr(filetype), version);
|
||||
}
|
||||
@@ -163,7 +163,7 @@ bool flipper_format_write_header_cstr(
|
||||
FlipperFormat* flipper_format,
|
||||
const char* filetype,
|
||||
const uint32_t version) {
|
||||
furi_assert(flipper_format);
|
||||
furi_check(flipper_format);
|
||||
return flipper_format_write_string_cstr(
|
||||
flipper_format, flipper_format_filetype_key, filetype) &&
|
||||
flipper_format_write_uint32(flipper_format, flipper_format_version_key, &version, 1);
|
||||
@@ -173,19 +173,19 @@ bool flipper_format_get_value_count(
|
||||
FlipperFormat* flipper_format,
|
||||
const char* key,
|
||||
uint32_t* count) {
|
||||
furi_assert(flipper_format);
|
||||
furi_check(flipper_format);
|
||||
return flipper_format_stream_get_value_count(
|
||||
flipper_format->stream, key, count, flipper_format->strict_mode);
|
||||
}
|
||||
|
||||
bool flipper_format_read_string(FlipperFormat* flipper_format, const char* key, FuriString* data) {
|
||||
furi_assert(flipper_format);
|
||||
furi_check(flipper_format);
|
||||
return flipper_format_stream_read_value_line(
|
||||
flipper_format->stream, key, FlipperStreamValueStr, data, 1, flipper_format->strict_mode);
|
||||
}
|
||||
|
||||
bool flipper_format_write_string(FlipperFormat* flipper_format, const char* key, FuriString* data) {
|
||||
furi_assert(flipper_format);
|
||||
furi_check(flipper_format);
|
||||
FlipperStreamWriteData write_data = {
|
||||
.key = key,
|
||||
.type = FlipperStreamValueStr,
|
||||
@@ -200,7 +200,7 @@ bool flipper_format_write_string_cstr(
|
||||
FlipperFormat* flipper_format,
|
||||
const char* key,
|
||||
const char* data) {
|
||||
furi_assert(flipper_format);
|
||||
furi_check(flipper_format);
|
||||
FlipperStreamWriteData write_data = {
|
||||
.key = key,
|
||||
.type = FlipperStreamValueStr,
|
||||
@@ -216,7 +216,7 @@ bool flipper_format_read_hex_uint64(
|
||||
const char* key,
|
||||
uint64_t* data,
|
||||
const uint16_t data_size) {
|
||||
furi_assert(flipper_format);
|
||||
furi_check(flipper_format);
|
||||
return flipper_format_stream_read_value_line(
|
||||
flipper_format->stream,
|
||||
key,
|
||||
@@ -231,7 +231,7 @@ bool flipper_format_write_hex_uint64(
|
||||
const char* key,
|
||||
const uint64_t* data,
|
||||
const uint16_t data_size) {
|
||||
furi_assert(flipper_format);
|
||||
furi_check(flipper_format);
|
||||
FlipperStreamWriteData write_data = {
|
||||
.key = key,
|
||||
.type = FlipperStreamValueHexUint64,
|
||||
@@ -247,7 +247,7 @@ bool flipper_format_read_uint32(
|
||||
const char* key,
|
||||
uint32_t* data,
|
||||
const uint16_t data_size) {
|
||||
furi_assert(flipper_format);
|
||||
furi_check(flipper_format);
|
||||
return flipper_format_stream_read_value_line(
|
||||
flipper_format->stream,
|
||||
key,
|
||||
@@ -262,7 +262,7 @@ bool flipper_format_write_uint32(
|
||||
const char* key,
|
||||
const uint32_t* data,
|
||||
const uint16_t data_size) {
|
||||
furi_assert(flipper_format);
|
||||
furi_check(flipper_format);
|
||||
FlipperStreamWriteData write_data = {
|
||||
.key = key,
|
||||
.type = FlipperStreamValueUint32,
|
||||
@@ -292,7 +292,7 @@ bool flipper_format_write_int32(
|
||||
const char* key,
|
||||
const int32_t* data,
|
||||
const uint16_t data_size) {
|
||||
furi_assert(flipper_format);
|
||||
furi_check(flipper_format);
|
||||
FlipperStreamWriteData write_data = {
|
||||
.key = key,
|
||||
.type = FlipperStreamValueInt32,
|
||||
@@ -322,7 +322,7 @@ bool flipper_format_write_bool(
|
||||
const char* key,
|
||||
const bool* data,
|
||||
const uint16_t data_size) {
|
||||
furi_assert(flipper_format);
|
||||
furi_check(flipper_format);
|
||||
FlipperStreamWriteData write_data = {
|
||||
.key = key,
|
||||
.type = FlipperStreamValueBool,
|
||||
@@ -352,7 +352,7 @@ bool flipper_format_write_float(
|
||||
const char* key,
|
||||
const float* data,
|
||||
const uint16_t data_size) {
|
||||
furi_assert(flipper_format);
|
||||
furi_check(flipper_format);
|
||||
FlipperStreamWriteData write_data = {
|
||||
.key = key,
|
||||
.type = FlipperStreamValueFloat,
|
||||
@@ -382,7 +382,7 @@ bool flipper_format_write_hex(
|
||||
const char* key,
|
||||
const uint8_t* data,
|
||||
const uint16_t data_size) {
|
||||
furi_assert(flipper_format);
|
||||
furi_check(flipper_format);
|
||||
FlipperStreamWriteData write_data = {
|
||||
.key = key,
|
||||
.type = FlipperStreamValueHex,
|
||||
@@ -394,17 +394,17 @@ bool flipper_format_write_hex(
|
||||
}
|
||||
|
||||
bool flipper_format_write_comment(FlipperFormat* flipper_format, FuriString* data) {
|
||||
furi_assert(flipper_format);
|
||||
furi_check(flipper_format);
|
||||
return flipper_format_write_comment_cstr(flipper_format, furi_string_get_cstr(data));
|
||||
}
|
||||
|
||||
bool flipper_format_write_comment_cstr(FlipperFormat* flipper_format, const char* data) {
|
||||
furi_assert(flipper_format);
|
||||
furi_check(flipper_format);
|
||||
return flipper_format_stream_write_comment_cstr(flipper_format->stream, data);
|
||||
}
|
||||
|
||||
bool flipper_format_delete_key(FlipperFormat* flipper_format, const char* key) {
|
||||
furi_assert(flipper_format);
|
||||
furi_check(flipper_format);
|
||||
FlipperStreamWriteData write_data = {
|
||||
.key = key,
|
||||
.type = FlipperStreamValueIgnore,
|
||||
@@ -417,7 +417,7 @@ bool flipper_format_delete_key(FlipperFormat* flipper_format, const char* key) {
|
||||
}
|
||||
|
||||
bool flipper_format_update_string(FlipperFormat* flipper_format, const char* key, FuriString* data) {
|
||||
furi_assert(flipper_format);
|
||||
furi_check(flipper_format);
|
||||
FlipperStreamWriteData write_data = {
|
||||
.key = key,
|
||||
.type = FlipperStreamValueStr,
|
||||
@@ -433,7 +433,7 @@ bool flipper_format_update_string_cstr(
|
||||
FlipperFormat* flipper_format,
|
||||
const char* key,
|
||||
const char* data) {
|
||||
furi_assert(flipper_format);
|
||||
furi_check(flipper_format);
|
||||
FlipperStreamWriteData write_data = {
|
||||
.key = key,
|
||||
.type = FlipperStreamValueStr,
|
||||
@@ -450,7 +450,7 @@ bool flipper_format_update_uint32(
|
||||
const char* key,
|
||||
const uint32_t* data,
|
||||
const uint16_t data_size) {
|
||||
furi_assert(flipper_format);
|
||||
furi_check(flipper_format);
|
||||
FlipperStreamWriteData write_data = {
|
||||
.key = key,
|
||||
.type = FlipperStreamValueUint32,
|
||||
|
||||
+437
-368
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,5 @@
|
||||
#include "ibutton_key_i.h"
|
||||
#include <furi.h>
|
||||
|
||||
struct iButtonKey {
|
||||
iButtonProtocolId protocol_id;
|
||||
@@ -17,20 +18,28 @@ iButtonKey* ibutton_key_alloc(size_t data_size) {
|
||||
}
|
||||
|
||||
void ibutton_key_free(iButtonKey* key) {
|
||||
furi_check(key);
|
||||
|
||||
free(key->protocol_data);
|
||||
free(key);
|
||||
}
|
||||
|
||||
void ibutton_key_reset(iButtonKey* key) {
|
||||
furi_check(key);
|
||||
|
||||
key->protocol_id = iButtonProtocolIdInvalid;
|
||||
|
||||
memset(key->protocol_data, 0, key->protocol_data_size);
|
||||
}
|
||||
|
||||
iButtonProtocolId ibutton_key_get_protocol_id(const iButtonKey* key) {
|
||||
furi_check(key);
|
||||
|
||||
return key->protocol_id;
|
||||
}
|
||||
|
||||
void ibutton_key_set_protocol_id(iButtonKey* key, iButtonProtocolId protocol_id) {
|
||||
furi_check(key);
|
||||
key->protocol_id = protocol_id;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ static void ibutton_protocols_get_group_by_id(
|
||||
furi_crash();
|
||||
}
|
||||
|
||||
iButtonProtocols* ibutton_protocols_alloc() {
|
||||
iButtonProtocols* ibutton_protocols_alloc(void) {
|
||||
iButtonProtocols* protocols = malloc(sizeof(iButtonProtocols*));
|
||||
|
||||
protocols->group_datas = malloc(sizeof(iButtonProtocolGroupData*) * iButtonProtocolGroupMax);
|
||||
@@ -64,6 +64,8 @@ iButtonProtocols* ibutton_protocols_alloc() {
|
||||
}
|
||||
|
||||
void ibutton_protocols_free(iButtonProtocols* protocols) {
|
||||
furi_check(protocols);
|
||||
|
||||
for(iButtonProtocolGroupId i = 0; i < iButtonProtocolGroupMax; ++i) {
|
||||
ibutton_protocol_groups[i]->free(protocols->group_datas[i]);
|
||||
}
|
||||
@@ -72,7 +74,7 @@ void ibutton_protocols_free(iButtonProtocols* protocols) {
|
||||
free(protocols);
|
||||
}
|
||||
|
||||
uint32_t ibutton_protocols_get_protocol_count() {
|
||||
uint32_t ibutton_protocols_get_protocol_count(void) {
|
||||
uint32_t count = 0;
|
||||
|
||||
for(iButtonProtocolGroupId i = 0; i < iButtonProtocolGroupMax; ++i) {
|
||||
@@ -83,6 +85,9 @@ uint32_t ibutton_protocols_get_protocol_count() {
|
||||
}
|
||||
|
||||
iButtonProtocolId ibutton_protocols_get_id_by_name(iButtonProtocols* protocols, const char* name) {
|
||||
furi_check(protocols);
|
||||
furi_check(name);
|
||||
|
||||
iButtonProtocolLocalId offset = 0;
|
||||
|
||||
for(iButtonProtocolGroupId i = 0; i < iButtonProtocolGroupMax; ++i) {
|
||||
@@ -96,11 +101,16 @@ iButtonProtocolId ibutton_protocols_get_id_by_name(iButtonProtocols* protocols,
|
||||
}
|
||||
|
||||
uint32_t ibutton_protocols_get_features(iButtonProtocols* protocols, iButtonProtocolId id) {
|
||||
furi_check(protocols);
|
||||
|
||||
GET_PROTOCOL_GROUP(id);
|
||||
|
||||
return GROUP_BASE->get_features(GROUP_DATA, PROTOCOL_ID);
|
||||
}
|
||||
|
||||
size_t ibutton_protocols_get_max_data_size(iButtonProtocols* protocols) {
|
||||
furi_check(protocols);
|
||||
|
||||
size_t max_size = 0;
|
||||
|
||||
for(iButtonProtocolGroupId i = 0; i < iButtonProtocolGroupMax; ++i) {
|
||||
@@ -115,16 +125,25 @@ size_t ibutton_protocols_get_max_data_size(iButtonProtocols* protocols) {
|
||||
}
|
||||
|
||||
const char* ibutton_protocols_get_manufacturer(iButtonProtocols* protocols, iButtonProtocolId id) {
|
||||
furi_check(protocols);
|
||||
|
||||
GET_PROTOCOL_GROUP(id);
|
||||
|
||||
return GROUP_BASE->get_manufacturer(GROUP_DATA, PROTOCOL_ID);
|
||||
}
|
||||
|
||||
const char* ibutton_protocols_get_name(iButtonProtocols* protocols, iButtonProtocolId id) {
|
||||
furi_check(protocols);
|
||||
|
||||
GET_PROTOCOL_GROUP(id);
|
||||
|
||||
return GROUP_BASE->get_name(GROUP_DATA, PROTOCOL_ID);
|
||||
}
|
||||
|
||||
bool ibutton_protocols_read(iButtonProtocols* protocols, iButtonKey* key) {
|
||||
furi_check(protocols);
|
||||
furi_check(key);
|
||||
|
||||
iButtonProtocolLocalId id = iButtonProtocolIdInvalid;
|
||||
iButtonProtocolData* data = ibutton_key_get_protocol_data(key);
|
||||
|
||||
@@ -142,6 +161,9 @@ bool ibutton_protocols_read(iButtonProtocols* protocols, iButtonKey* key) {
|
||||
}
|
||||
|
||||
bool ibutton_protocols_write_blank(iButtonProtocols* protocols, iButtonKey* key) {
|
||||
furi_check(protocols);
|
||||
furi_check(key);
|
||||
|
||||
const iButtonProtocolId id = ibutton_key_get_protocol_id(key);
|
||||
iButtonProtocolData* data = ibutton_key_get_protocol_data(key);
|
||||
|
||||
@@ -150,6 +172,9 @@ bool ibutton_protocols_write_blank(iButtonProtocols* protocols, iButtonKey* key)
|
||||
}
|
||||
|
||||
bool ibutton_protocols_write_copy(iButtonProtocols* protocols, iButtonKey* key) {
|
||||
furi_check(protocols);
|
||||
furi_check(key);
|
||||
|
||||
const iButtonProtocolId id = ibutton_key_get_protocol_id(key);
|
||||
iButtonProtocolData* data = ibutton_key_get_protocol_data(key);
|
||||
|
||||
@@ -158,6 +183,9 @@ bool ibutton_protocols_write_copy(iButtonProtocols* protocols, iButtonKey* key)
|
||||
}
|
||||
|
||||
void ibutton_protocols_emulate_start(iButtonProtocols* protocols, iButtonKey* key) {
|
||||
furi_check(protocols);
|
||||
furi_check(key);
|
||||
|
||||
const iButtonProtocolId id = ibutton_key_get_protocol_id(key);
|
||||
iButtonProtocolData* data = ibutton_key_get_protocol_data(key);
|
||||
|
||||
@@ -166,6 +194,9 @@ void ibutton_protocols_emulate_start(iButtonProtocols* protocols, iButtonKey* ke
|
||||
}
|
||||
|
||||
void ibutton_protocols_emulate_stop(iButtonProtocols* protocols, iButtonKey* key) {
|
||||
furi_check(protocols);
|
||||
furi_check(key);
|
||||
|
||||
const iButtonProtocolId id = ibutton_key_get_protocol_id(key);
|
||||
iButtonProtocolData* data = ibutton_key_get_protocol_data(key);
|
||||
|
||||
@@ -177,6 +208,10 @@ bool ibutton_protocols_save(
|
||||
iButtonProtocols* protocols,
|
||||
const iButtonKey* key,
|
||||
const char* file_name) {
|
||||
furi_check(protocols);
|
||||
furi_check(key);
|
||||
furi_check(file_name);
|
||||
|
||||
const iButtonProtocolId id = ibutton_key_get_protocol_id(key);
|
||||
const iButtonProtocolData* data = ibutton_key_get_protocol_data(key);
|
||||
|
||||
@@ -207,6 +242,10 @@ bool ibutton_protocols_save(
|
||||
}
|
||||
|
||||
bool ibutton_protocols_load(iButtonProtocols* protocols, iButtonKey* key, const char* file_name) {
|
||||
furi_check(protocols);
|
||||
furi_check(key);
|
||||
furi_check(file_name);
|
||||
|
||||
iButtonProtocolData* data = ibutton_key_get_protocol_data(key);
|
||||
|
||||
bool success = false;
|
||||
@@ -252,6 +291,10 @@ void ibutton_protocols_render_data(
|
||||
iButtonProtocols* protocols,
|
||||
const iButtonKey* key,
|
||||
FuriString* result) {
|
||||
furi_check(protocols);
|
||||
furi_check(key);
|
||||
furi_check(result);
|
||||
|
||||
const iButtonProtocolId id = ibutton_key_get_protocol_id(key);
|
||||
const iButtonProtocolData* data = ibutton_key_get_protocol_data(key);
|
||||
|
||||
@@ -263,6 +306,10 @@ void ibutton_protocols_render_brief_data(
|
||||
iButtonProtocols* protocols,
|
||||
const iButtonKey* key,
|
||||
FuriString* result) {
|
||||
furi_check(protocols);
|
||||
furi_check(key);
|
||||
furi_check(result);
|
||||
|
||||
const iButtonProtocolId id = ibutton_key_get_protocol_id(key);
|
||||
const iButtonProtocolData* data = ibutton_key_get_protocol_data(key);
|
||||
|
||||
@@ -274,6 +321,10 @@ void ibutton_protocols_render_error(
|
||||
iButtonProtocols* protocols,
|
||||
const iButtonKey* key,
|
||||
FuriString* result) {
|
||||
furi_check(protocols);
|
||||
furi_check(key);
|
||||
furi_check(result);
|
||||
|
||||
const iButtonProtocolId id = ibutton_key_get_protocol_id(key);
|
||||
const iButtonProtocolData* data = ibutton_key_get_protocol_data(key);
|
||||
|
||||
@@ -282,6 +333,9 @@ void ibutton_protocols_render_error(
|
||||
}
|
||||
|
||||
bool ibutton_protocols_is_valid(iButtonProtocols* protocols, const iButtonKey* key) {
|
||||
furi_check(protocols);
|
||||
furi_check(key);
|
||||
|
||||
const iButtonProtocolId id = ibutton_key_get_protocol_id(key);
|
||||
const iButtonProtocolData* data = ibutton_key_get_protocol_data(key);
|
||||
|
||||
@@ -293,6 +347,10 @@ void ibutton_protocols_get_editable_data(
|
||||
iButtonProtocols* protocols,
|
||||
const iButtonKey* key,
|
||||
iButtonEditableData* editable) {
|
||||
furi_check(protocols);
|
||||
furi_check(key);
|
||||
furi_check(editable);
|
||||
|
||||
const iButtonProtocolId id = ibutton_key_get_protocol_id(key);
|
||||
iButtonProtocolData* data = ibutton_key_get_protocol_data(key);
|
||||
|
||||
@@ -301,6 +359,9 @@ void ibutton_protocols_get_editable_data(
|
||||
}
|
||||
|
||||
void ibutton_protocols_apply_edits(iButtonProtocols* protocols, const iButtonKey* key) {
|
||||
furi_check(protocols);
|
||||
furi_check(key);
|
||||
|
||||
const iButtonProtocolId id = ibutton_key_get_protocol_id(key);
|
||||
iButtonProtocolData* data = ibutton_key_get_protocol_data(key);
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ typedef struct iButtonProtocols iButtonProtocols;
|
||||
* Allocate an iButtonProtocols object
|
||||
* @return pointer to an iButtonProtocols object
|
||||
*/
|
||||
iButtonProtocols* ibutton_protocols_alloc();
|
||||
iButtonProtocols* ibutton_protocols_alloc(void);
|
||||
|
||||
/**
|
||||
* Destroy an iButtonProtocols object, free resources
|
||||
@@ -34,7 +34,7 @@ void ibutton_protocols_free(iButtonProtocols* protocols);
|
||||
/**
|
||||
* Get the total number of available protocols
|
||||
*/
|
||||
uint32_t ibutton_protocols_get_protocol_count();
|
||||
uint32_t ibutton_protocols_get_protocol_count(void);
|
||||
|
||||
/**
|
||||
* Get maximum data size out of all protocols available
|
||||
|
||||
@@ -23,6 +23,8 @@ typedef struct {
|
||||
static int32_t ibutton_worker_thread(void* thread_context);
|
||||
|
||||
iButtonWorker* ibutton_worker_alloc(iButtonProtocols* protocols) {
|
||||
furi_check(protocols);
|
||||
|
||||
iButtonWorker* worker = malloc(sizeof(iButtonWorker));
|
||||
|
||||
worker->protocols = protocols;
|
||||
@@ -38,7 +40,9 @@ void ibutton_worker_read_set_callback(
|
||||
iButtonWorker* worker,
|
||||
iButtonWorkerReadCallback callback,
|
||||
void* context) {
|
||||
furi_check(worker);
|
||||
furi_check(worker->mode_index == iButtonWorkerModeIdle);
|
||||
|
||||
worker->read_cb = callback;
|
||||
worker->cb_ctx = context;
|
||||
}
|
||||
@@ -47,7 +51,9 @@ void ibutton_worker_write_set_callback(
|
||||
iButtonWorker* worker,
|
||||
iButtonWorkerWriteCallback callback,
|
||||
void* context) {
|
||||
furi_check(worker);
|
||||
furi_check(worker->mode_index == iButtonWorkerModeIdle);
|
||||
|
||||
worker->write_cb = callback;
|
||||
worker->cb_ctx = context;
|
||||
}
|
||||
@@ -56,55 +62,83 @@ void ibutton_worker_emulate_set_callback(
|
||||
iButtonWorker* worker,
|
||||
iButtonWorkerEmulateCallback callback,
|
||||
void* context) {
|
||||
furi_check(worker);
|
||||
furi_check(worker->mode_index == iButtonWorkerModeIdle);
|
||||
|
||||
worker->emulate_cb = callback;
|
||||
worker->cb_ctx = context;
|
||||
}
|
||||
|
||||
void ibutton_worker_read_start(iButtonWorker* worker, iButtonKey* key) {
|
||||
furi_check(worker);
|
||||
|
||||
iButtonMessage message = {.type = iButtonMessageRead, .data.key = key};
|
||||
|
||||
furi_check(
|
||||
furi_message_queue_put(worker->messages, &message, FuriWaitForever) == FuriStatusOk);
|
||||
}
|
||||
|
||||
void ibutton_worker_write_blank_start(iButtonWorker* worker, iButtonKey* key) {
|
||||
furi_check(worker);
|
||||
furi_check(key);
|
||||
|
||||
iButtonMessage message = {.type = iButtonMessageWriteBlank, .data.key = key};
|
||||
|
||||
furi_check(
|
||||
furi_message_queue_put(worker->messages, &message, FuriWaitForever) == FuriStatusOk);
|
||||
}
|
||||
|
||||
void ibutton_worker_write_copy_start(iButtonWorker* worker, iButtonKey* key) {
|
||||
furi_check(worker);
|
||||
furi_check(key);
|
||||
|
||||
iButtonMessage message = {.type = iButtonMessageWriteCopy, .data.key = key};
|
||||
|
||||
furi_check(
|
||||
furi_message_queue_put(worker->messages, &message, FuriWaitForever) == FuriStatusOk);
|
||||
}
|
||||
|
||||
void ibutton_worker_emulate_start(iButtonWorker* worker, iButtonKey* key) {
|
||||
furi_check(worker);
|
||||
|
||||
iButtonMessage message = {.type = iButtonMessageEmulate, .data.key = key};
|
||||
|
||||
furi_check(
|
||||
furi_message_queue_put(worker->messages, &message, FuriWaitForever) == FuriStatusOk);
|
||||
}
|
||||
|
||||
void ibutton_worker_stop(iButtonWorker* worker) {
|
||||
furi_check(worker);
|
||||
|
||||
iButtonMessage message = {.type = iButtonMessageStop};
|
||||
|
||||
furi_check(
|
||||
furi_message_queue_put(worker->messages, &message, FuriWaitForever) == FuriStatusOk);
|
||||
}
|
||||
|
||||
void ibutton_worker_free(iButtonWorker* worker) {
|
||||
furi_check(worker);
|
||||
|
||||
furi_message_queue_free(worker->messages);
|
||||
furi_thread_free(worker->thread);
|
||||
|
||||
free(worker);
|
||||
}
|
||||
|
||||
void ibutton_worker_start_thread(iButtonWorker* worker) {
|
||||
furi_check(worker);
|
||||
|
||||
furi_thread_start(worker->thread);
|
||||
}
|
||||
|
||||
void ibutton_worker_stop_thread(iButtonWorker* worker) {
|
||||
furi_check(worker);
|
||||
|
||||
iButtonMessage message = {.type = iButtonMessageEnd};
|
||||
|
||||
furi_check(
|
||||
furi_message_queue_put(worker->messages, &message, FuriWaitForever) == FuriStatusOk);
|
||||
|
||||
furi_thread_join(worker->thread);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ typedef struct {
|
||||
OneWireSlave* bus;
|
||||
} iButtonProtocolGroupDallas;
|
||||
|
||||
static iButtonProtocolGroupDallas* ibutton_protocol_group_dallas_alloc() {
|
||||
static iButtonProtocolGroupDallas* ibutton_protocol_group_dallas_alloc(void) {
|
||||
iButtonProtocolGroupDallas* group = malloc(sizeof(iButtonProtocolGroupDallas));
|
||||
|
||||
group->host = onewire_host_alloc(&gpio_ibutton);
|
||||
|
||||
@@ -16,7 +16,7 @@ typedef struct {
|
||||
ProtocolId emulate_id;
|
||||
} iButtonProtocolGroupMisc;
|
||||
|
||||
static iButtonProtocolGroupMisc* ibutton_protocol_group_misc_alloc() {
|
||||
static iButtonProtocolGroupMisc* ibutton_protocol_group_misc_alloc(void) {
|
||||
iButtonProtocolGroupMisc* group = malloc(sizeof(iButtonProtocolGroupMisc));
|
||||
|
||||
group->dict = protocol_dict_alloc(ibutton_protocols_misc, iButtonProtocolMiscMax);
|
||||
|
||||
@@ -18,7 +18,6 @@ typedef InfraredStatus (
|
||||
typedef struct {
|
||||
InfraredTimings timings;
|
||||
bool manchester_start_from_space;
|
||||
bool no_stop_bit;
|
||||
uint8_t databit_len[4];
|
||||
InfraredCommonDecode decode;
|
||||
InfraredCommonDecodeRepeat decode_repeat;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "sirc/infrared_protocol_sirc.h"
|
||||
#include "kaseikyo/infrared_protocol_kaseikyo.h"
|
||||
#include "rca/infrared_protocol_rca.h"
|
||||
#include "pioneer/infrared_protocol_pioneer.h"
|
||||
|
||||
typedef struct {
|
||||
InfraredAlloc alloc;
|
||||
@@ -114,6 +115,20 @@ static const InfraredEncoderDecoder infrared_encoder_decoder[] = {
|
||||
.free = infrared_encoder_sirc_free},
|
||||
.get_protocol_variant = infrared_protocol_sirc_get_variant,
|
||||
},
|
||||
{
|
||||
.decoder =
|
||||
{.alloc = infrared_decoder_pioneer_alloc,
|
||||
.decode = infrared_decoder_pioneer_decode,
|
||||
.reset = infrared_decoder_pioneer_reset,
|
||||
.check_ready = infrared_decoder_pioneer_check_ready,
|
||||
.free = infrared_decoder_pioneer_free},
|
||||
.encoder =
|
||||
{.alloc = infrared_encoder_pioneer_alloc,
|
||||
.encode = infrared_encoder_pioneer_encode,
|
||||
.reset = infrared_encoder_pioneer_reset,
|
||||
.free = infrared_encoder_pioneer_free},
|
||||
.get_protocol_variant = infrared_protocol_pioneer_get_variant,
|
||||
},
|
||||
{
|
||||
.decoder =
|
||||
{.alloc = infrared_decoder_kaseikyo_alloc,
|
||||
@@ -149,7 +164,7 @@ static const InfraredProtocolVariant* infrared_get_variant_by_protocol(InfraredP
|
||||
|
||||
const InfraredMessage*
|
||||
infrared_decode(InfraredDecoderHandler* handler, bool level, uint32_t duration) {
|
||||
furi_assert(handler);
|
||||
furi_check(handler);
|
||||
|
||||
InfraredMessage* message = NULL;
|
||||
InfraredMessage* result = NULL;
|
||||
@@ -181,8 +196,8 @@ InfraredDecoderHandler* infrared_alloc_decoder(void) {
|
||||
}
|
||||
|
||||
void infrared_free_decoder(InfraredDecoderHandler* handler) {
|
||||
furi_assert(handler);
|
||||
furi_assert(handler->ctx);
|
||||
furi_check(handler);
|
||||
furi_check(handler->ctx);
|
||||
|
||||
for(size_t i = 0; i < COUNT_OF(infrared_encoder_decoder); ++i) {
|
||||
if(infrared_encoder_decoder[i].decoder.free)
|
||||
@@ -194,6 +209,8 @@ void infrared_free_decoder(InfraredDecoderHandler* handler) {
|
||||
}
|
||||
|
||||
void infrared_reset_decoder(InfraredDecoderHandler* handler) {
|
||||
furi_check(handler);
|
||||
|
||||
for(size_t i = 0; i < COUNT_OF(infrared_encoder_decoder); ++i) {
|
||||
if(infrared_encoder_decoder[i].decoder.reset)
|
||||
infrared_encoder_decoder[i].decoder.reset(handler->ctx[i]);
|
||||
@@ -201,7 +218,7 @@ void infrared_reset_decoder(InfraredDecoderHandler* handler) {
|
||||
}
|
||||
|
||||
const InfraredMessage* infrared_check_decoder_ready(InfraredDecoderHandler* handler) {
|
||||
furi_assert(handler);
|
||||
furi_check(handler);
|
||||
|
||||
InfraredMessage* message = NULL;
|
||||
InfraredMessage* result = NULL;
|
||||
@@ -226,13 +243,13 @@ InfraredEncoderHandler* infrared_alloc_encoder(void) {
|
||||
}
|
||||
|
||||
void infrared_free_encoder(InfraredEncoderHandler* handler) {
|
||||
furi_assert(handler);
|
||||
furi_check(handler);
|
||||
const InfraredEncoders* encoder = handler->encoder;
|
||||
|
||||
if(encoder || handler->handler) {
|
||||
furi_assert(encoder);
|
||||
furi_assert(handler->handler);
|
||||
furi_assert(encoder->free);
|
||||
furi_check(encoder);
|
||||
furi_check(handler->handler);
|
||||
furi_check(encoder->free);
|
||||
encoder->free(handler->handler);
|
||||
}
|
||||
|
||||
@@ -250,20 +267,20 @@ static int infrared_find_index_by_protocol(InfraredProtocol protocol) {
|
||||
}
|
||||
|
||||
void infrared_reset_encoder(InfraredEncoderHandler* handler, const InfraredMessage* message) {
|
||||
furi_assert(handler);
|
||||
furi_assert(message);
|
||||
furi_check(handler);
|
||||
furi_check(message);
|
||||
int index = infrared_find_index_by_protocol(message->protocol);
|
||||
furi_check(index >= 0);
|
||||
|
||||
const InfraredEncoders* required_encoder = &infrared_encoder_decoder[index].encoder;
|
||||
furi_assert(required_encoder);
|
||||
furi_assert(required_encoder->reset);
|
||||
furi_assert(required_encoder->alloc);
|
||||
furi_check(required_encoder);
|
||||
furi_check(required_encoder->reset);
|
||||
furi_check(required_encoder->alloc);
|
||||
|
||||
/* Realloc encoder if different protocol set */
|
||||
if(required_encoder != handler->encoder) {
|
||||
if(handler->handler != NULL) {
|
||||
furi_assert(handler->encoder->free);
|
||||
furi_check(handler->encoder->free);
|
||||
handler->encoder->free(handler->handler);
|
||||
}
|
||||
handler->encoder = required_encoder;
|
||||
@@ -274,15 +291,16 @@ void infrared_reset_encoder(InfraredEncoderHandler* handler, const InfraredMessa
|
||||
}
|
||||
|
||||
InfraredStatus infrared_encode(InfraredEncoderHandler* handler, uint32_t* duration, bool* level) {
|
||||
furi_assert(handler);
|
||||
furi_assert(duration);
|
||||
furi_assert(level);
|
||||
furi_check(handler);
|
||||
furi_check(duration);
|
||||
furi_check(level);
|
||||
|
||||
const InfraredEncoders* encoder = handler->encoder;
|
||||
furi_assert(encoder);
|
||||
furi_assert(encoder->encode);
|
||||
furi_check(encoder);
|
||||
furi_check(encoder->encode);
|
||||
|
||||
InfraredStatus status = encoder->encode(handler->handler, duration, level);
|
||||
furi_assert(status != InfraredStatusError);
|
||||
furi_check(status != InfraredStatusError);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -292,6 +310,8 @@ bool infrared_is_protocol_valid(InfraredProtocol protocol) {
|
||||
}
|
||||
|
||||
InfraredProtocol infrared_get_protocol_by_name(const char* protocol_name) {
|
||||
furi_check(protocol_name);
|
||||
|
||||
for(InfraredProtocol protocol = 0; protocol < InfraredProtocolMAX; ++protocol) {
|
||||
const char* name = infrared_get_protocol_name(protocol);
|
||||
if(!strcmp(name, protocol_name)) return protocol;
|
||||
@@ -306,7 +326,7 @@ static const InfraredProtocolVariant* infrared_get_variant_by_protocol(InfraredP
|
||||
variant = infrared_encoder_decoder[index].get_protocol_variant(protocol);
|
||||
}
|
||||
|
||||
furi_assert(variant);
|
||||
furi_check(variant);
|
||||
return variant;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@ typedef enum {
|
||||
InfraredProtocolSIRC20,
|
||||
InfraredProtocolKaseikyo,
|
||||
InfraredProtocolRCA,
|
||||
InfraredProtocolPioneer,
|
||||
/* Add new protocols here */
|
||||
InfraredProtocolMAX,
|
||||
} InfraredProtocol;
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ const InfraredCommonProtocolSpec infrared_protocol_kaseikyo = {
|
||||
.min_split_time = INFRARED_KASEIKYO_MIN_SPLIT_TIME,
|
||||
},
|
||||
.databit_len[0] = 48,
|
||||
.no_stop_bit = false,
|
||||
.decode = infrared_common_decode_pdwm,
|
||||
.encode = infrared_common_encode_pdwm,
|
||||
.interpret = infrared_decoder_kaseikyo_interpret,
|
||||
|
||||
@@ -16,7 +16,6 @@ const InfraredCommonProtocolSpec infrared_protocol_nec = {
|
||||
},
|
||||
.databit_len[0] = 42,
|
||||
.databit_len[1] = 32,
|
||||
.no_stop_bit = false,
|
||||
.decode = infrared_common_decode_pdwm,
|
||||
.encode = infrared_common_encode_pdwm,
|
||||
.interpret = infrared_decoder_nec_interpret,
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
#include "infrared_protocol_pioneer_i.h"
|
||||
#include <core/check.h>
|
||||
|
||||
InfraredMessage* infrared_decoder_pioneer_check_ready(void* ctx) {
|
||||
return infrared_common_decoder_check_ready(ctx);
|
||||
}
|
||||
|
||||
bool infrared_decoder_pioneer_interpret(InfraredCommonDecoder* decoder) {
|
||||
furi_assert(decoder);
|
||||
|
||||
uint32_t* data = (void*)&decoder->data[0];
|
||||
uint8_t address = 0;
|
||||
uint8_t command = 0;
|
||||
InfraredProtocol protocol = InfraredProtocolUnknown;
|
||||
|
||||
if(decoder->databit_cnt == decoder->protocol->databit_len[0] ||
|
||||
decoder->databit_cnt == decoder->protocol->databit_len[1]) {
|
||||
address = *data & 0xFF;
|
||||
uint8_t real_address_checksum = ~address;
|
||||
uint8_t address_checksum = (*data >> 8) & 0xFF;
|
||||
command = (*data >> 16) & 0xFF;
|
||||
uint8_t real_command_checksum = ~command;
|
||||
uint8_t command_checksum = (*data >> 24) & 0xFF;
|
||||
if(address_checksum != real_address_checksum) {
|
||||
return false;
|
||||
}
|
||||
if(command_checksum != real_command_checksum) {
|
||||
return false;
|
||||
}
|
||||
protocol = InfraredProtocolPioneer;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
decoder->message.protocol = protocol;
|
||||
decoder->message.address = address;
|
||||
decoder->message.command = command;
|
||||
decoder->message.repeat = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void* infrared_decoder_pioneer_alloc(void) {
|
||||
return infrared_common_decoder_alloc(&infrared_protocol_pioneer);
|
||||
}
|
||||
|
||||
InfraredMessage* infrared_decoder_pioneer_decode(void* decoder, bool level, uint32_t duration) {
|
||||
return infrared_common_decode(decoder, level, duration);
|
||||
}
|
||||
|
||||
void infrared_decoder_pioneer_free(void* decoder) {
|
||||
infrared_common_decoder_free(decoder);
|
||||
}
|
||||
|
||||
void infrared_decoder_pioneer_reset(void* decoder) {
|
||||
infrared_common_decoder_reset(decoder);
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
#include "infrared_protocol_pioneer_i.h"
|
||||
#include <core/check.h>
|
||||
|
||||
void infrared_encoder_pioneer_reset(void* encoder_ptr, const InfraredMessage* message) {
|
||||
furi_assert(encoder_ptr);
|
||||
furi_assert(message);
|
||||
|
||||
InfraredCommonEncoder* encoder = encoder_ptr;
|
||||
infrared_common_encoder_reset(encoder);
|
||||
|
||||
uint8_t* data = encoder->data;
|
||||
|
||||
if(message->protocol == InfraredProtocolPioneer) {
|
||||
data[0] = message->address & 0xFF;
|
||||
data[1] = ~(message->address & 0xFF);
|
||||
data[2] = message->command & 0xFF;
|
||||
data[3] = ~(message->command & 0xFF);
|
||||
data[4] = 0;
|
||||
encoder->bits_to_encode = encoder->protocol->databit_len[0];
|
||||
} else {
|
||||
furi_crash();
|
||||
}
|
||||
}
|
||||
|
||||
void* infrared_encoder_pioneer_alloc(void) {
|
||||
return infrared_common_encoder_alloc(&infrared_protocol_pioneer);
|
||||
}
|
||||
|
||||
void infrared_encoder_pioneer_free(void* encoder_ptr) {
|
||||
infrared_common_encoder_free(encoder_ptr);
|
||||
}
|
||||
|
||||
InfraredStatus infrared_encoder_pioneer_encode_repeat(
|
||||
InfraredCommonEncoder* encoder,
|
||||
uint32_t* duration,
|
||||
bool* level) {
|
||||
furi_assert(encoder);
|
||||
|
||||
*duration = INFRARED_PIONEER_SILENCE;
|
||||
*level = false;
|
||||
|
||||
encoder->timings_sum = 0;
|
||||
encoder->timings_encoded = 1;
|
||||
encoder->bits_encoded = 0;
|
||||
encoder->state = InfraredCommonEncoderStatePreamble;
|
||||
|
||||
return InfraredStatusOk;
|
||||
}
|
||||
|
||||
InfraredStatus
|
||||
infrared_encoder_pioneer_encode(void* encoder_ptr, uint32_t* duration, bool* level) {
|
||||
InfraredCommonEncoder* encoder = encoder_ptr;
|
||||
|
||||
InfraredStatus status = infrared_common_encode(encoder, duration, level);
|
||||
if((status == InfraredStatusOk) && (encoder->bits_encoded == encoder->bits_to_encode)) {
|
||||
furi_assert(!*level);
|
||||
status = InfraredStatusDone;
|
||||
encoder->state = InfraredCommonEncoderStateEncodeRepeat;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#include "infrared_protocol_pioneer_i.h"
|
||||
|
||||
const InfraredCommonProtocolSpec infrared_protocol_pioneer = {
|
||||
.timings =
|
||||
{
|
||||
.preamble_mark = INFRARED_PIONEER_PREAMBLE_MARK,
|
||||
.preamble_space = INFRARED_PIONEER_PREAMBLE_SPACE,
|
||||
.bit1_mark = INFRARED_PIONEER_BIT1_MARK,
|
||||
.bit1_space = INFRARED_PIONEER_BIT1_SPACE,
|
||||
.bit0_mark = INFRARED_PIONEER_BIT0_MARK,
|
||||
.bit0_space = INFRARED_PIONEER_BIT0_SPACE,
|
||||
.preamble_tolerance = INFRARED_PIONEER_PREAMBLE_TOLERANCE,
|
||||
.bit_tolerance = INFRARED_PIONEER_BIT_TOLERANCE,
|
||||
.silence_time = INFRARED_PIONEER_SILENCE,
|
||||
.min_split_time = INFRARED_PIONEER_MIN_SPLIT_TIME,
|
||||
},
|
||||
.databit_len[0] = 33,
|
||||
.databit_len[1] = 32,
|
||||
.decode = infrared_common_decode_pdwm,
|
||||
.encode = infrared_common_encode_pdwm,
|
||||
.interpret = infrared_decoder_pioneer_interpret,
|
||||
.decode_repeat = NULL,
|
||||
.encode_repeat = infrared_encoder_pioneer_encode_repeat,
|
||||
};
|
||||
|
||||
static const InfraredProtocolVariant infrared_protocol_variant_pioneer = {
|
||||
.name = "Pioneer",
|
||||
.address_length = 8,
|
||||
.command_length = 8,
|
||||
.frequency = INFRARED_PIONEER_CARRIER_FREQUENCY,
|
||||
.duty_cycle = INFRARED_PIONEER_DUTY_CYCLE,
|
||||
.repeat_count = INFRARED_PIONEER_REPEAT_COUNT_MIN,
|
||||
};
|
||||
|
||||
const InfraredProtocolVariant* infrared_protocol_pioneer_get_variant(InfraredProtocol protocol) {
|
||||
if(protocol == InfraredProtocolPioneer)
|
||||
return &infrared_protocol_variant_pioneer;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include "../infrared_i.h"
|
||||
|
||||
/***************************************************************************************************
|
||||
* Pioneer SR protocol description
|
||||
* http://www.adrian-kingston.com/IRFormatPioneer.htm
|
||||
****************************************************************************************************
|
||||
* Preamble Preamble Pulse Width Modulation Pause Entirely repeat
|
||||
* mark space up to period message..
|
||||
*
|
||||
* 8500 4250 33 bits (500, 1500) ...26000 8500 4250
|
||||
* __________ _ _ _ _ _ _ _ _ _ _ _ _ _ __________ _ _
|
||||
* ____ __________ _ _ _ __ __ __ _ _ __ __ _ _ ____________________ __________ _
|
||||
*
|
||||
* In 33 bits of data there is:
|
||||
* - 8 bits address
|
||||
* - 8 bits address inverse
|
||||
* - 8 bits command
|
||||
* - 8 bits command inverse
|
||||
* - 1 stop bit
|
||||
***************************************************************************************************/
|
||||
|
||||
void* infrared_decoder_pioneer_alloc(void);
|
||||
void infrared_decoder_pioneer_reset(void* decoder);
|
||||
InfraredMessage* infrared_decoder_pioneer_check_ready(void* decoder);
|
||||
void infrared_decoder_pioneer_free(void* decoder);
|
||||
InfraredMessage* infrared_decoder_pioneer_decode(void* decoder, bool level, uint32_t duration);
|
||||
|
||||
void* infrared_encoder_pioneer_alloc(void);
|
||||
void infrared_encoder_pioneer_reset(void* encoder_ptr, const InfraredMessage* message);
|
||||
void infrared_encoder_pioneer_free(void* decoder);
|
||||
InfraredStatus
|
||||
infrared_encoder_pioneer_encode(void* encoder_ptr, uint32_t* duration, bool* polarity);
|
||||
|
||||
const InfraredProtocolVariant* infrared_protocol_pioneer_get_variant(InfraredProtocol protocol);
|
||||
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "../common/infrared_common_i.h"
|
||||
|
||||
#define INFRARED_PIONEER_CARRIER_FREQUENCY 40000
|
||||
#define INFRARED_PIONEER_DUTY_CYCLE 0.33
|
||||
#define INFRARED_PIONEER_PREAMBLE_MARK 8500
|
||||
#define INFRARED_PIONEER_PREAMBLE_SPACE 4225
|
||||
#define INFRARED_PIONEER_BIT1_MARK 500
|
||||
#define INFRARED_PIONEER_BIT1_SPACE 1500
|
||||
#define INFRARED_PIONEER_BIT0_MARK 500
|
||||
#define INFRARED_PIONEER_BIT0_SPACE 500
|
||||
#define INFRARED_PIONEER_PREAMBLE_TOLERANCE 200 // us
|
||||
#define INFRARED_PIONEER_BIT_TOLERANCE 120 // us
|
||||
#define INFRARED_PIONEER_SILENCE 26000
|
||||
#define INFRARED_PIONEER_MIN_SPLIT_TIME (INFRARED_PIONEER_SILENCE)
|
||||
#define INFRARED_PIONEER_REPEAT_COUNT_MIN 2
|
||||
|
||||
extern const InfraredCommonProtocolSpec infrared_protocol_pioneer;
|
||||
|
||||
bool infrared_decoder_pioneer_interpret(InfraredCommonDecoder* decoder);
|
||||
InfraredStatus infrared_encoder_pioneer_encode_repeat(
|
||||
InfraredCommonEncoder* encoder,
|
||||
uint32_t* duration,
|
||||
bool* level);
|
||||
@@ -15,7 +15,6 @@ const InfraredCommonProtocolSpec infrared_protocol_rca = {
|
||||
.min_split_time = INFRARED_RCA_MIN_SPLIT_TIME,
|
||||
},
|
||||
.databit_len[0] = 24,
|
||||
.no_stop_bit = false,
|
||||
.decode = infrared_common_decode_pdwm,
|
||||
.encode = infrared_common_encode_pdwm,
|
||||
.interpret = infrared_decoder_rca_interpret,
|
||||
|
||||
@@ -15,7 +15,6 @@ const InfraredCommonProtocolSpec infrared_protocol_samsung32 = {
|
||||
.min_split_time = INFRARED_SAMSUNG_MIN_SPLIT_TIME,
|
||||
},
|
||||
.databit_len[0] = 32,
|
||||
.no_stop_bit = false,
|
||||
.decode = infrared_common_decode_pdwm,
|
||||
.encode = infrared_common_encode_pdwm,
|
||||
.interpret = infrared_decoder_samsung32_interpret,
|
||||
|
||||
@@ -17,7 +17,6 @@ const InfraredCommonProtocolSpec infrared_protocol_sirc = {
|
||||
.databit_len[0] = 20,
|
||||
.databit_len[1] = 15,
|
||||
.databit_len[2] = 12,
|
||||
.no_stop_bit = true,
|
||||
.decode = infrared_common_decode_pdwm,
|
||||
.encode = infrared_common_encode_pdwm,
|
||||
.interpret = infrared_decoder_sirc_interpret,
|
||||
|
||||
@@ -42,7 +42,7 @@ void infrared_send_raw_ext(
|
||||
bool start_from_mark,
|
||||
uint32_t frequency,
|
||||
float duty_cycle) {
|
||||
furi_assert(timings);
|
||||
furi_check(timings);
|
||||
|
||||
infrared_tx_raw_start_from_mark = start_from_mark;
|
||||
infrared_tx_raw_timings_index = 0;
|
||||
@@ -53,7 +53,7 @@ void infrared_send_raw_ext(
|
||||
furi_hal_infrared_async_tx_start(frequency, duty_cycle);
|
||||
furi_hal_infrared_async_tx_wait_termination();
|
||||
|
||||
furi_assert(!furi_hal_infrared_is_busy());
|
||||
furi_check(!furi_hal_infrared_is_busy());
|
||||
}
|
||||
|
||||
void infrared_send_raw(const uint32_t timings[], uint32_t timings_cnt, bool start_from_mark) {
|
||||
@@ -95,9 +95,9 @@ FuriHalInfraredTxGetDataState
|
||||
}
|
||||
|
||||
void infrared_send(const InfraredMessage* message, int times) {
|
||||
furi_assert(message);
|
||||
furi_assert(times);
|
||||
furi_assert(infrared_is_protocol_valid(message->protocol));
|
||||
furi_check(message);
|
||||
furi_check(times);
|
||||
furi_check(infrared_is_protocol_valid(message->protocol));
|
||||
|
||||
InfraredEncoderHandler* handler = infrared_alloc_encoder();
|
||||
infrared_reset_encoder(handler, message);
|
||||
@@ -113,5 +113,5 @@ void infrared_send(const InfraredMessage* message, int times) {
|
||||
|
||||
infrared_free_encoder(handler);
|
||||
|
||||
furi_assert(!furi_hal_infrared_is_busy());
|
||||
furi_check(!furi_hal_infrared_is_busy());
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <furi_hal_infrared.h>
|
||||
#include <infrared.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -217,12 +217,13 @@ void infrared_worker_rx_set_received_signal_callback(
|
||||
InfraredWorker* instance,
|
||||
InfraredWorkerReceivedSignalCallback callback,
|
||||
void* context) {
|
||||
furi_assert(instance);
|
||||
furi_check(instance);
|
||||
|
||||
instance->rx.received_signal_callback = callback;
|
||||
instance->rx.received_signal_context = context;
|
||||
}
|
||||
|
||||
InfraredWorker* infrared_worker_alloc() {
|
||||
InfraredWorker* infrared_worker_alloc(void) {
|
||||
InfraredWorker* instance = malloc(sizeof(InfraredWorker));
|
||||
|
||||
instance->thread = furi_thread_alloc_ex("InfraredWorker", 2048, NULL, instance);
|
||||
@@ -242,8 +243,8 @@ InfraredWorker* infrared_worker_alloc() {
|
||||
}
|
||||
|
||||
void infrared_worker_free(InfraredWorker* instance) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->state == InfraredWorkerStateIdle);
|
||||
furi_check(instance);
|
||||
furi_check(instance->state == InfraredWorkerStateIdle);
|
||||
|
||||
furi_record_close(RECORD_NOTIFICATION);
|
||||
infrared_free_decoder(instance->infrared_decoder);
|
||||
@@ -255,8 +256,8 @@ void infrared_worker_free(InfraredWorker* instance) {
|
||||
}
|
||||
|
||||
void infrared_worker_rx_start(InfraredWorker* instance) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->state == InfraredWorkerStateIdle);
|
||||
furi_check(instance);
|
||||
furi_check(instance->state == InfraredWorkerStateIdle);
|
||||
|
||||
furi_stream_set_trigger_level(instance->stream, sizeof(LevelDuration));
|
||||
|
||||
@@ -274,8 +275,8 @@ void infrared_worker_rx_start(InfraredWorker* instance) {
|
||||
}
|
||||
|
||||
void infrared_worker_rx_stop(InfraredWorker* instance) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->state == InfraredWorkerStateRunRx);
|
||||
furi_check(instance);
|
||||
furi_check(instance->state == InfraredWorkerStateRunRx);
|
||||
|
||||
furi_hal_infrared_async_rx_set_timeout_isr_callback(NULL, NULL);
|
||||
furi_hal_infrared_async_rx_set_capture_isr_callback(NULL, NULL);
|
||||
@@ -284,15 +285,14 @@ void infrared_worker_rx_stop(InfraredWorker* instance) {
|
||||
furi_thread_flags_set(furi_thread_get_id(instance->thread), INFRARED_WORKER_EXIT);
|
||||
furi_thread_join(instance->thread);
|
||||
|
||||
FuriStatus status = furi_stream_buffer_reset(instance->stream);
|
||||
furi_assert(status == FuriStatusOk);
|
||||
(void)status;
|
||||
furi_check(furi_stream_buffer_reset(instance->stream) == FuriStatusOk);
|
||||
|
||||
instance->state = InfraredWorkerStateIdle;
|
||||
}
|
||||
|
||||
bool infrared_worker_signal_is_decoded(const InfraredWorkerSignal* signal) {
|
||||
furi_assert(signal);
|
||||
furi_check(signal);
|
||||
|
||||
return signal->decoded;
|
||||
}
|
||||
|
||||
@@ -300,33 +300,36 @@ void infrared_worker_get_raw_signal(
|
||||
const InfraredWorkerSignal* signal,
|
||||
const uint32_t** timings,
|
||||
size_t* timings_cnt) {
|
||||
furi_assert(signal);
|
||||
furi_assert(timings);
|
||||
furi_assert(timings_cnt);
|
||||
furi_check(signal);
|
||||
furi_check(timings);
|
||||
furi_check(timings_cnt);
|
||||
|
||||
*timings = signal->raw.timings;
|
||||
*timings_cnt = signal->timings_cnt;
|
||||
}
|
||||
|
||||
const InfraredMessage* infrared_worker_get_decoded_signal(const InfraredWorkerSignal* signal) {
|
||||
furi_assert(signal);
|
||||
furi_check(signal);
|
||||
|
||||
return &signal->message;
|
||||
}
|
||||
|
||||
void infrared_worker_rx_enable_blink_on_receiving(InfraredWorker* instance, bool enable) {
|
||||
furi_assert(instance);
|
||||
furi_check(instance);
|
||||
|
||||
instance->blink_enable = enable;
|
||||
}
|
||||
|
||||
void infrared_worker_rx_enable_signal_decoding(InfraredWorker* instance, bool enable) {
|
||||
furi_assert(instance);
|
||||
furi_check(instance);
|
||||
|
||||
instance->decode_enable = enable;
|
||||
}
|
||||
|
||||
void infrared_worker_tx_start(InfraredWorker* instance) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->state == InfraredWorkerStateIdle);
|
||||
furi_assert(instance->tx.get_signal_callback);
|
||||
furi_check(instance);
|
||||
furi_check(instance->state == InfraredWorkerStateIdle);
|
||||
furi_check(instance->tx.get_signal_callback);
|
||||
|
||||
// size have to be greater than api hal infrared async tx buffer size
|
||||
furi_stream_set_trigger_level(instance->stream, sizeof(InfraredWorkerTiming));
|
||||
@@ -560,7 +563,8 @@ void infrared_worker_tx_set_get_signal_callback(
|
||||
InfraredWorker* instance,
|
||||
InfraredWorkerGetSignalCallback callback,
|
||||
void* context) {
|
||||
furi_assert(instance);
|
||||
furi_check(instance);
|
||||
|
||||
instance->tx.get_signal_callback = callback;
|
||||
instance->tx.get_signal_context = context;
|
||||
}
|
||||
@@ -569,14 +573,15 @@ void infrared_worker_tx_set_signal_sent_callback(
|
||||
InfraredWorker* instance,
|
||||
InfraredWorkerMessageSentCallback callback,
|
||||
void* context) {
|
||||
furi_assert(instance);
|
||||
furi_check(instance);
|
||||
|
||||
instance->tx.message_sent_callback = callback;
|
||||
instance->tx.message_sent_context = context;
|
||||
}
|
||||
|
||||
void infrared_worker_tx_stop(InfraredWorker* instance) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->state != InfraredWorkerStateRunRx);
|
||||
furi_check(instance);
|
||||
furi_check(instance->state != InfraredWorkerStateRunRx);
|
||||
|
||||
furi_thread_flags_set(furi_thread_get_id(instance->thread), INFRARED_WORKER_EXIT);
|
||||
furi_thread_join(instance->thread);
|
||||
@@ -584,15 +589,14 @@ void infrared_worker_tx_stop(InfraredWorker* instance) {
|
||||
furi_hal_infrared_async_tx_set_signal_sent_isr_callback(NULL, NULL);
|
||||
|
||||
instance->signal.timings_cnt = 0;
|
||||
FuriStatus status = furi_stream_buffer_reset(instance->stream);
|
||||
furi_assert(status == FuriStatusOk);
|
||||
(void)status;
|
||||
furi_check(furi_stream_buffer_reset(instance->stream) == FuriStatusOk);
|
||||
|
||||
instance->state = InfraredWorkerStateIdle;
|
||||
}
|
||||
|
||||
void infrared_worker_set_decoded_signal(InfraredWorker* instance, const InfraredMessage* message) {
|
||||
furi_assert(instance);
|
||||
furi_assert(message);
|
||||
furi_check(instance);
|
||||
furi_check(message);
|
||||
|
||||
instance->signal.decoded = true;
|
||||
instance->signal.message = *message;
|
||||
@@ -604,11 +608,12 @@ void infrared_worker_set_raw_signal(
|
||||
size_t timings_cnt,
|
||||
uint32_t frequency,
|
||||
float duty_cycle) {
|
||||
furi_assert(instance);
|
||||
furi_assert(timings);
|
||||
furi_assert(timings_cnt > 0);
|
||||
furi_assert((frequency <= INFRARED_MAX_FREQUENCY) && (frequency >= INFRARED_MIN_FREQUENCY));
|
||||
furi_assert((duty_cycle < 1.0f) && (duty_cycle > 0.0f));
|
||||
furi_check(instance);
|
||||
furi_check(timings);
|
||||
furi_check(timings_cnt > 0);
|
||||
furi_check((frequency <= INFRARED_MAX_FREQUENCY) && (frequency >= INFRARED_MIN_FREQUENCY));
|
||||
furi_check((duty_cycle <= 1.0f) && (duty_cycle > 0.0f));
|
||||
|
||||
size_t max_copy_num = COUNT_OF(instance->signal.raw.timings) - 1;
|
||||
furi_check(timings_cnt <= max_copy_num);
|
||||
|
||||
@@ -623,6 +628,8 @@ void infrared_worker_set_raw_signal(
|
||||
InfraredWorkerGetSignalResponse
|
||||
infrared_worker_tx_get_signal_steady_callback(void* context, InfraredWorker* instance) {
|
||||
UNUSED(context);
|
||||
furi_check(instance);
|
||||
|
||||
InfraredWorkerGetSignalResponse response = instance->tx.steady_signal_sent ?
|
||||
InfraredWorkerGetSignalResponseSame :
|
||||
InfraredWorkerGetSignalResponseNew;
|
||||
|
||||
@@ -37,7 +37,7 @@ typedef void (
|
||||
*
|
||||
* @return just created instance of InfraredWorker
|
||||
*/
|
||||
InfraredWorker* infrared_worker_alloc();
|
||||
InfraredWorker* infrared_worker_alloc(void);
|
||||
|
||||
/** Free InfraredWorker
|
||||
*
|
||||
|
||||
@@ -6,7 +6,10 @@
|
||||
#define LFRFID_DICT_FILETYPE "Flipper RFID key"
|
||||
|
||||
bool lfrfid_dict_file_save(ProtocolDict* dict, ProtocolId protocol, const char* filename) {
|
||||
furi_check(dict);
|
||||
furi_check(protocol != PROTOCOL_NO);
|
||||
furi_check(filename);
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
FlipperFormat* file = flipper_format_file_alloc(storage);
|
||||
size_t data_size = protocol_dict_get_data_size(dict, protocol);
|
||||
@@ -139,6 +142,9 @@ static ProtocolId lfrfid_dict_protocol_fallback(
|
||||
}
|
||||
|
||||
ProtocolId lfrfid_dict_file_load(ProtocolDict* dict, const char* filename) {
|
||||
furi_check(dict);
|
||||
furi_check(filename);
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
FlipperFormat* file = flipper_format_file_alloc(storage);
|
||||
ProtocolId result = PROTOCOL_NO;
|
||||
|
||||
@@ -26,6 +26,8 @@ struct LFRFIDRawFile {
|
||||
};
|
||||
|
||||
LFRFIDRawFile* lfrfid_raw_file_alloc(Storage* storage) {
|
||||
furi_check(storage);
|
||||
|
||||
LFRFIDRawFile* file = malloc(sizeof(LFRFIDRawFile));
|
||||
file->stream = file_stream_alloc(storage);
|
||||
file->buffer = NULL;
|
||||
@@ -33,16 +35,24 @@ LFRFIDRawFile* lfrfid_raw_file_alloc(Storage* storage) {
|
||||
}
|
||||
|
||||
void lfrfid_raw_file_free(LFRFIDRawFile* file) {
|
||||
furi_check(file);
|
||||
|
||||
if(file->buffer) free(file->buffer);
|
||||
stream_free(file->stream);
|
||||
free(file);
|
||||
}
|
||||
|
||||
bool lfrfid_raw_file_open_write(LFRFIDRawFile* file, const char* file_path) {
|
||||
furi_check(file);
|
||||
furi_check(file_path);
|
||||
|
||||
return file_stream_open(file->stream, file_path, FSAM_READ_WRITE, FSOM_CREATE_ALWAYS);
|
||||
}
|
||||
|
||||
bool lfrfid_raw_file_open_read(LFRFIDRawFile* file, const char* file_path) {
|
||||
furi_check(file);
|
||||
furi_check(file_path);
|
||||
|
||||
return file_stream_open(file->stream, file_path, FSAM_READ, FSOM_OPEN_EXISTING);
|
||||
}
|
||||
|
||||
@@ -51,6 +61,8 @@ bool lfrfid_raw_file_write_header(
|
||||
float frequency,
|
||||
float duty_cycle,
|
||||
uint32_t max_buffer_size) {
|
||||
furi_check(file);
|
||||
|
||||
LFRFIDRawFileHeader header = {
|
||||
.magic = LFRFID_RAW_FILE_MAGIC,
|
||||
.version = LFRFID_RAW_FILE_VERSION,
|
||||
@@ -63,6 +75,10 @@ bool lfrfid_raw_file_write_header(
|
||||
}
|
||||
|
||||
bool lfrfid_raw_file_write_buffer(LFRFIDRawFile* file, uint8_t* buffer_data, size_t buffer_size) {
|
||||
furi_check(file);
|
||||
furi_check(buffer_data);
|
||||
furi_check(buffer_size);
|
||||
|
||||
size_t size;
|
||||
size = stream_write(file->stream, (uint8_t*)&buffer_size, sizeof(size_t));
|
||||
if(size != sizeof(size_t)) return false;
|
||||
@@ -74,6 +90,10 @@ bool lfrfid_raw_file_write_buffer(LFRFIDRawFile* file, uint8_t* buffer_data, siz
|
||||
}
|
||||
|
||||
bool lfrfid_raw_file_read_header(LFRFIDRawFile* file, float* frequency, float* duty_cycle) {
|
||||
furi_check(file);
|
||||
furi_check(frequency);
|
||||
furi_check(duty_cycle);
|
||||
|
||||
LFRFIDRawFileHeader header;
|
||||
size_t size = stream_read(file->stream, (uint8_t*)&header, sizeof(LFRFIDRawFileHeader));
|
||||
if(size == sizeof(LFRFIDRawFileHeader)) {
|
||||
@@ -98,6 +118,10 @@ bool lfrfid_raw_file_read_pair(
|
||||
uint32_t* duration,
|
||||
uint32_t* pulse,
|
||||
bool* pass_end) {
|
||||
furi_check(file);
|
||||
furi_check(duration);
|
||||
furi_check(pulse);
|
||||
|
||||
size_t length = 0;
|
||||
if(file->buffer_counter >= file->buffer_size) {
|
||||
if(stream_eof(file->stream)) {
|
||||
|
||||
@@ -58,21 +58,23 @@ typedef enum {
|
||||
static int32_t lfrfid_raw_read_worker_thread(void* thread_context);
|
||||
static int32_t lfrfid_raw_emulate_worker_thread(void* thread_context);
|
||||
|
||||
LFRFIDRawWorker* lfrfid_raw_worker_alloc() {
|
||||
LFRFIDRawWorker* lfrfid_raw_worker_alloc(void) {
|
||||
LFRFIDRawWorker* worker = malloc(sizeof(LFRFIDRawWorker));
|
||||
|
||||
worker->thread = furi_thread_alloc_ex("LfrfidRawWorker", 2048, NULL, worker);
|
||||
|
||||
worker->events = furi_event_flag_alloc(NULL);
|
||||
|
||||
worker->events = furi_event_flag_alloc();
|
||||
worker->file_path = furi_string_alloc();
|
||||
|
||||
return worker;
|
||||
}
|
||||
|
||||
void lfrfid_raw_worker_free(LFRFIDRawWorker* worker) {
|
||||
furi_check(worker);
|
||||
|
||||
furi_thread_free(worker->thread);
|
||||
furi_event_flag_free(worker->events);
|
||||
furi_string_free(worker->file_path);
|
||||
|
||||
free(worker);
|
||||
}
|
||||
|
||||
@@ -83,6 +85,8 @@ void lfrfid_raw_worker_start_read(
|
||||
float duty_cycle,
|
||||
LFRFIDWorkerReadRawCallback callback,
|
||||
void* context) {
|
||||
furi_check(worker);
|
||||
furi_check(file_path);
|
||||
furi_check(furi_thread_get_state(worker->thread) == FuriThreadStateStopped);
|
||||
|
||||
furi_string_set(worker->file_path, file_path);
|
||||
@@ -102,7 +106,10 @@ void lfrfid_raw_worker_start_emulate(
|
||||
const char* file_path,
|
||||
LFRFIDWorkerEmulateRawCallback callback,
|
||||
void* context) {
|
||||
furi_check(worker);
|
||||
furi_check(file_path);
|
||||
furi_check(furi_thread_get_state(worker->thread) == FuriThreadStateStopped);
|
||||
|
||||
furi_string_set(worker->file_path, file_path);
|
||||
worker->emulate_callback = callback;
|
||||
worker->context = context;
|
||||
@@ -111,6 +118,8 @@ void lfrfid_raw_worker_start_emulate(
|
||||
}
|
||||
|
||||
void lfrfid_raw_worker_stop(LFRFIDRawWorker* worker) {
|
||||
furi_check(worker);
|
||||
|
||||
worker->emulate_callback = NULL;
|
||||
worker->context = NULL;
|
||||
worker->read_callback = NULL;
|
||||
|
||||
@@ -15,7 +15,7 @@ typedef struct LFRFIDRawWorker LFRFIDRawWorker;
|
||||
*
|
||||
* @return LFRFIDRawWorker*
|
||||
*/
|
||||
LFRFIDRawWorker* lfrfid_raw_worker_alloc();
|
||||
LFRFIDRawWorker* lfrfid_raw_worker_alloc(void);
|
||||
|
||||
/**
|
||||
* @brief Free a LFRFIDRawWorker instance
|
||||
|
||||
@@ -21,7 +21,7 @@ typedef enum {
|
||||
static int32_t lfrfid_worker_thread(void* thread_context);
|
||||
|
||||
LFRFIDWorker* lfrfid_worker_alloc(ProtocolDict* dict) {
|
||||
furi_assert(dict);
|
||||
furi_check(dict);
|
||||
|
||||
LFRFIDWorker* worker = malloc(sizeof(LFRFIDWorker));
|
||||
worker->mode_index = LFRFIDWorkerIdle;
|
||||
@@ -39,6 +39,8 @@ LFRFIDWorker* lfrfid_worker_alloc(ProtocolDict* dict) {
|
||||
}
|
||||
|
||||
void lfrfid_worker_free(LFRFIDWorker* worker) {
|
||||
furi_check(worker);
|
||||
|
||||
if(worker->raw_filename) {
|
||||
free(worker->raw_filename);
|
||||
}
|
||||
@@ -52,7 +54,9 @@ void lfrfid_worker_read_start(
|
||||
LFRFIDWorkerReadType type,
|
||||
LFRFIDWorkerReadCallback callback,
|
||||
void* context) {
|
||||
furi_assert(worker->mode_index == LFRFIDWorkerIdle);
|
||||
furi_check(worker);
|
||||
furi_check(worker->mode_index == LFRFIDWorkerIdle);
|
||||
|
||||
worker->read_type = type;
|
||||
worker->read_cb = callback;
|
||||
worker->cb_ctx = context;
|
||||
@@ -64,7 +68,7 @@ void lfrfid_worker_write_start(
|
||||
LFRFIDProtocol protocol,
|
||||
LFRFIDWorkerWriteCallback callback,
|
||||
void* context) {
|
||||
furi_assert(worker->mode_index == LFRFIDWorkerIdle);
|
||||
furi_check(worker->mode_index == LFRFIDWorkerIdle);
|
||||
worker->protocol = protocol;
|
||||
worker->write_cb = callback;
|
||||
worker->cb_ctx = context;
|
||||
@@ -84,7 +88,9 @@ void lfrfid_worker_write_and_set_pass_start(
|
||||
}
|
||||
|
||||
void lfrfid_worker_emulate_start(LFRFIDWorker* worker, LFRFIDProtocol protocol) {
|
||||
furi_assert(worker->mode_index == LFRFIDWorkerIdle);
|
||||
furi_check(worker);
|
||||
furi_check(worker->mode_index == LFRFIDWorkerIdle);
|
||||
|
||||
worker->protocol = protocol;
|
||||
furi_thread_flags_set(furi_thread_get_id(worker->thread), LFRFIDEventEmulate);
|
||||
}
|
||||
@@ -103,7 +109,9 @@ void lfrfid_worker_read_raw_start(
|
||||
LFRFIDWorkerReadType type,
|
||||
LFRFIDWorkerReadRawCallback callback,
|
||||
void* context) {
|
||||
furi_assert(worker->mode_index == LFRFIDWorkerIdle);
|
||||
furi_check(worker);
|
||||
furi_check(worker->mode_index == LFRFIDWorkerIdle);
|
||||
|
||||
worker->read_type = type;
|
||||
worker->read_raw_cb = callback;
|
||||
worker->cb_ctx = context;
|
||||
@@ -116,7 +124,9 @@ void lfrfid_worker_emulate_raw_start(
|
||||
const char* filename,
|
||||
LFRFIDWorkerEmulateRawCallback callback,
|
||||
void* context) {
|
||||
furi_assert(worker->mode_index == LFRFIDWorkerIdle);
|
||||
furi_check(worker);
|
||||
furi_check(worker->mode_index == LFRFIDWorkerIdle);
|
||||
|
||||
lfrfid_worker_set_filename(worker, filename);
|
||||
worker->emulate_raw_cb = callback;
|
||||
worker->cb_ctx = context;
|
||||
@@ -124,14 +134,20 @@ void lfrfid_worker_emulate_raw_start(
|
||||
}
|
||||
|
||||
void lfrfid_worker_stop(LFRFIDWorker* worker) {
|
||||
furi_check(worker);
|
||||
|
||||
furi_thread_flags_set(furi_thread_get_id(worker->thread), LFRFIDEventStopMode);
|
||||
}
|
||||
|
||||
void lfrfid_worker_start_thread(LFRFIDWorker* worker) {
|
||||
furi_check(worker);
|
||||
|
||||
furi_thread_start(worker->thread);
|
||||
}
|
||||
|
||||
void lfrfid_worker_stop_thread(LFRFIDWorker* worker) {
|
||||
furi_check(worker);
|
||||
|
||||
furi_thread_flags_set(furi_thread_get_id(worker->thread), LFRFIDEventStopThread);
|
||||
furi_thread_join(worker->thread);
|
||||
}
|
||||
|
||||
+39
-44
@@ -1,5 +1,4 @@
|
||||
/**
|
||||
* @file lfrfid_worker.h
|
||||
/** @file lfrfid_worker.h
|
||||
*
|
||||
* LFRFID worker
|
||||
*/
|
||||
@@ -54,37 +53,35 @@ typedef void (*LFRFIDWorkerEmulateRawCallback)(LFRFIDWorkerEmulateRawResult resu
|
||||
|
||||
typedef struct LFRFIDWorker LFRFIDWorker;
|
||||
|
||||
/**
|
||||
* Allocate LF-RFID worker
|
||||
/** Allocate LF-RFID worker
|
||||
* @return LFRFIDWorker*
|
||||
*/
|
||||
LFRFIDWorker* lfrfid_worker_alloc(ProtocolDict* dict);
|
||||
|
||||
/**
|
||||
* Free LF-RFID worker
|
||||
* @param worker
|
||||
/** Free LF-RFID worker
|
||||
*
|
||||
* @param worker The worker
|
||||
*/
|
||||
void lfrfid_worker_free(LFRFIDWorker* worker);
|
||||
|
||||
/**
|
||||
* Start LF-RFID worker thread
|
||||
* @param worker
|
||||
/** Start LF-RFID worker thread
|
||||
*
|
||||
* @param worker The worker
|
||||
*/
|
||||
void lfrfid_worker_start_thread(LFRFIDWorker* worker);
|
||||
|
||||
/**
|
||||
* Stop LF-RFID worker thread
|
||||
* @param worker
|
||||
/** Stop LF-RFID worker thread
|
||||
*
|
||||
* @param worker The worker
|
||||
*/
|
||||
void lfrfid_worker_stop_thread(LFRFIDWorker* worker);
|
||||
|
||||
/**
|
||||
* @brief Start read mode
|
||||
*
|
||||
* @param worker
|
||||
* @param type
|
||||
* @param callback
|
||||
* @param context
|
||||
/** Start read mode
|
||||
*
|
||||
* @param worker The worker
|
||||
* @param type The type
|
||||
* @param callback The callback
|
||||
* @param context The context
|
||||
*/
|
||||
void lfrfid_worker_read_start(
|
||||
LFRFIDWorker* worker,
|
||||
@@ -92,13 +89,12 @@ void lfrfid_worker_read_start(
|
||||
LFRFIDWorkerReadCallback callback,
|
||||
void* context);
|
||||
|
||||
/**
|
||||
* @brief Start write mode
|
||||
*
|
||||
* @param worker
|
||||
* @param protocol
|
||||
* @param callback
|
||||
* @param context
|
||||
/** Start write mode
|
||||
*
|
||||
* @param worker The worker
|
||||
* @param protocol The protocol
|
||||
* @param callback The callback
|
||||
* @param context The context
|
||||
*/
|
||||
void lfrfid_worker_write_start(
|
||||
LFRFIDWorker* worker,
|
||||
@@ -126,14 +122,13 @@ void lfrfid_worker_write_and_set_pass_start(
|
||||
*/
|
||||
void lfrfid_worker_emulate_start(LFRFIDWorker* worker, LFRFIDProtocol protocol);
|
||||
|
||||
/**
|
||||
* @brief Start raw read mode
|
||||
*
|
||||
* @param worker
|
||||
* @param filename
|
||||
* @param type
|
||||
* @param callback
|
||||
* @param context
|
||||
/** Start raw read mode
|
||||
*
|
||||
* @param worker The worker
|
||||
* @param filename The filename
|
||||
* @param type The type
|
||||
* @param callback The callback
|
||||
* @param context The context
|
||||
*/
|
||||
void lfrfid_worker_read_raw_start(
|
||||
LFRFIDWorker* worker,
|
||||
@@ -142,12 +137,12 @@ void lfrfid_worker_read_raw_start(
|
||||
LFRFIDWorkerReadRawCallback callback,
|
||||
void* context);
|
||||
|
||||
/**
|
||||
* Emulate raw read mode
|
||||
* @param worker
|
||||
* @param filename
|
||||
* @param callback
|
||||
* @param context
|
||||
/** Emulate raw read mode
|
||||
*
|
||||
* @param worker The worker
|
||||
* @param filename The filename
|
||||
* @param callback The callback
|
||||
* @param context The context
|
||||
*/
|
||||
void lfrfid_worker_emulate_raw_start(
|
||||
LFRFIDWorker* worker,
|
||||
@@ -155,9 +150,9 @@ void lfrfid_worker_emulate_raw_start(
|
||||
LFRFIDWorkerEmulateRawCallback callback,
|
||||
void* context);
|
||||
|
||||
/**
|
||||
* Stop all modes
|
||||
* @param worker
|
||||
/** Stop all modes
|
||||
*
|
||||
* @param worker The worker
|
||||
*/
|
||||
void lfrfid_worker_stop(LFRFIDWorker* worker);
|
||||
|
||||
|
||||
@@ -164,7 +164,8 @@ void protocol_awid_render_data(ProtocolAwid* protocol, FuriString* result) {
|
||||
uint8_t* decoded_data = protocol->data;
|
||||
uint8_t format_length = decoded_data[0];
|
||||
|
||||
furi_string_cat_printf(result, "Format: %d\r\n", format_length);
|
||||
furi_string_printf(result, "Format: %hhu\n", format_length);
|
||||
|
||||
if(format_length == 26) {
|
||||
uint8_t facility;
|
||||
bit_lib_copy_bits(&facility, 0, 8, decoded_data, 9);
|
||||
@@ -172,13 +173,17 @@ void protocol_awid_render_data(ProtocolAwid* protocol, FuriString* result) {
|
||||
uint16_t card_id;
|
||||
bit_lib_copy_bits((uint8_t*)&card_id, 8, 8, decoded_data, 17);
|
||||
bit_lib_copy_bits((uint8_t*)&card_id, 0, 8, decoded_data, 25);
|
||||
furi_string_cat_printf(result, "Facility: %d\r\n", facility);
|
||||
furi_string_cat_printf(result, "Card: %d", card_id);
|
||||
furi_string_cat_printf(
|
||||
result,
|
||||
"FC: %hhu\n"
|
||||
"Card: %hu",
|
||||
facility,
|
||||
card_id);
|
||||
} else {
|
||||
// print 66 bits as hex
|
||||
furi_string_cat_printf(result, "Data: ");
|
||||
for(size_t i = 0; i < AWID_DECODED_DATA_SIZE; i++) {
|
||||
furi_string_cat_printf(result, "%02X", decoded_data[i]);
|
||||
furi_string_cat_printf(result, "%02hhX", decoded_data[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -187,7 +192,8 @@ void protocol_awid_render_brief_data(ProtocolAwid* protocol, FuriString* result)
|
||||
uint8_t* decoded_data = protocol->data;
|
||||
uint8_t format_length = decoded_data[0];
|
||||
|
||||
furi_string_cat_printf(result, "Format: %d\r\n", format_length);
|
||||
furi_string_printf(result, "Format: %hhu", format_length);
|
||||
|
||||
if(format_length == 26) {
|
||||
uint8_t facility;
|
||||
bit_lib_copy_bits(&facility, 0, 8, decoded_data, 9);
|
||||
@@ -195,9 +201,14 @@ void protocol_awid_render_brief_data(ProtocolAwid* protocol, FuriString* result)
|
||||
uint16_t card_id;
|
||||
bit_lib_copy_bits((uint8_t*)&card_id, 8, 8, decoded_data, 17);
|
||||
bit_lib_copy_bits((uint8_t*)&card_id, 0, 8, decoded_data, 25);
|
||||
furi_string_cat_printf(result, "ID: %03u,%05u", facility, card_id);
|
||||
furi_string_cat_printf(
|
||||
result,
|
||||
"; FC: %hhu\n"
|
||||
"Card: %hu",
|
||||
facility,
|
||||
card_id);
|
||||
} else {
|
||||
furi_string_cat_printf(result, "Data: unknown");
|
||||
furi_string_cat(result, "\nData: Unknown");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -252,4 +263,4 @@ const ProtocolBase protocol_awid = {
|
||||
.render_data = (ProtocolRenderData)protocol_awid_render_data,
|
||||
.render_brief_data = (ProtocolRenderData)protocol_awid_render_brief_data,
|
||||
.write_data = (ProtocolWriteData)protocol_awid_write_data,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -335,8 +335,8 @@ bool protocol_em4100_write_data(ProtocolEM4100* protocol, void* data) {
|
||||
request->t5577.block[0] =
|
||||
(LFRFID_T5577_MODULATION_MANCHESTER | protocol_em4100_get_t5577_bitrate(protocol) |
|
||||
(2 << LFRFID_T5577_MAXBLOCK_SHIFT));
|
||||
request->t5577.block[1] = protocol->encoded_data;
|
||||
request->t5577.block[2] = protocol->encoded_data >> 32;
|
||||
request->t5577.block[1] = protocol->encoded_data >> 32;
|
||||
request->t5577.block[2] = protocol->encoded_data;
|
||||
request->t5577.blocks_to_write = 3;
|
||||
result = true;
|
||||
}
|
||||
@@ -347,7 +347,8 @@ void protocol_em4100_render_data(ProtocolEM4100* protocol, FuriString* result) {
|
||||
uint8_t* data = protocol->data;
|
||||
furi_string_printf(
|
||||
result,
|
||||
"FC: %03u, Card: %05u\n(RF/%u)",
|
||||
"FC: %03u\n"
|
||||
"Card: %05hu (RF/%hhu)",
|
||||
data[2],
|
||||
(uint16_t)((data[3] << 8) | (data[4])),
|
||||
protocol->clock_per_bit);
|
||||
|
||||
@@ -217,14 +217,10 @@ void protocol_fdx_a_render_data(ProtocolFDXA* protocol, FuriString* result) {
|
||||
|
||||
furi_string_printf(
|
||||
result,
|
||||
"ID: %02X%02X%02X%02X%02X\r\n"
|
||||
"Parity: %s",
|
||||
data[0],
|
||||
data[1],
|
||||
data[2],
|
||||
data[3],
|
||||
data[4],
|
||||
parity_sum == 0 ? "+" : "-");
|
||||
"ID: %010llX\n"
|
||||
"Parity: %c",
|
||||
bit_lib_get_bits_64(data, 0, 40),
|
||||
parity_sum == 0 ? '+' : '-');
|
||||
};
|
||||
|
||||
const ProtocolBase protocol_fdx_a = {
|
||||
@@ -249,4 +245,4 @@ const ProtocolBase protocol_fdx_a = {
|
||||
.render_data = (ProtocolRenderData)protocol_fdx_a_render_data,
|
||||
.render_brief_data = (ProtocolRenderData)protocol_fdx_a_render_data,
|
||||
.write_data = (ProtocolWriteData)protocol_fdx_a_write_data,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -288,21 +288,33 @@ void protocol_fdx_b_render_data(ProtocolFDXB* protocol, FuriString* result) {
|
||||
uint8_t replacement_number = bit_lib_get_bits(protocol->data, 60, 3);
|
||||
bool animal_flag = bit_lib_get_bit(protocol->data, 63);
|
||||
|
||||
furi_string_printf(result, "ID: %03u-%012llu\r\n", country_code, national_code);
|
||||
furi_string_cat_printf(result, "Animal: %s, ", animal_flag ? "Yes" : "No");
|
||||
furi_string_printf(
|
||||
result,
|
||||
"ID: %03hu-%012llu\n"
|
||||
"Country Code: %hu\n"
|
||||
"Temperature: ",
|
||||
country_code,
|
||||
national_code,
|
||||
country_code);
|
||||
|
||||
float temperature;
|
||||
if(protocol_fdx_b_get_temp(protocol->data, &temperature)) {
|
||||
float temperature_c = (temperature - 32) / 1.8;
|
||||
furi_string_cat_printf(
|
||||
result, "T: %.2fF, %.2fC\r\n", (double)temperature, (double)temperature_c);
|
||||
if(furi_hal_rtc_get_locale_units() == FuriHalRtcLocaleUnitsMetric) {
|
||||
float temperature_c = (temperature - 32.0f) / 1.8f;
|
||||
furi_string_cat_printf(result, "%.2fC", (double)temperature_c);
|
||||
} else {
|
||||
furi_string_cat_printf(result, "%.2fF", (double)temperature);
|
||||
}
|
||||
} else {
|
||||
furi_string_cat_printf(result, "T: ---\r\n");
|
||||
furi_string_cat(result, "---");
|
||||
}
|
||||
|
||||
furi_string_cat_printf(
|
||||
result,
|
||||
"Bits: %X-%X-%X-%X-%X",
|
||||
"\n"
|
||||
"Animal: %s\n"
|
||||
"Bits: %hhX-%hhX-%hhX-%hhX-%hhX",
|
||||
animal_flag ? "Yes" : "No",
|
||||
block_status,
|
||||
rudi_bit,
|
||||
reserved,
|
||||
@@ -317,21 +329,24 @@ void protocol_fdx_b_render_brief_data(ProtocolFDXB* protocol, FuriString* result
|
||||
// 10 bit of country code
|
||||
uint16_t country_code = protocol_fdx_b_get_country_code(protocol->data);
|
||||
|
||||
bool animal_flag = bit_lib_get_bit(protocol->data, 63);
|
||||
|
||||
furi_string_printf(result, "ID: %03u-%012llu\r\n", country_code, national_code);
|
||||
furi_string_cat_printf(result, "Animal: %s, ", animal_flag ? "Yes" : "No");
|
||||
furi_string_printf(
|
||||
result,
|
||||
"ID: %03hu-%012llu\n"
|
||||
"Country: %hu; Temp.: ",
|
||||
country_code,
|
||||
national_code,
|
||||
country_code);
|
||||
|
||||
float temperature;
|
||||
if(protocol_fdx_b_get_temp(protocol->data, &temperature)) {
|
||||
if(furi_hal_rtc_get_locale_units() == FuriHalRtcLocaleUnitsMetric) {
|
||||
float temperature_c = (temperature - 32.0f) / 1.8f;
|
||||
furi_string_cat_printf(result, "T: %.2fC", (double)temperature_c);
|
||||
furi_string_cat_printf(result, "%.2fC", (double)temperature_c);
|
||||
} else {
|
||||
furi_string_cat_printf(result, "T: %.2fF", (double)temperature);
|
||||
furi_string_cat_printf(result, "%.2fF", (double)temperature);
|
||||
}
|
||||
} else {
|
||||
furi_string_cat_printf(result, "T: ---");
|
||||
furi_string_cat(result, "---");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -380,4 +395,4 @@ const ProtocolBase protocol_fdx_b = {
|
||||
.render_data = (ProtocolRenderData)protocol_fdx_b_render_data,
|
||||
.render_brief_data = (ProtocolRenderData)protocol_fdx_b_render_brief_data,
|
||||
.write_data = (ProtocolWriteData)protocol_fdx_b_write_data,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -268,17 +268,44 @@ bool protocol_gallagher_write_data(ProtocolGallagher* protocol, void* data) {
|
||||
return result;
|
||||
};
|
||||
|
||||
void protocol_gallagher_render_data(ProtocolGallagher* protocol, FuriString* result) {
|
||||
UNUSED(protocol);
|
||||
uint8_t rc = bit_lib_get_bits(protocol->data, 0, 4);
|
||||
uint8_t il = bit_lib_get_bits(protocol->data, 4, 4);
|
||||
static void protocol_gallagher_render_data_internal(
|
||||
ProtocolGallagher* protocol,
|
||||
FuriString* result,
|
||||
bool brief) {
|
||||
uint8_t region = bit_lib_get_bits(protocol->data, 0, 4);
|
||||
uint8_t issue_level = bit_lib_get_bits(protocol->data, 4, 4);
|
||||
uint32_t fc = bit_lib_get_bits_32(protocol->data, 8, 24);
|
||||
uint32_t card_id = bit_lib_get_bits_32(protocol->data, 32, 32);
|
||||
|
||||
furi_string_cat_printf(result, "Region: %u, Issue Level: %u\r\n", rc, il);
|
||||
furi_string_cat_printf(result, "FC: %lu, C: %lu\r\n", fc, card_id);
|
||||
if(brief) {
|
||||
furi_string_printf(
|
||||
result,
|
||||
"FC: %lu\n"
|
||||
"Card: %lu",
|
||||
fc,
|
||||
card_id);
|
||||
} else {
|
||||
furi_string_printf(
|
||||
result,
|
||||
"FC: %lu\n"
|
||||
"Card: %lu\n"
|
||||
"Region: %u\n"
|
||||
"Issue Level: %u",
|
||||
fc,
|
||||
card_id,
|
||||
region,
|
||||
issue_level);
|
||||
}
|
||||
};
|
||||
|
||||
void protocol_gallagher_render_data(ProtocolGallagher* protocol, FuriString* result) {
|
||||
protocol_gallagher_render_data_internal(protocol, result, false);
|
||||
}
|
||||
|
||||
void protocol_gallagher_render_brief_data(ProtocolGallagher* protocol, FuriString* result) {
|
||||
protocol_gallagher_render_data_internal(protocol, result, true);
|
||||
}
|
||||
|
||||
const ProtocolBase protocol_gallagher = {
|
||||
.name = "Gallagher",
|
||||
.manufacturer = "Gallagher",
|
||||
@@ -299,6 +326,6 @@ const ProtocolBase protocol_gallagher = {
|
||||
.yield = (ProtocolEncoderYield)protocol_gallagher_encoder_yield,
|
||||
},
|
||||
.render_data = (ProtocolRenderData)protocol_gallagher_render_data,
|
||||
.render_brief_data = (ProtocolRenderData)protocol_gallagher_render_data,
|
||||
.render_brief_data = (ProtocolRenderData)protocol_gallagher_render_brief_data,
|
||||
.write_data = (ProtocolWriteData)protocol_gallagher_write_data,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -359,8 +359,8 @@ void protocol_h10301_render_data(ProtocolH10301* protocol, FuriString* result) {
|
||||
uint8_t* data = protocol->data;
|
||||
furi_string_printf(
|
||||
result,
|
||||
"FC: %u\r\n"
|
||||
"Card: %u",
|
||||
"FC: %hhu\n"
|
||||
"Card: %hu",
|
||||
data[0],
|
||||
(uint16_t)((data[1] << 8) | (data[2])));
|
||||
};
|
||||
@@ -387,4 +387,4 @@ const ProtocolBase protocol_h10301 = {
|
||||
.render_data = (ProtocolRenderData)protocol_h10301_render_data,
|
||||
.render_brief_data = (ProtocolRenderData)protocol_h10301_render_data,
|
||||
.write_data = (ProtocolWriteData)protocol_h10301_write_data,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -193,9 +193,13 @@ bool protocol_hid_ex_generic_write_data(ProtocolHIDEx* protocol, void* data) {
|
||||
};
|
||||
|
||||
void protocol_hid_ex_generic_render_data(ProtocolHIDEx* protocol, FuriString* result) {
|
||||
// TODO FL-3518: parser and render functions
|
||||
UNUSED(protocol);
|
||||
furi_string_printf(result, "Generic HID Extended\r\nData: Unknown");
|
||||
|
||||
// TODO FL-3518: parser and render functions
|
||||
furi_string_set(
|
||||
result,
|
||||
"Type: Generic HID Extended\n"
|
||||
"Data: Unknown");
|
||||
};
|
||||
|
||||
const ProtocolBase protocol_hid_ex_generic = {
|
||||
@@ -220,4 +224,4 @@ const ProtocolBase protocol_hid_ex_generic = {
|
||||
.render_data = (ProtocolRenderData)protocol_hid_ex_generic_render_data,
|
||||
.render_brief_data = (ProtocolRenderData)protocol_hid_ex_generic_render_data,
|
||||
.write_data = (ProtocolWriteData)protocol_hid_ex_generic_write_data,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -245,7 +245,7 @@ void protocol_hid_generic_render_data(ProtocolHID* protocol, FuriString* result)
|
||||
if(protocol_size == HID_PROTOCOL_SIZE_UNKNOWN) {
|
||||
furi_string_printf(
|
||||
result,
|
||||
"Generic HID Proximity\r\n"
|
||||
"Generic HID Proximity\n"
|
||||
"Data: %02X%02X%02X%02X%02X%X",
|
||||
protocol->data[0],
|
||||
protocol->data[1],
|
||||
@@ -256,7 +256,7 @@ void protocol_hid_generic_render_data(ProtocolHID* protocol, FuriString* result)
|
||||
} else {
|
||||
furi_string_printf(
|
||||
result,
|
||||
"%hhu-bit HID Proximity\r\n"
|
||||
"%hhu-bit HID Proximity\n"
|
||||
"Data: ",
|
||||
protocol_size);
|
||||
protocol_hid_generic_string_cat_protocol_bits(protocol, protocol_size, result);
|
||||
|
||||
@@ -205,26 +205,16 @@ static uint32_t get_card(const uint8_t* data) {
|
||||
return cn;
|
||||
}
|
||||
|
||||
void protocol_idteck_render_data_internal(ProtocolIdteck* protocol, FuriString* result, bool brief) {
|
||||
void protocol_idteck_render_data(ProtocolIdteck* protocol, FuriString* result) {
|
||||
const uint32_t fc = get_fc(protocol->data);
|
||||
const uint32_t card = get_card(protocol->data);
|
||||
|
||||
if(brief) {
|
||||
furi_string_printf(result, "FC: %08lX\r\nCard: %08lX", fc, card);
|
||||
} else {
|
||||
furi_string_printf(
|
||||
result,
|
||||
"FC: %08lX\r\n"
|
||||
"Card: %08lX\r\n",
|
||||
fc,
|
||||
card);
|
||||
}
|
||||
}
|
||||
void protocol_idteck_render_data(ProtocolIdteck* protocol, FuriString* result) {
|
||||
protocol_idteck_render_data_internal(protocol, result, false);
|
||||
}
|
||||
void protocol_idteck_render_brief_data(ProtocolIdteck* protocol, FuriString* result) {
|
||||
protocol_idteck_render_data_internal(protocol, result, true);
|
||||
furi_string_printf(
|
||||
result,
|
||||
"FC: %08lX\n"
|
||||
"Card: %08lX",
|
||||
fc,
|
||||
card);
|
||||
}
|
||||
|
||||
bool protocol_idteck_write_data(ProtocolIdteck* protocol, void* data) {
|
||||
@@ -264,6 +254,6 @@ const ProtocolBase protocol_idteck = {
|
||||
.yield = (ProtocolEncoderYield)protocol_idteck_encoder_yield,
|
||||
},
|
||||
.render_data = (ProtocolRenderData)protocol_idteck_render_data,
|
||||
.render_brief_data = (ProtocolRenderData)protocol_idteck_render_brief_data,
|
||||
.render_brief_data = (ProtocolRenderData)protocol_idteck_render_data,
|
||||
.write_data = (ProtocolWriteData)protocol_idteck_write_data,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -289,22 +289,21 @@ void protocol_indala26_render_data_internal(
|
||||
if(brief) {
|
||||
furi_string_printf(
|
||||
result,
|
||||
"FC: %u\r\nCard: %u, Parity:%s%s",
|
||||
"FC: %u\n"
|
||||
"Card: %u",
|
||||
fc,
|
||||
card,
|
||||
(checksum_correct ? "+" : "-"),
|
||||
(wiegand_correct ? "+" : "-"));
|
||||
card);
|
||||
} else {
|
||||
furi_string_printf(
|
||||
result,
|
||||
"FC: %u\r\n"
|
||||
"Card: %u\r\n"
|
||||
"Checksum: %s\r\n"
|
||||
"W26 Parity: %s",
|
||||
"FC: %u\n"
|
||||
"Card: %u\n"
|
||||
"Parity: %c\n"
|
||||
"Checksum: %c",
|
||||
fc,
|
||||
card,
|
||||
(checksum_correct ? "+" : "-"),
|
||||
(wiegand_correct ? "+" : "-"));
|
||||
(wiegand_correct ? '+' : '-'),
|
||||
(checksum_correct ? '+' : '-'));
|
||||
}
|
||||
}
|
||||
void protocol_indala26_render_data(ProtocolIndala* protocol, FuriString* result) {
|
||||
|
||||
@@ -236,9 +236,9 @@ void protocol_io_prox_xsf_render_data(ProtocolIOProxXSF* protocol, FuriString* r
|
||||
uint8_t* data = protocol->data;
|
||||
furi_string_printf(
|
||||
result,
|
||||
"FC: %u\r\n"
|
||||
"VС: %u\r\n"
|
||||
"Card: %u",
|
||||
"FC: %hhu\n"
|
||||
"V: %hhu\n"
|
||||
"Card: %hu",
|
||||
data[0],
|
||||
data[1],
|
||||
(uint16_t)((data[2] << 8) | (data[3])));
|
||||
@@ -248,8 +248,8 @@ void protocol_io_prox_xsf_render_brief_data(ProtocolIOProxXSF* protocol, FuriStr
|
||||
uint8_t* data = protocol->data;
|
||||
furi_string_printf(
|
||||
result,
|
||||
"FC: %u, VС: %u\r\n"
|
||||
"Card: %u",
|
||||
"FC: %hhu, V: %hhu\n"
|
||||
"Card: %hu",
|
||||
data[0],
|
||||
data[1],
|
||||
(uint16_t)((data[2] << 8) | (data[3])));
|
||||
@@ -298,4 +298,4 @@ const ProtocolBase protocol_io_prox_xsf = {
|
||||
.render_data = (ProtocolRenderData)protocol_io_prox_xsf_render_data,
|
||||
.render_brief_data = (ProtocolRenderData)protocol_io_prox_xsf_render_brief_data,
|
||||
.write_data = (ProtocolWriteData)protocol_io_prox_xsf_write_data,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -162,7 +162,7 @@ LevelDuration protocol_jablotron_encoder_yield(ProtocolJablotron* protocol) {
|
||||
|
||||
void protocol_jablotron_render_data(ProtocolJablotron* protocol, FuriString* result) {
|
||||
uint64_t id = protocol_jablotron_card_id(protocol->data);
|
||||
furi_string_printf(result, "ID: %llX\r\n", id);
|
||||
furi_string_printf(result, "Card: %llX", id);
|
||||
};
|
||||
|
||||
bool protocol_jablotron_write_data(ProtocolJablotron* protocol, void* data) {
|
||||
@@ -208,4 +208,4 @@ const ProtocolBase protocol_jablotron = {
|
||||
.render_data = (ProtocolRenderData)protocol_jablotron_render_data,
|
||||
.render_brief_data = (ProtocolRenderData)protocol_jablotron_render_data,
|
||||
.write_data = (ProtocolWriteData)protocol_jablotron_write_data,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -212,13 +212,40 @@ LevelDuration protocol_keri_encoder_yield(ProtocolKeri* protocol) {
|
||||
return level_duration;
|
||||
};
|
||||
|
||||
void protocol_keri_render_data(ProtocolKeri* protocol, FuriString* result) {
|
||||
static void
|
||||
protocol_keri_render_data_internal(ProtocolKeri* protocol, FuriString* result, bool brief) {
|
||||
uint32_t data = bit_lib_get_bits_32(protocol->data, 0, 32);
|
||||
uint32_t internal_id = data & 0x7FFFFFFF;
|
||||
uint32_t fc = 0;
|
||||
uint32_t cn = 0;
|
||||
protocol_keri_descramble(&fc, &cn, &data);
|
||||
furi_string_printf(result, "Internal ID: %lu\r\nFC: %lu, Card: %lu\r\n", internal_id, fc, cn);
|
||||
|
||||
if(brief) {
|
||||
furi_string_printf(
|
||||
result,
|
||||
"Internal ID: %lu\n"
|
||||
"FC: %lu; Card: %lu",
|
||||
internal_id,
|
||||
fc,
|
||||
cn);
|
||||
} else {
|
||||
furi_string_printf(
|
||||
result,
|
||||
"Internal ID: %lu\n"
|
||||
"FC: %lu\n"
|
||||
"Card: %lu",
|
||||
internal_id,
|
||||
fc,
|
||||
cn);
|
||||
}
|
||||
}
|
||||
|
||||
void protocol_keri_render_data(ProtocolKeri* protocol, FuriString* result) {
|
||||
protocol_keri_render_data_internal(protocol, result, false);
|
||||
}
|
||||
|
||||
void protocol_keri_render_brief_data(ProtocolKeri* protocol, FuriString* result) {
|
||||
protocol_keri_render_data_internal(protocol, result, true);
|
||||
}
|
||||
|
||||
bool protocol_keri_write_data(ProtocolKeri* protocol, void* data) {
|
||||
@@ -262,6 +289,6 @@ const ProtocolBase protocol_keri = {
|
||||
.yield = (ProtocolEncoderYield)protocol_keri_encoder_yield,
|
||||
},
|
||||
.render_data = (ProtocolRenderData)protocol_keri_render_data,
|
||||
.render_brief_data = (ProtocolRenderData)protocol_keri_render_data,
|
||||
.render_brief_data = (ProtocolRenderData)protocol_keri_render_brief_data,
|
||||
.write_data = (ProtocolWriteData)protocol_keri_write_data,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -263,7 +263,10 @@ LevelDuration protocol_nexwatch_encoder_yield(ProtocolNexwatch* protocol) {
|
||||
return level_duration;
|
||||
};
|
||||
|
||||
void protocol_nexwatch_render_data(ProtocolNexwatch* protocol, FuriString* result) {
|
||||
static void protocol_nexwatch_render_data_internal(
|
||||
ProtocolNexwatch* protocol,
|
||||
FuriString* result,
|
||||
bool brief) {
|
||||
uint32_t id = 0;
|
||||
uint32_t scrambled = bit_lib_get_bits_32(protocol->data, 8, 32);
|
||||
protocol_nexwatch_descramble(&id, &scrambled);
|
||||
@@ -272,13 +275,42 @@ void protocol_nexwatch_render_data(ProtocolNexwatch* protocol, FuriString* resul
|
||||
uint8_t mode = bit_lib_get_bits(protocol->data, 40, 4);
|
||||
uint8_t parity = bit_lib_get_bits(protocol->data, 44, 4);
|
||||
uint8_t chk = bit_lib_get_bits(protocol->data, 48, 8);
|
||||
for(m_idx = 0; m_idx < 3; m_idx++) {
|
||||
|
||||
for(m_idx = 0; m_idx < COUNT_OF(magic_items); m_idx++) {
|
||||
magic_items[m_idx].chk = protocol_nexwatch_checksum(magic_items[m_idx].magic, id, parity);
|
||||
if(magic_items[m_idx].chk == chk) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
furi_string_printf(result, "ID: %lu, M:%u\r\nType: %s\r\n", id, mode, magic_items[m_idx].desc);
|
||||
|
||||
const char* type = m_idx < COUNT_OF(magic_items) ? magic_items[m_idx].desc : "Unknown";
|
||||
|
||||
if(brief) {
|
||||
furi_string_printf(
|
||||
result,
|
||||
"ID: %lu\n"
|
||||
"Mode: %hhu; Type: %s",
|
||||
id,
|
||||
mode,
|
||||
type);
|
||||
} else {
|
||||
furi_string_printf(
|
||||
result,
|
||||
"ID: %lu\n"
|
||||
"Mode: %hhu\n"
|
||||
"Type: %s",
|
||||
id,
|
||||
mode,
|
||||
type);
|
||||
}
|
||||
}
|
||||
|
||||
void protocol_nexwatch_render_data(ProtocolNexwatch* protocol, FuriString* result) {
|
||||
protocol_nexwatch_render_data_internal(protocol, result, false);
|
||||
}
|
||||
|
||||
void protocol_nexwatch_render_brief_data(ProtocolNexwatch* protocol, FuriString* result) {
|
||||
protocol_nexwatch_render_data_internal(protocol, result, true);
|
||||
}
|
||||
|
||||
bool protocol_nexwatch_write_data(ProtocolNexwatch* protocol, void* data) {
|
||||
@@ -318,6 +350,6 @@ const ProtocolBase protocol_nexwatch = {
|
||||
.yield = (ProtocolEncoderYield)protocol_nexwatch_encoder_yield,
|
||||
},
|
||||
.render_data = (ProtocolRenderData)protocol_nexwatch_render_data,
|
||||
.render_brief_data = (ProtocolRenderData)protocol_nexwatch_render_data,
|
||||
.render_brief_data = (ProtocolRenderData)protocol_nexwatch_render_brief_data,
|
||||
.write_data = (ProtocolWriteData)protocol_nexwatch_write_data,
|
||||
};
|
||||
|
||||
@@ -202,8 +202,7 @@ bool protocol_pac_stanley_write_data(ProtocolPACStanley* protocol, void* data) {
|
||||
}
|
||||
|
||||
void protocol_pac_stanley_render_data(ProtocolPACStanley* protocol, FuriString* result) {
|
||||
uint8_t* data = protocol->data;
|
||||
furi_string_printf(result, "CIN: %02X%02X%02X%02X", data[0], data[1], data[2], data[3]);
|
||||
furi_string_printf(result, "CIN: %08lX", bit_lib_get_bits_32(protocol->data, 0, 32));
|
||||
}
|
||||
|
||||
const ProtocolBase protocol_pac_stanley = {
|
||||
|
||||
@@ -171,10 +171,20 @@ void protocol_paradox_render_data(ProtocolParadox* protocol, FuriString* result)
|
||||
uint8_t card_crc = bit_lib_get_bits_16(decoded_data, 34, 8);
|
||||
uint8_t calc_crc = protocol_paradox_calculate_checksum(fc, card_id);
|
||||
|
||||
furi_string_cat_printf(result, "Facility: %u\r\n", fc);
|
||||
furi_string_cat_printf(result, "Card: %u\r\n", card_id);
|
||||
furi_string_cat_printf(result, "CRC: %u Calc CRC: %u\r\n", card_crc, calc_crc);
|
||||
if(card_crc != calc_crc) furi_string_cat_printf(result, "CRC Mismatch, Invalid Card!\r\n");
|
||||
furi_string_printf(
|
||||
result,
|
||||
"FC: %hhu\n"
|
||||
"Card: %hu\n"
|
||||
"CRC: %hhu\n"
|
||||
"Calc CRC: %hhu",
|
||||
fc,
|
||||
card_id,
|
||||
card_crc,
|
||||
calc_crc);
|
||||
|
||||
if(card_crc != calc_crc) {
|
||||
furi_string_cat(result, "\nCRC Mismatch, Invalid Card!");
|
||||
}
|
||||
};
|
||||
|
||||
void protocol_paradox_render_brief_data(ProtocolParadox* protocol, FuriString* result) {
|
||||
@@ -185,11 +195,10 @@ void protocol_paradox_render_brief_data(ProtocolParadox* protocol, FuriString* r
|
||||
uint8_t card_crc = bit_lib_get_bits_16(decoded_data, 34, 8);
|
||||
uint8_t calc_crc = protocol_paradox_calculate_checksum(fc, card_id);
|
||||
|
||||
furi_string_cat_printf(result, "FC: %03u, Card: %05u\r\n", fc, card_id);
|
||||
if(calc_crc == card_crc) {
|
||||
furi_string_cat_printf(result, "CRC : %03u", card_crc);
|
||||
} else {
|
||||
furi_string_cat_printf(result, "Card is Invalid!");
|
||||
furi_string_printf(result, "FC: %hhu; Card: %hu", fc, card_id);
|
||||
|
||||
if(calc_crc != card_crc) {
|
||||
furi_string_cat(result, "\nCRC Mismatch, Invalid Card!");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -237,4 +246,4 @@ const ProtocolBase protocol_paradox = {
|
||||
.render_data = (ProtocolRenderData)protocol_paradox_render_data,
|
||||
.render_brief_data = (ProtocolRenderData)protocol_paradox_render_brief_data,
|
||||
.write_data = (ProtocolWriteData)protocol_paradox_write_data,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -243,7 +243,7 @@ void protocol_pyramid_render_data(ProtocolPyramid* protocol, FuriString* result)
|
||||
uint8_t* decoded_data = protocol->data;
|
||||
uint8_t format_length = decoded_data[0];
|
||||
|
||||
furi_string_cat_printf(result, "Format: %d\r\n", format_length);
|
||||
furi_string_printf(result, "Format: %hhu\n", format_length);
|
||||
if(format_length == 26) {
|
||||
uint8_t facility;
|
||||
bit_lib_copy_bits(&facility, 0, 8, decoded_data, 8);
|
||||
@@ -251,9 +251,9 @@ void protocol_pyramid_render_data(ProtocolPyramid* protocol, FuriString* result)
|
||||
uint16_t card_id;
|
||||
bit_lib_copy_bits((uint8_t*)&card_id, 8, 8, decoded_data, 16);
|
||||
bit_lib_copy_bits((uint8_t*)&card_id, 0, 8, decoded_data, 24);
|
||||
furi_string_cat_printf(result, "FC: %03u, Card: %05u", facility, card_id);
|
||||
furi_string_cat_printf(result, "FC: %03hhu; Card: %05hu", facility, card_id);
|
||||
} else {
|
||||
furi_string_cat_printf(result, "Data: unknown");
|
||||
furi_string_cat_printf(result, "Data: Unknown");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -176,8 +176,7 @@ bool protocol_viking_write_data(ProtocolViking* protocol, void* data) {
|
||||
};
|
||||
|
||||
void protocol_viking_render_data(ProtocolViking* protocol, FuriString* result) {
|
||||
uint32_t id = bit_lib_get_bits_32(protocol->data, 0, 32);
|
||||
furi_string_printf(result, "ID: %08lX\r\n", id);
|
||||
furi_string_printf(result, "ID: %08lX", bit_lib_get_bits_32(protocol->data, 0, 32));
|
||||
};
|
||||
|
||||
const ProtocolBase protocol_viking = {
|
||||
@@ -202,4 +201,4 @@ const ProtocolBase protocol_viking = {
|
||||
.render_data = (ProtocolRenderData)protocol_viking_render_data,
|
||||
.render_brief_data = (ProtocolRenderData)protocol_viking_render_data,
|
||||
.write_data = (ProtocolWriteData)protocol_viking_write_data,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -17,14 +17,14 @@
|
||||
#define T5577_BLOCKS_IN_PAGE_0 8
|
||||
#define T5577_BLOCKS_IN_PAGE_1 4
|
||||
|
||||
static void t5577_start() {
|
||||
static void t5577_start(void) {
|
||||
furi_hal_rfid_tim_read_start(125000, 0.5);
|
||||
|
||||
// do not ground the antenna
|
||||
furi_hal_rfid_pin_pull_release();
|
||||
}
|
||||
|
||||
static void t5577_stop() {
|
||||
static void t5577_stop(void) {
|
||||
furi_hal_rfid_tim_read_stop();
|
||||
furi_hal_rfid_pins_reset();
|
||||
}
|
||||
@@ -49,7 +49,7 @@ static void t5577_write_opcode(uint8_t value) {
|
||||
t5577_write_bit((value >> 0) & 1);
|
||||
}
|
||||
|
||||
static void t5577_write_reset() {
|
||||
static void t5577_write_reset(void) {
|
||||
t5577_write_gap(T5577_TIMING_START_GAP);
|
||||
t5577_write_bit(1);
|
||||
t5577_write_bit(0);
|
||||
|
||||
@@ -8,7 +8,7 @@ struct VarintPair {
|
||||
uint8_t data[VARINT_PAIR_SIZE];
|
||||
};
|
||||
|
||||
VarintPair* varint_pair_alloc() {
|
||||
VarintPair* varint_pair_alloc(void) {
|
||||
VarintPair* pair = malloc(sizeof(VarintPair));
|
||||
pair->data_length = 0;
|
||||
return pair;
|
||||
|
||||
@@ -15,7 +15,7 @@ typedef struct VarintPair VarintPair;
|
||||
* VarintPair is a buffer that holds pair of varint values
|
||||
* @return VarintPair*
|
||||
*/
|
||||
VarintPair* varint_pair_alloc();
|
||||
VarintPair* varint_pair_alloc(void);
|
||||
|
||||
/**
|
||||
* @brief Free a VarintPair instance
|
||||
|
||||
@@ -97,7 +97,7 @@ static int32_t music_worker_thread_callback(void* context) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
MusicWorker* music_worker_alloc() {
|
||||
MusicWorker* music_worker_alloc(void) {
|
||||
MusicWorker* instance = malloc(sizeof(MusicWorker));
|
||||
|
||||
NoteBlockArray_init(instance->notes);
|
||||
|
||||
@@ -12,7 +12,7 @@ typedef void (*MusicWorkerCallback)(
|
||||
|
||||
typedef struct MusicWorker MusicWorker;
|
||||
|
||||
MusicWorker* music_worker_alloc();
|
||||
MusicWorker* music_worker_alloc(void);
|
||||
|
||||
void music_worker_clear(MusicWorker* instance);
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ env.Append(
|
||||
File("protocols/emv/emv.h"),
|
||||
File("protocols/slix/slix.h"),
|
||||
File("protocols/st25tb/st25tb.h"),
|
||||
File("protocols/felica/felica.h"),
|
||||
# Pollers
|
||||
File("protocols/iso14443_3a/iso14443_3a_poller.h"),
|
||||
File("protocols/iso14443_3b/iso14443_3b_poller.h"),
|
||||
@@ -35,6 +36,7 @@ env.Append(
|
||||
File("protocols/mf_desfire/mf_desfire_poller.h"),
|
||||
File("protocols/emv/emv_poller.h"),
|
||||
File("protocols/st25tb/st25tb_poller.h"),
|
||||
File("protocols/felica/felica_poller.h"),
|
||||
# Listeners
|
||||
File("protocols/iso14443_3a/iso14443_3a_listener.h"),
|
||||
File("protocols/iso14443_4a/iso14443_4a_listener.h"),
|
||||
@@ -50,6 +52,7 @@ env.Append(
|
||||
File("helpers/iso14443_crc.h"),
|
||||
File("helpers/iso13239_crc.h"),
|
||||
File("helpers/nfc_data_generator.h"),
|
||||
File("helpers/crypto1.h"),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
#define BEBIT(x, n) FURI_BIT(x, (n) ^ 24)
|
||||
|
||||
Crypto1* crypto1_alloc() {
|
||||
Crypto1* crypto1_alloc(void) {
|
||||
Crypto1* instance = malloc(sizeof(Crypto1));
|
||||
|
||||
return instance;
|
||||
@@ -11,7 +11,7 @@ typedef struct {
|
||||
uint32_t even;
|
||||
} Crypto1;
|
||||
|
||||
Crypto1* crypto1_alloc();
|
||||
Crypto1* crypto1_alloc(void);
|
||||
|
||||
void crypto1_free(Crypto1* instance);
|
||||
|
||||
@@ -33,6 +33,8 @@ static uint16_t
|
||||
}
|
||||
|
||||
void iso13239_crc_append(Iso13239CrcType type, BitBuffer* buf) {
|
||||
furi_check(buf);
|
||||
|
||||
const uint8_t* data = bit_buffer_get_data(buf);
|
||||
const size_t data_size = bit_buffer_get_size_bytes(buf);
|
||||
|
||||
@@ -41,6 +43,8 @@ void iso13239_crc_append(Iso13239CrcType type, BitBuffer* buf) {
|
||||
}
|
||||
|
||||
bool iso13239_crc_check(Iso13239CrcType type, const BitBuffer* buf) {
|
||||
furi_check(buf);
|
||||
|
||||
const size_t data_size = bit_buffer_get_size_bytes(buf);
|
||||
if(data_size <= ISO13239_CRC_SIZE) return false;
|
||||
|
||||
@@ -55,6 +59,8 @@ bool iso13239_crc_check(Iso13239CrcType type, const BitBuffer* buf) {
|
||||
}
|
||||
|
||||
void iso13239_crc_trim(BitBuffer* buf) {
|
||||
furi_check(buf);
|
||||
|
||||
const size_t data_size = bit_buffer_get_size_bytes(buf);
|
||||
furi_assert(data_size > ISO13239_CRC_SIZE);
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ static inline void iso14443_4_layer_update_pcb(Iso14443_4Layer* instance) {
|
||||
instance->pcb ^= (uint8_t)0x01;
|
||||
}
|
||||
|
||||
Iso14443_4Layer* iso14443_4_layer_alloc() {
|
||||
Iso14443_4Layer* iso14443_4_layer_alloc(void) {
|
||||
Iso14443_4Layer* instance = malloc(sizeof(Iso14443_4Layer));
|
||||
|
||||
iso14443_4_layer_reset(instance);
|
||||
|
||||
@@ -9,7 +9,7 @@ extern "C" {
|
||||
|
||||
typedef struct Iso14443_4Layer Iso14443_4Layer;
|
||||
|
||||
Iso14443_4Layer* iso14443_4_layer_alloc();
|
||||
Iso14443_4Layer* iso14443_4_layer_alloc(void);
|
||||
|
||||
void iso14443_4_layer_free(Iso14443_4Layer* instance);
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@ static uint16_t
|
||||
}
|
||||
|
||||
void iso14443_crc_append(Iso14443CrcType type, BitBuffer* buf) {
|
||||
furi_check(buf);
|
||||
|
||||
const uint8_t* data = bit_buffer_get_data(buf);
|
||||
const size_t data_size = bit_buffer_get_size_bytes(buf);
|
||||
|
||||
@@ -36,6 +38,8 @@ void iso14443_crc_append(Iso14443CrcType type, BitBuffer* buf) {
|
||||
}
|
||||
|
||||
bool iso14443_crc_check(Iso14443CrcType type, const BitBuffer* buf) {
|
||||
furi_check(buf);
|
||||
|
||||
const size_t data_size = bit_buffer_get_size_bytes(buf);
|
||||
if(data_size <= ISO14443_CRC_SIZE) return false;
|
||||
|
||||
@@ -50,8 +54,9 @@ bool iso14443_crc_check(Iso14443CrcType type, const BitBuffer* buf) {
|
||||
}
|
||||
|
||||
void iso14443_crc_trim(BitBuffer* buf) {
|
||||
furi_check(buf);
|
||||
const size_t data_size = bit_buffer_get_size_bytes(buf);
|
||||
furi_assert(data_size > ISO14443_CRC_SIZE);
|
||||
furi_check(data_size > ISO14443_CRC_SIZE);
|
||||
|
||||
bit_buffer_set_size_bytes(buf, data_size - ISO14443_CRC_SIZE);
|
||||
}
|
||||
|
||||
@@ -552,9 +552,14 @@ static const NfcDataGenerator nfc_data_generator[NfcDataGeneratorTypeNum] = {
|
||||
};
|
||||
|
||||
const char* nfc_data_generator_get_name(NfcDataGeneratorType type) {
|
||||
furi_check(type < NfcDataGeneratorTypeNum);
|
||||
|
||||
return nfc_data_generator[type].name;
|
||||
}
|
||||
|
||||
void nfc_data_generator_fill_data(NfcDataGeneratorType type, NfcDevice* nfc_device) {
|
||||
furi_check(type < NfcDataGeneratorTypeNum);
|
||||
furi_check(nfc_device);
|
||||
|
||||
nfc_data_generator[type].handler(nfc_device);
|
||||
}
|
||||
|
||||
@@ -25,8 +25,8 @@ uint8_t nfc_util_odd_parity8(uint8_t data) {
|
||||
}
|
||||
|
||||
void nfc_util_odd_parity(const uint8_t* src, uint8_t* dst, uint8_t len) {
|
||||
furi_assert(src);
|
||||
furi_assert(dst);
|
||||
furi_check(src);
|
||||
furi_check(dst);
|
||||
|
||||
uint8_t parity = 0;
|
||||
uint8_t bit = 0;
|
||||
|
||||
+40
-42
@@ -235,7 +235,7 @@ static int32_t nfc_worker_poller(void* context) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Nfc* nfc_alloc() {
|
||||
Nfc* nfc_alloc(void) {
|
||||
furi_check(furi_hal_nfc_acquire() == FuriHalNfcErrorNone);
|
||||
|
||||
Nfc* instance = malloc(sizeof(Nfc));
|
||||
@@ -253,8 +253,8 @@ Nfc* nfc_alloc() {
|
||||
}
|
||||
|
||||
void nfc_free(Nfc* instance) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->state == NfcStateIdle);
|
||||
furi_check(instance);
|
||||
furi_check(instance->state == NfcStateIdle);
|
||||
|
||||
furi_thread_free(instance->worker_thread);
|
||||
free(instance);
|
||||
@@ -263,10 +263,10 @@ void nfc_free(Nfc* instance) {
|
||||
}
|
||||
|
||||
void nfc_config(Nfc* instance, NfcMode mode, NfcTech tech) {
|
||||
furi_assert(instance);
|
||||
furi_assert(mode < NfcModeNum);
|
||||
furi_assert(tech < NfcTechNum);
|
||||
furi_assert(instance->config_state == NfcConfigurationStateIdle);
|
||||
furi_check(instance);
|
||||
furi_check(mode < NfcModeNum);
|
||||
furi_check(tech < NfcTechNum);
|
||||
furi_check(instance->config_state == NfcConfigurationStateIdle);
|
||||
|
||||
FuriHalNfcTech hal_tech = nfc_tech_table[mode][tech];
|
||||
if(hal_tech == FuriHalNfcTechInvalid) {
|
||||
@@ -282,35 +282,35 @@ void nfc_config(Nfc* instance, NfcMode mode, NfcTech tech) {
|
||||
}
|
||||
|
||||
void nfc_set_fdt_poll_fc(Nfc* instance, uint32_t fdt_poll_fc) {
|
||||
furi_assert(instance);
|
||||
furi_check(instance);
|
||||
instance->fdt_poll_fc = fdt_poll_fc;
|
||||
}
|
||||
|
||||
void nfc_set_fdt_listen_fc(Nfc* instance, uint32_t fdt_listen_fc) {
|
||||
furi_assert(instance);
|
||||
furi_check(instance);
|
||||
instance->fdt_listen_fc = fdt_listen_fc;
|
||||
}
|
||||
|
||||
void nfc_set_fdt_poll_poll_us(Nfc* instance, uint32_t fdt_poll_poll_us) {
|
||||
furi_assert(instance);
|
||||
furi_check(instance);
|
||||
instance->fdt_poll_poll_us = fdt_poll_poll_us;
|
||||
}
|
||||
|
||||
void nfc_set_guard_time_us(Nfc* instance, uint32_t guard_time_us) {
|
||||
furi_assert(instance);
|
||||
furi_check(instance);
|
||||
instance->guard_time_us = guard_time_us;
|
||||
}
|
||||
|
||||
void nfc_set_mask_receive_time_fc(Nfc* instance, uint32_t mask_rx_time_fc) {
|
||||
furi_assert(instance);
|
||||
furi_check(instance);
|
||||
instance->mask_rx_time_fc = mask_rx_time_fc;
|
||||
}
|
||||
|
||||
void nfc_start(Nfc* instance, NfcEventCallback callback, void* context) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->worker_thread);
|
||||
furi_assert(callback);
|
||||
furi_assert(instance->config_state == NfcConfigurationStateDone);
|
||||
furi_check(instance);
|
||||
furi_check(instance->worker_thread);
|
||||
furi_check(callback);
|
||||
furi_check(instance->config_state == NfcConfigurationStateDone);
|
||||
|
||||
instance->callback = callback;
|
||||
instance->context = context;
|
||||
@@ -324,8 +324,8 @@ void nfc_start(Nfc* instance, NfcEventCallback callback, void* context) {
|
||||
}
|
||||
|
||||
void nfc_stop(Nfc* instance) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->state == NfcStateRunning);
|
||||
furi_check(instance);
|
||||
furi_check(instance->state == NfcStateRunning);
|
||||
|
||||
if(instance->mode == NfcModeListener) {
|
||||
furi_hal_nfc_abort();
|
||||
@@ -336,8 +336,8 @@ void nfc_stop(Nfc* instance) {
|
||||
}
|
||||
|
||||
NfcError nfc_listener_tx(Nfc* instance, const BitBuffer* tx_buffer) {
|
||||
furi_assert(instance);
|
||||
furi_assert(tx_buffer);
|
||||
furi_check(instance);
|
||||
furi_check(tx_buffer);
|
||||
|
||||
NfcError ret = NfcErrorNone;
|
||||
|
||||
@@ -409,11 +409,11 @@ NfcError nfc_iso14443a_poller_trx_custom_parity(
|
||||
const BitBuffer* tx_buffer,
|
||||
BitBuffer* rx_buffer,
|
||||
uint32_t fwt) {
|
||||
furi_assert(instance);
|
||||
furi_assert(tx_buffer);
|
||||
furi_assert(rx_buffer);
|
||||
furi_check(instance);
|
||||
furi_check(tx_buffer);
|
||||
furi_check(rx_buffer);
|
||||
|
||||
furi_assert(instance->poller_state == NfcPollerStateReady);
|
||||
furi_check(instance->poller_state == NfcPollerStateReady);
|
||||
|
||||
NfcError ret = NfcErrorNone;
|
||||
FuriHalNfcError error = FuriHalNfcErrorNone;
|
||||
@@ -462,11 +462,11 @@ NfcError nfc_iso14443a_poller_trx_custom_parity(
|
||||
|
||||
NfcError
|
||||
nfc_poller_trx(Nfc* instance, const BitBuffer* tx_buffer, BitBuffer* rx_buffer, uint32_t fwt) {
|
||||
furi_assert(instance);
|
||||
furi_assert(tx_buffer);
|
||||
furi_assert(rx_buffer);
|
||||
furi_check(instance);
|
||||
furi_check(tx_buffer);
|
||||
furi_check(rx_buffer);
|
||||
|
||||
furi_assert(instance->poller_state == NfcPollerStateReady);
|
||||
furi_check(instance->poller_state == NfcPollerStateReady);
|
||||
|
||||
NfcError ret = NfcErrorNone;
|
||||
FuriHalNfcError error = FuriHalNfcErrorNone;
|
||||
@@ -511,7 +511,7 @@ NfcError nfc_iso14443a_listener_set_col_res_data(
|
||||
uint8_t uid_len,
|
||||
uint8_t* atqa,
|
||||
uint8_t sak) {
|
||||
furi_assert(instance);
|
||||
furi_check(instance);
|
||||
|
||||
FuriHalNfcError error =
|
||||
furi_hal_nfc_iso14443a_listener_set_col_res_data(uid, uid_len, atqa, sak);
|
||||
@@ -524,14 +524,14 @@ NfcError nfc_iso14443a_poller_trx_short_frame(
|
||||
NfcIso14443aShortFrame frame,
|
||||
BitBuffer* rx_buffer,
|
||||
uint32_t fwt) {
|
||||
furi_assert(instance);
|
||||
furi_assert(rx_buffer);
|
||||
furi_check(instance);
|
||||
furi_check(rx_buffer);
|
||||
|
||||
FuriHalNfcaShortFrame short_frame = (frame == NfcIso14443aShortFrameAllReqa) ?
|
||||
FuriHalNfcaShortFrameAllReq :
|
||||
FuriHalNfcaShortFrameSensReq;
|
||||
|
||||
furi_assert(instance->poller_state == NfcPollerStateReady);
|
||||
furi_check(instance->poller_state == NfcPollerStateReady);
|
||||
|
||||
NfcError ret = NfcErrorNone;
|
||||
FuriHalNfcError error = FuriHalNfcErrorNone;
|
||||
@@ -574,11 +574,11 @@ NfcError nfc_iso14443a_poller_trx_sdd_frame(
|
||||
const BitBuffer* tx_buffer,
|
||||
BitBuffer* rx_buffer,
|
||||
uint32_t fwt) {
|
||||
furi_assert(instance);
|
||||
furi_assert(tx_buffer);
|
||||
furi_assert(rx_buffer);
|
||||
furi_check(instance);
|
||||
furi_check(tx_buffer);
|
||||
furi_check(rx_buffer);
|
||||
|
||||
furi_assert(instance->poller_state == NfcPollerStateReady);
|
||||
furi_check(instance->poller_state == NfcPollerStateReady);
|
||||
|
||||
NfcError ret = NfcErrorNone;
|
||||
FuriHalNfcError error = FuriHalNfcErrorNone;
|
||||
@@ -618,8 +618,8 @@ NfcError nfc_iso14443a_poller_trx_sdd_frame(
|
||||
}
|
||||
|
||||
NfcError nfc_iso14443a_listener_tx_custom_parity(Nfc* instance, const BitBuffer* tx_buffer) {
|
||||
furi_assert(instance);
|
||||
furi_assert(tx_buffer);
|
||||
furi_check(instance);
|
||||
furi_check(tx_buffer);
|
||||
|
||||
NfcError ret = NfcErrorNone;
|
||||
FuriHalNfcError error = FuriHalNfcErrorNone;
|
||||
@@ -635,7 +635,7 @@ NfcError nfc_iso14443a_listener_tx_custom_parity(Nfc* instance, const BitBuffer*
|
||||
}
|
||||
|
||||
NfcError nfc_iso15693_listener_tx_sof(Nfc* instance) {
|
||||
furi_assert(instance);
|
||||
furi_check(instance);
|
||||
|
||||
while(furi_hal_nfc_timer_block_tx_is_running()) {
|
||||
}
|
||||
@@ -652,9 +652,7 @@ NfcError nfc_felica_listener_set_sensf_res_data(
|
||||
const uint8_t idm_len,
|
||||
const uint8_t* pmm,
|
||||
const uint8_t pmm_len) {
|
||||
furi_assert(instance);
|
||||
furi_assert(idm);
|
||||
furi_assert(pmm);
|
||||
furi_check(instance);
|
||||
|
||||
FuriHalNfcError error =
|
||||
furi_hal_nfc_felica_listener_set_sensf_res_data(idm, idm_len, pmm, pmm_len);
|
||||
|
||||
+2
-2
@@ -128,7 +128,7 @@ typedef enum {
|
||||
*
|
||||
* @returns pointer to the allocated Nfc instance.
|
||||
*/
|
||||
Nfc* nfc_alloc();
|
||||
Nfc* nfc_alloc(void);
|
||||
|
||||
/**
|
||||
* @brief Delete an Nfc instance.
|
||||
@@ -170,7 +170,7 @@ void nfc_set_fdt_listen_fc(Nfc* instance, uint32_t fdt_listen_fc);
|
||||
* @brief Set mask receive time.
|
||||
*
|
||||
* @param[in,out] instance pointer to the instance to be modified.
|
||||
* @param[in] mask_rx_time mask receive time, in carrier cycles.
|
||||
* @param[in] mask_rx_time_fc mask receive time, in carrier cycles.
|
||||
*/
|
||||
void nfc_set_mask_receive_time_fc(Nfc* instance, uint32_t mask_rx_time_fc);
|
||||
|
||||
|
||||
+34
-30
@@ -14,7 +14,7 @@
|
||||
|
||||
#define NFC_DEVICE_UID_MAX_LEN (10U)
|
||||
|
||||
NfcDevice* nfc_device_alloc() {
|
||||
NfcDevice* nfc_device_alloc(void) {
|
||||
NfcDevice* instance = malloc(sizeof(NfcDevice));
|
||||
instance->protocol = NfcProtocolInvalid;
|
||||
|
||||
@@ -22,14 +22,14 @@ NfcDevice* nfc_device_alloc() {
|
||||
}
|
||||
|
||||
void nfc_device_free(NfcDevice* instance) {
|
||||
furi_assert(instance);
|
||||
furi_check(instance);
|
||||
|
||||
nfc_device_clear(instance);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
void nfc_device_clear(NfcDevice* instance) {
|
||||
furi_assert(instance);
|
||||
furi_check(instance);
|
||||
|
||||
if(instance->protocol == NfcProtocolInvalid) {
|
||||
furi_assert(instance->protocol_data == NULL);
|
||||
@@ -43,8 +43,8 @@ void nfc_device_clear(NfcDevice* instance) {
|
||||
}
|
||||
|
||||
void nfc_device_reset(NfcDevice* instance) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->protocol < NfcProtocolNum);
|
||||
furi_check(instance);
|
||||
furi_check(instance->protocol < NfcProtocolNum);
|
||||
|
||||
if(instance->protocol_data) {
|
||||
nfc_devices[instance->protocol]->reset(instance->protocol_data);
|
||||
@@ -52,37 +52,40 @@ void nfc_device_reset(NfcDevice* instance) {
|
||||
}
|
||||
|
||||
NfcProtocol nfc_device_get_protocol(const NfcDevice* instance) {
|
||||
furi_assert(instance);
|
||||
furi_check(instance);
|
||||
return instance->protocol;
|
||||
}
|
||||
|
||||
const NfcDeviceData* nfc_device_get_data(const NfcDevice* instance, NfcProtocol protocol) {
|
||||
furi_check(instance);
|
||||
return nfc_device_get_data_ptr(instance, protocol);
|
||||
}
|
||||
|
||||
const char* nfc_device_get_protocol_name(NfcProtocol protocol) {
|
||||
furi_assert(protocol < NfcProtocolNum);
|
||||
furi_check(protocol < NfcProtocolNum);
|
||||
|
||||
return nfc_devices[protocol]->protocol_name;
|
||||
}
|
||||
|
||||
const char* nfc_device_get_name(const NfcDevice* instance, NfcDeviceNameType name_type) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->protocol < NfcProtocolNum);
|
||||
furi_check(instance);
|
||||
furi_check(instance->protocol < NfcProtocolNum);
|
||||
|
||||
return nfc_devices[instance->protocol]->get_name(instance->protocol_data, name_type);
|
||||
}
|
||||
|
||||
const uint8_t* nfc_device_get_uid(const NfcDevice* instance, size_t* uid_len) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->protocol < NfcProtocolNum);
|
||||
furi_check(instance);
|
||||
furi_check(uid_len);
|
||||
furi_check(instance->protocol < NfcProtocolNum);
|
||||
|
||||
return nfc_devices[instance->protocol]->get_uid(instance->protocol_data, uid_len);
|
||||
}
|
||||
|
||||
bool nfc_device_set_uid(NfcDevice* instance, const uint8_t* uid, size_t uid_len) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->protocol < NfcProtocolNum);
|
||||
furi_check(instance);
|
||||
furi_check(uid);
|
||||
furi_check(instance->protocol < NfcProtocolNum);
|
||||
|
||||
return nfc_devices[instance->protocol]->set_uid(instance->protocol_data, uid, uid_len);
|
||||
}
|
||||
@@ -91,8 +94,9 @@ void nfc_device_set_data(
|
||||
NfcDevice* instance,
|
||||
NfcProtocol protocol,
|
||||
const NfcDeviceData* protocol_data) {
|
||||
furi_assert(instance);
|
||||
furi_assert(protocol < NfcProtocolNum);
|
||||
furi_check(instance);
|
||||
furi_check(protocol_data);
|
||||
furi_check(protocol < NfcProtocolNum);
|
||||
|
||||
nfc_device_clear(instance);
|
||||
|
||||
@@ -106,9 +110,9 @@ void nfc_device_copy_data(
|
||||
const NfcDevice* instance,
|
||||
NfcProtocol protocol,
|
||||
NfcDeviceData* protocol_data) {
|
||||
furi_assert(instance);
|
||||
furi_assert(protocol < NfcProtocolNum);
|
||||
furi_assert(protocol_data);
|
||||
furi_check(instance);
|
||||
furi_check(protocol < NfcProtocolNum);
|
||||
furi_check(protocol_data);
|
||||
|
||||
if(instance->protocol != protocol) {
|
||||
furi_crash(NFC_DEV_TYPE_ERROR);
|
||||
@@ -121,17 +125,17 @@ bool nfc_device_is_equal_data(
|
||||
const NfcDevice* instance,
|
||||
NfcProtocol protocol,
|
||||
const NfcDeviceData* protocol_data) {
|
||||
furi_assert(instance);
|
||||
furi_assert(protocol < NfcProtocolNum);
|
||||
furi_assert(protocol_data);
|
||||
furi_check(instance);
|
||||
furi_check(protocol < NfcProtocolNum);
|
||||
furi_check(protocol_data);
|
||||
|
||||
return instance->protocol == protocol &&
|
||||
nfc_devices[protocol]->is_equal(instance->protocol_data, protocol_data);
|
||||
}
|
||||
|
||||
bool nfc_device_is_equal(const NfcDevice* instance, const NfcDevice* other) {
|
||||
furi_assert(instance);
|
||||
furi_assert(other);
|
||||
furi_check(instance);
|
||||
furi_check(other);
|
||||
|
||||
return nfc_device_is_equal_data(instance, other->protocol, other->protocol_data);
|
||||
}
|
||||
@@ -140,17 +144,17 @@ void nfc_device_set_loading_callback(
|
||||
NfcDevice* instance,
|
||||
NfcLoadingCallback callback,
|
||||
void* context) {
|
||||
furi_assert(instance);
|
||||
furi_assert(callback);
|
||||
furi_check(instance);
|
||||
furi_check(callback);
|
||||
|
||||
instance->loading_callback = callback;
|
||||
instance->loading_callback_context = context;
|
||||
}
|
||||
|
||||
bool nfc_device_save(NfcDevice* instance, const char* path) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->protocol < NfcProtocolNum);
|
||||
furi_assert(path);
|
||||
furi_check(instance);
|
||||
furi_check(instance->protocol < NfcProtocolNum);
|
||||
furi_check(path);
|
||||
|
||||
bool saved = false;
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
@@ -313,8 +317,8 @@ static bool nfc_device_load_legacy(NfcDevice* instance, FlipperFormat* ff, uint3
|
||||
}
|
||||
|
||||
bool nfc_device_load(NfcDevice* instance, const char* path) {
|
||||
furi_assert(instance);
|
||||
furi_assert(path);
|
||||
furi_check(instance);
|
||||
furi_check(path);
|
||||
|
||||
bool loaded = false;
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
|
||||
@@ -47,7 +47,7 @@ typedef void (*NfcLoadingCallback)(void* context, bool state);
|
||||
*
|
||||
* @returns pointer to the allocated instance.
|
||||
*/
|
||||
NfcDevice* nfc_device_alloc();
|
||||
NfcDevice* nfc_device_alloc(void);
|
||||
|
||||
/**
|
||||
* @brief Delete an NfcDevice instance.
|
||||
|
||||
+10
-10
@@ -73,10 +73,10 @@ static void nfc_listener_list_free(NfcListener* instance) {
|
||||
}
|
||||
|
||||
NfcListener* nfc_listener_alloc(Nfc* nfc, NfcProtocol protocol, const NfcDeviceData* data) {
|
||||
furi_assert(nfc);
|
||||
furi_assert(protocol < NfcProtocolNum);
|
||||
furi_assert(data);
|
||||
furi_assert(nfc_listeners_api[protocol]);
|
||||
furi_check(nfc);
|
||||
furi_check(protocol < NfcProtocolNum);
|
||||
furi_check(data);
|
||||
furi_check(nfc_listeners_api[protocol]);
|
||||
|
||||
NfcListener* instance = malloc(sizeof(NfcListener));
|
||||
instance->nfc = nfc;
|
||||
@@ -89,7 +89,7 @@ NfcListener* nfc_listener_alloc(Nfc* nfc, NfcProtocol protocol, const NfcDeviceD
|
||||
}
|
||||
|
||||
void nfc_listener_free(NfcListener* instance) {
|
||||
furi_assert(instance);
|
||||
furi_check(instance);
|
||||
|
||||
nfc_listener_list_free(instance);
|
||||
nfc_device_free(instance->nfc_dev);
|
||||
@@ -116,7 +116,7 @@ NfcCommand nfc_listener_start_callback(NfcEvent event, void* context) {
|
||||
}
|
||||
|
||||
void nfc_listener_start(NfcListener* instance, NfcGenericCallback callback, void* context) {
|
||||
furi_assert(instance);
|
||||
furi_check(instance);
|
||||
|
||||
NfcListenerListElement* tail_element = instance->list.tail;
|
||||
tail_element->listener_api->set_callback(tail_element->listener, callback, context);
|
||||
@@ -124,20 +124,20 @@ void nfc_listener_start(NfcListener* instance, NfcGenericCallback callback, void
|
||||
}
|
||||
|
||||
void nfc_listener_stop(NfcListener* instance) {
|
||||
furi_assert(instance);
|
||||
furi_check(instance);
|
||||
|
||||
nfc_stop(instance->nfc);
|
||||
}
|
||||
|
||||
NfcProtocol nfc_listener_get_protocol(const NfcListener* instance) {
|
||||
furi_assert(instance);
|
||||
furi_check(instance);
|
||||
|
||||
return instance->protocol;
|
||||
}
|
||||
|
||||
const NfcDeviceData* nfc_listener_get_data(const NfcListener* instance, NfcProtocol protocol) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->protocol == protocol);
|
||||
furi_check(instance);
|
||||
furi_check(instance->protocol == protocol);
|
||||
|
||||
NfcListenerListElement* tail_element = instance->list.tail;
|
||||
return tail_element->listener_api->get_data(tail_element->listener);
|
||||
|
||||
+15
-15
@@ -75,8 +75,8 @@ static void nfc_poller_list_free(NfcPoller* instance) {
|
||||
}
|
||||
|
||||
NfcPoller* nfc_poller_alloc(Nfc* nfc, NfcProtocol protocol) {
|
||||
furi_assert(nfc);
|
||||
furi_assert(protocol < NfcProtocolNum);
|
||||
furi_check(nfc);
|
||||
furi_check(protocol < NfcProtocolNum);
|
||||
|
||||
NfcPoller* instance = malloc(sizeof(NfcPoller));
|
||||
instance->session_state = NfcPollerSessionStateIdle;
|
||||
@@ -88,7 +88,7 @@ NfcPoller* nfc_poller_alloc(Nfc* nfc, NfcProtocol protocol) {
|
||||
}
|
||||
|
||||
void nfc_poller_free(NfcPoller* instance) {
|
||||
furi_assert(instance);
|
||||
furi_check(instance);
|
||||
|
||||
nfc_poller_list_free(instance);
|
||||
free(instance);
|
||||
@@ -119,9 +119,9 @@ static NfcCommand nfc_poller_start_callback(NfcEvent event, void* context) {
|
||||
}
|
||||
|
||||
void nfc_poller_start(NfcPoller* instance, NfcGenericCallback callback, void* context) {
|
||||
furi_assert(instance);
|
||||
furi_assert(callback);
|
||||
furi_assert(instance->session_state == NfcPollerSessionStateIdle);
|
||||
furi_check(instance);
|
||||
furi_check(callback);
|
||||
furi_check(instance->session_state == NfcPollerSessionStateIdle);
|
||||
|
||||
NfcPollerListElement* tail_poller = instance->list.tail;
|
||||
tail_poller->poller_api->set_callback(tail_poller->poller, callback, context);
|
||||
@@ -180,9 +180,9 @@ static NfcCommand nfc_poller_start_ex_head_callback(NfcEvent event, void* contex
|
||||
}
|
||||
|
||||
void nfc_poller_start_ex(NfcPoller* instance, NfcGenericCallbackEx callback, void* context) {
|
||||
furi_assert(instance);
|
||||
furi_assert(callback);
|
||||
furi_assert(instance->session_state == NfcPollerSessionStateIdle);
|
||||
furi_check(instance);
|
||||
furi_check(callback);
|
||||
furi_check(instance->session_state == NfcPollerSessionStateIdle);
|
||||
|
||||
instance->callback = callback;
|
||||
instance->context = context;
|
||||
@@ -200,8 +200,8 @@ void nfc_poller_start_ex(NfcPoller* instance, NfcGenericCallbackEx callback, voi
|
||||
}
|
||||
|
||||
void nfc_poller_stop(NfcPoller* instance) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->nfc);
|
||||
furi_check(instance);
|
||||
furi_check(instance->nfc);
|
||||
|
||||
instance->session_state = NfcPollerSessionStateStopRequest;
|
||||
nfc_stop(instance->nfc);
|
||||
@@ -246,8 +246,8 @@ static NfcCommand nfc_poller_detect_head_callback(NfcEvent event, void* context)
|
||||
}
|
||||
|
||||
bool nfc_poller_detect(NfcPoller* instance) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->session_state == NfcPollerSessionStateIdle);
|
||||
furi_check(instance);
|
||||
furi_check(instance->session_state == NfcPollerSessionStateIdle);
|
||||
|
||||
instance->session_state = NfcPollerSessionStateActive;
|
||||
NfcPollerListElement* tail_poller = instance->list.tail;
|
||||
@@ -270,13 +270,13 @@ bool nfc_poller_detect(NfcPoller* instance) {
|
||||
}
|
||||
|
||||
NfcProtocol nfc_poller_get_protocol(const NfcPoller* instance) {
|
||||
furi_assert(instance);
|
||||
furi_check(instance);
|
||||
|
||||
return instance->protocol;
|
||||
}
|
||||
|
||||
const NfcDeviceData* nfc_poller_get_data(const NfcPoller* instance) {
|
||||
furi_assert(instance);
|
||||
furi_check(instance);
|
||||
|
||||
NfcPollerListElement* tail_poller = instance->list.tail;
|
||||
return tail_poller->poller_api->get_data(tail_poller->poller);
|
||||
|
||||
@@ -218,7 +218,7 @@ static int32_t nfc_scanner_worker(void* context) {
|
||||
}
|
||||
|
||||
NfcScanner* nfc_scanner_alloc(Nfc* nfc) {
|
||||
furi_assert(nfc);
|
||||
furi_check(nfc);
|
||||
|
||||
NfcScanner* instance = malloc(sizeof(NfcScanner));
|
||||
instance->nfc = nfc;
|
||||
@@ -227,16 +227,17 @@ NfcScanner* nfc_scanner_alloc(Nfc* nfc) {
|
||||
}
|
||||
|
||||
void nfc_scanner_free(NfcScanner* instance) {
|
||||
furi_assert(instance);
|
||||
furi_check(instance);
|
||||
furi_check(instance->state == NfcScannerStateIdle);
|
||||
|
||||
free(instance);
|
||||
}
|
||||
|
||||
void nfc_scanner_start(NfcScanner* instance, NfcScannerCallback callback, void* context) {
|
||||
furi_assert(instance);
|
||||
furi_assert(callback);
|
||||
furi_assert(instance->session_state == NfcScannerSessionStateIdle);
|
||||
furi_assert(instance->scan_worker == NULL);
|
||||
furi_check(instance);
|
||||
furi_check(callback);
|
||||
furi_check(instance->state == NfcScannerStateIdle);
|
||||
furi_check(instance->scan_worker == NULL);
|
||||
|
||||
instance->callback = callback;
|
||||
instance->context = context;
|
||||
@@ -252,8 +253,8 @@ void nfc_scanner_start(NfcScanner* instance, NfcScannerCallback callback, void*
|
||||
}
|
||||
|
||||
void nfc_scanner_stop(NfcScanner* instance) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->scan_worker);
|
||||
furi_check(instance);
|
||||
furi_check(instance->scan_worker);
|
||||
|
||||
instance->session_state = NfcScannerSessionStateStopRequest;
|
||||
furi_thread_join(instance->scan_worker);
|
||||
|
||||
@@ -72,14 +72,14 @@ NfcScanner* nfc_scanner_alloc(Nfc* nfc);
|
||||
/**
|
||||
* @brief Delete an NfcScanner instance.
|
||||
*
|
||||
* @param[in,out] pointer to the instance to be deleted.
|
||||
* @param[in,out] instance pointer to the instance to be deleted.
|
||||
*/
|
||||
void nfc_scanner_free(NfcScanner* instance);
|
||||
|
||||
/**
|
||||
* @brief Start an NfcScanner.
|
||||
*
|
||||
* @param[in,out] pointer to the instance to be started.
|
||||
* @param[in,out] instance pointer to the instance to be started.
|
||||
* @param[in] callback pointer to the callback function (will be called upon a detection event).
|
||||
* @param[in] context pointer to the caller-specific context (will be passed to the callback).
|
||||
*/
|
||||
@@ -88,7 +88,7 @@ void nfc_scanner_start(NfcScanner* instance, NfcScannerCallback callback, void*
|
||||
/**
|
||||
* @brief Stop an NfcScanner.
|
||||
*
|
||||
* @param[in,out] pointer to the instance to be stopped.
|
||||
* @param[in,out] instance pointer to the instance to be stopped.
|
||||
*/
|
||||
void nfc_scanner_stop(NfcScanner* instance);
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ const NfcDeviceBase nfc_device_emv = {
|
||||
.get_base_data = (NfcDeviceGetBaseData)emv_get_base_data,
|
||||
};
|
||||
|
||||
EmvData* emv_alloc() {
|
||||
EmvData* emv_alloc(void) {
|
||||
EmvData* data = malloc(sizeof(EmvData));
|
||||
data->iso14443_4a_data = iso14443_4a_alloc();
|
||||
data->emv_application.pin_try_counter = 0xff;
|
||||
|
||||
@@ -119,7 +119,7 @@ extern const NfcDeviceBase nfc_device_emv;
|
||||
|
||||
// Virtual methods
|
||||
|
||||
EmvData* emv_alloc();
|
||||
EmvData* emv_alloc(void);
|
||||
|
||||
void emv_free(EmvData* data);
|
||||
|
||||
|
||||
@@ -13,6 +13,14 @@
|
||||
|
||||
static const uint32_t felica_data_format_version = 1;
|
||||
|
||||
/** @brief This is used in felica_prepare_first_block to define which
|
||||
* type of block needs to be prepared.
|
||||
*/
|
||||
typedef enum {
|
||||
FelicaMACTypeRead,
|
||||
FelicaMACTypeWrite,
|
||||
} FelicaMACType;
|
||||
|
||||
const NfcDeviceBase nfc_device_felica = {
|
||||
.protocol_name = FELICA_PROTOCOL_NAME,
|
||||
.alloc = (NfcDeviceAlloc)felica_alloc,
|
||||
@@ -29,24 +37,24 @@ const NfcDeviceBase nfc_device_felica = {
|
||||
.get_base_data = (NfcDeviceGetBaseData)felica_get_base_data,
|
||||
};
|
||||
|
||||
FelicaData* felica_alloc() {
|
||||
FelicaData* felica_alloc(void) {
|
||||
FelicaData* data = malloc(sizeof(FelicaData));
|
||||
return data;
|
||||
}
|
||||
|
||||
void felica_free(FelicaData* data) {
|
||||
furi_assert(data);
|
||||
|
||||
furi_check(data);
|
||||
free(data);
|
||||
}
|
||||
|
||||
void felica_reset(FelicaData* data) {
|
||||
furi_check(data);
|
||||
memset(data, 0, sizeof(FelicaData));
|
||||
}
|
||||
|
||||
void felica_copy(FelicaData* data, const FelicaData* other) {
|
||||
furi_assert(data);
|
||||
furi_assert(other);
|
||||
furi_check(data);
|
||||
furi_check(other);
|
||||
|
||||
*data = *other;
|
||||
}
|
||||
@@ -59,7 +67,7 @@ bool felica_verify(FelicaData* data, const FuriString* device_type) {
|
||||
}
|
||||
|
||||
bool felica_load(FelicaData* data, FlipperFormat* ff, uint32_t version) {
|
||||
furi_assert(data);
|
||||
furi_check(data);
|
||||
|
||||
bool parsed = false;
|
||||
|
||||
@@ -77,13 +85,32 @@ bool felica_load(FelicaData* data, FlipperFormat* ff, uint32_t version) {
|
||||
break;
|
||||
|
||||
parsed = true;
|
||||
uint32_t blocks_total = 0;
|
||||
uint32_t blocks_read = 0;
|
||||
if(!flipper_format_read_uint32(ff, "Blocks total", &blocks_total, 1)) break;
|
||||
if(!flipper_format_read_uint32(ff, "Blocks read", &blocks_read, 1)) break;
|
||||
data->blocks_total = (uint8_t)blocks_total;
|
||||
data->blocks_read = (uint8_t)blocks_read;
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
for(uint8_t i = 0; i < data->blocks_total; i++) {
|
||||
furi_string_printf(temp_str, "Block %d", i);
|
||||
if(!flipper_format_read_hex(
|
||||
ff,
|
||||
furi_string_get_cstr(temp_str),
|
||||
(&data->data.dump[i * sizeof(FelicaBlock)]),
|
||||
sizeof(FelicaBlock))) {
|
||||
parsed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while(false);
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
bool felica_save(const FelicaData* data, FlipperFormat* ff) {
|
||||
furi_assert(data);
|
||||
furi_check(data);
|
||||
|
||||
bool saved = false;
|
||||
|
||||
@@ -98,15 +125,33 @@ bool felica_save(const FelicaData* data, FlipperFormat* ff) {
|
||||
ff, FELICA_MANUFACTURE_PARAMETER, data->pmm.data, FELICA_PMM_SIZE))
|
||||
break;
|
||||
|
||||
uint32_t blocks_total = data->blocks_total;
|
||||
uint32_t blocks_read = data->blocks_read;
|
||||
if(!flipper_format_write_uint32(ff, "Blocks total", &blocks_total, 1)) break;
|
||||
if(!flipper_format_write_uint32(ff, "Blocks read", &blocks_read, 1)) break;
|
||||
|
||||
saved = true;
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
for(uint8_t i = 0; i < blocks_total; i++) {
|
||||
furi_string_printf(temp_str, "Block %d", i);
|
||||
if(!flipper_format_write_hex(
|
||||
ff,
|
||||
furi_string_get_cstr(temp_str),
|
||||
(&data->data.dump[i * sizeof(FelicaBlock)]),
|
||||
sizeof(FelicaBlock))) {
|
||||
saved = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
furi_string_free(temp_str);
|
||||
} while(false);
|
||||
|
||||
return saved;
|
||||
}
|
||||
|
||||
bool felica_is_equal(const FelicaData* data, const FelicaData* other) {
|
||||
furi_assert(data);
|
||||
furi_assert(other);
|
||||
furi_check(data);
|
||||
furi_check(other);
|
||||
|
||||
return memcmp(data, other, sizeof(FelicaData)) == 0;
|
||||
}
|
||||
@@ -119,7 +164,7 @@ const char* felica_get_device_name(const FelicaData* data, NfcDeviceNameType nam
|
||||
}
|
||||
|
||||
const uint8_t* felica_get_uid(const FelicaData* data, size_t* uid_len) {
|
||||
furi_assert(data);
|
||||
furi_check(data);
|
||||
|
||||
// Consider Manufacturer ID as UID
|
||||
if(uid_len) {
|
||||
@@ -130,7 +175,7 @@ const uint8_t* felica_get_uid(const FelicaData* data, size_t* uid_len) {
|
||||
}
|
||||
|
||||
bool felica_set_uid(FelicaData* data, const uint8_t* uid, size_t uid_len) {
|
||||
furi_assert(data);
|
||||
furi_check(data);
|
||||
|
||||
// Consider Manufacturer ID as UID
|
||||
const bool uid_valid = uid_len == FELICA_IDM_SIZE;
|
||||
@@ -145,3 +190,149 @@ FelicaData* felica_get_base_data(const FelicaData* data) {
|
||||
UNUSED(data);
|
||||
furi_crash("No base data");
|
||||
}
|
||||
|
||||
static void felica_reverse_copy_block(const uint8_t* array, uint8_t* reverse_array) {
|
||||
furi_assert(array);
|
||||
furi_assert(reverse_array);
|
||||
|
||||
for(int i = 0; i < 8; i++) {
|
||||
reverse_array[i] = array[7 - i];
|
||||
}
|
||||
}
|
||||
|
||||
void felica_calculate_session_key(
|
||||
mbedtls_des3_context* ctx,
|
||||
const uint8_t* ck,
|
||||
const uint8_t* rc,
|
||||
uint8_t* out) {
|
||||
furi_check(ctx);
|
||||
furi_check(ck);
|
||||
furi_check(rc);
|
||||
furi_check(out);
|
||||
|
||||
uint8_t iv[8];
|
||||
memset(iv, 0, 8);
|
||||
|
||||
uint8_t ck_reversed[16];
|
||||
felica_reverse_copy_block(ck, ck_reversed);
|
||||
felica_reverse_copy_block(ck + 8, ck_reversed + 8);
|
||||
|
||||
uint8_t rc_reversed[16];
|
||||
felica_reverse_copy_block(rc, rc_reversed);
|
||||
felica_reverse_copy_block(rc + 8, rc_reversed + 8);
|
||||
|
||||
mbedtls_des3_set2key_enc(ctx, ck_reversed);
|
||||
mbedtls_des3_crypt_cbc(ctx, MBEDTLS_DES_ENCRYPT, FELICA_DATA_BLOCK_SIZE, iv, rc_reversed, out);
|
||||
}
|
||||
|
||||
static bool felica_calculate_mac(
|
||||
mbedtls_des3_context* ctx,
|
||||
const uint8_t* session_key,
|
||||
const uint8_t* rc,
|
||||
const uint8_t* first_block,
|
||||
const uint8_t* data,
|
||||
const size_t length,
|
||||
uint8_t* mac) {
|
||||
furi_check((length % 8) == 0);
|
||||
|
||||
uint8_t reverse_data[8];
|
||||
uint8_t iv[8];
|
||||
uint8_t out[8];
|
||||
mbedtls_des3_set2key_enc(ctx, session_key);
|
||||
|
||||
felica_reverse_copy_block(rc, iv);
|
||||
felica_reverse_copy_block(first_block, reverse_data);
|
||||
uint8_t i = 0;
|
||||
bool error = false;
|
||||
do {
|
||||
if(mbedtls_des3_crypt_cbc(ctx, MBEDTLS_DES_ENCRYPT, 8, iv, reverse_data, out) == 0) {
|
||||
memcpy(iv, out, sizeof(iv));
|
||||
felica_reverse_copy_block(data + i, reverse_data);
|
||||
i += 8;
|
||||
} else {
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
} while(i <= length);
|
||||
|
||||
if(!error) {
|
||||
felica_reverse_copy_block(out, mac);
|
||||
}
|
||||
return !error;
|
||||
}
|
||||
|
||||
static void felica_prepare_first_block(
|
||||
FelicaMACType operation_type,
|
||||
const uint8_t* blocks,
|
||||
const uint8_t block_count,
|
||||
uint8_t* out) {
|
||||
furi_check(blocks);
|
||||
furi_check(out);
|
||||
if(operation_type == FelicaMACTypeRead) {
|
||||
memset(out, 0xFF, 8);
|
||||
for(uint8_t i = 0, j = 0; i < block_count; i++, j += 2) {
|
||||
out[j] = blocks[i];
|
||||
out[j + 1] = 0;
|
||||
}
|
||||
} else {
|
||||
furi_check(block_count == 4);
|
||||
memset(out, 0, 8);
|
||||
out[0] = blocks[0];
|
||||
out[1] = blocks[1];
|
||||
out[2] = blocks[2];
|
||||
out[4] = blocks[3];
|
||||
out[6] = FELICA_BLOCK_INDEX_MAC_A;
|
||||
}
|
||||
}
|
||||
|
||||
bool felica_check_mac(
|
||||
mbedtls_des3_context* ctx,
|
||||
const uint8_t* session_key,
|
||||
const uint8_t* rc,
|
||||
const uint8_t* blocks,
|
||||
const uint8_t block_count,
|
||||
uint8_t* data) {
|
||||
furi_check(ctx);
|
||||
furi_check(session_key);
|
||||
furi_check(rc);
|
||||
furi_check(blocks);
|
||||
furi_check(data);
|
||||
|
||||
uint8_t first_block[8];
|
||||
uint8_t mac[8];
|
||||
felica_prepare_first_block(FelicaMACTypeRead, blocks, block_count, first_block);
|
||||
|
||||
uint8_t data_size_without_mac = FELICA_DATA_BLOCK_SIZE * (block_count - 1);
|
||||
felica_calculate_mac(ctx, session_key, rc, first_block, data, data_size_without_mac, mac);
|
||||
|
||||
uint8_t* mac_ptr = data + data_size_without_mac;
|
||||
return !memcmp(mac, mac_ptr, 8);
|
||||
}
|
||||
|
||||
void felica_calculate_mac_write(
|
||||
mbedtls_des3_context* ctx,
|
||||
const uint8_t* session_key,
|
||||
const uint8_t* rc,
|
||||
const uint8_t* wcnt,
|
||||
const uint8_t* data,
|
||||
uint8_t* mac) {
|
||||
furi_check(ctx);
|
||||
furi_check(session_key);
|
||||
furi_check(rc);
|
||||
furi_check(wcnt);
|
||||
furi_check(data);
|
||||
furi_check(mac);
|
||||
|
||||
const uint8_t WCNT_length = 3;
|
||||
uint8_t block_data[WCNT_length + 1];
|
||||
uint8_t first_block[8];
|
||||
|
||||
memcpy(block_data, wcnt, WCNT_length);
|
||||
block_data[3] = FELICA_BLOCK_INDEX_STATE;
|
||||
felica_prepare_first_block(FelicaMACTypeWrite, block_data, WCNT_length + 1, first_block);
|
||||
|
||||
uint8_t session_swapped[FELICA_DATA_BLOCK_SIZE];
|
||||
memcpy(session_swapped, session_key + 8, 8);
|
||||
memcpy(session_swapped + 8, session_key, 8);
|
||||
felica_calculate_mac(ctx, session_swapped, rc, first_block, data, FELICA_DATA_BLOCK_SIZE, mac);
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <toolbox/bit_buffer.h>
|
||||
#include <nfc/protocols/nfc_device_base_i.h>
|
||||
#include <mbedtls/include/mbedtls/des.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -9,6 +10,23 @@ extern "C" {
|
||||
|
||||
#define FELICA_IDM_SIZE (8U)
|
||||
#define FELICA_PMM_SIZE (8U)
|
||||
#define FELICA_DATA_BLOCK_SIZE (16U)
|
||||
|
||||
#define FELICA_BLOCKS_TOTAL_COUNT (27U)
|
||||
#define FELICA_BLOCK_INDEX_REG (0x0EU)
|
||||
#define FELICA_BLOCK_INDEX_RC (0x80U)
|
||||
#define FELICA_BLOCK_INDEX_MAC (0x81U)
|
||||
#define FELICA_BLOCK_INDEX_ID (0x82U)
|
||||
#define FELICA_BLOCK_INDEX_D_ID (0x83U)
|
||||
#define FELICA_BLOCK_INDEX_SER_C (0x84U)
|
||||
#define FELICA_BLOCK_INDEX_SYS_C (0x85U)
|
||||
#define FELICA_BLOCK_INDEX_CKV (0x86U)
|
||||
#define FELICA_BLOCK_INDEX_CK (0x87U)
|
||||
#define FELICA_BLOCK_INDEX_MC (0x88U)
|
||||
#define FELICA_BLOCK_INDEX_WCNT (0x90U)
|
||||
#define FELICA_BLOCK_INDEX_MAC_A (0x91U)
|
||||
#define FELICA_BLOCK_INDEX_STATE (0x92U)
|
||||
#define FELICA_BLOCK_INDEX_CRC_CHECK (0xA0U)
|
||||
|
||||
#define FELICA_GUARD_TIME_US (20000U)
|
||||
#define FELICA_FDT_POLL_FC (10000U)
|
||||
@@ -23,6 +41,7 @@ extern "C" {
|
||||
#define FELICA_TIME_SLOT_8 (0x07U)
|
||||
#define FELICA_TIME_SLOT_16 (0x0FU)
|
||||
|
||||
/** @brief Type of possible Felica errors */
|
||||
typedef enum {
|
||||
FelicaErrorNone,
|
||||
FelicaErrorNotPresent,
|
||||
@@ -35,22 +54,83 @@ typedef enum {
|
||||
FelicaErrorTimeout,
|
||||
} FelicaError;
|
||||
|
||||
/** @brief Separate type for card key block. Used in authentication process */
|
||||
typedef struct {
|
||||
uint8_t data[FELICA_DATA_BLOCK_SIZE];
|
||||
} FelicaCardKey;
|
||||
|
||||
/** @brief In Felica there two types of auth. Internal is the first one, after
|
||||
* which external became possible. Here are two flags representing which one
|
||||
* was passed */
|
||||
typedef struct {
|
||||
bool internal : 1;
|
||||
bool external : 1;
|
||||
} FelicaAuthenticationStatus;
|
||||
|
||||
/** @brief Struct which controls the process of authentication and can be passed as
|
||||
* a parameter to the application level. In order to force user to fill card key block data. */
|
||||
typedef struct {
|
||||
bool skip_auth; /**< By default it is true, so auth is skipped. By setting this to false several auth steps will be performed in order to pass auth*/
|
||||
FelicaCardKey
|
||||
card_key; /**< User must fill this field with known card key in order to pass auth*/
|
||||
FelicaAuthenticationStatus auth_status; /**< Authentication status*/
|
||||
} FelicaAuthenticationContext;
|
||||
|
||||
/** @brief Felica ID block */
|
||||
typedef struct {
|
||||
uint8_t data[FELICA_IDM_SIZE];
|
||||
} FelicaIDm;
|
||||
|
||||
/** @brief Felica PMm block */
|
||||
typedef struct {
|
||||
uint8_t data[FELICA_PMM_SIZE];
|
||||
} FelicaPMm;
|
||||
|
||||
/** @brief Felica block with status flags indicating last operation with it.
|
||||
* See Felica manual for more details on status codes. */
|
||||
typedef struct {
|
||||
uint8_t SF1; /**< Status flag 1, equals to 0 when success*/
|
||||
uint8_t SF2; /**< Status flag 2, equals to 0 when success*/
|
||||
uint8_t data[FELICA_DATA_BLOCK_SIZE]; /**< Block data */
|
||||
} FelicaBlock;
|
||||
|
||||
/** @brief Felica filesystem structure */
|
||||
typedef struct {
|
||||
FelicaBlock spad[14];
|
||||
FelicaBlock reg;
|
||||
FelicaBlock rc;
|
||||
FelicaBlock mac;
|
||||
FelicaBlock id;
|
||||
FelicaBlock d_id;
|
||||
FelicaBlock ser_c;
|
||||
FelicaBlock sys_c;
|
||||
FelicaBlock ckv;
|
||||
FelicaBlock ck;
|
||||
FelicaBlock mc;
|
||||
FelicaBlock wcnt;
|
||||
FelicaBlock mac_a;
|
||||
FelicaBlock state;
|
||||
FelicaBlock crc_check;
|
||||
} FelicaFileSystem;
|
||||
|
||||
/** @brief Union which represents filesystem in junction with plain data dump */
|
||||
typedef union {
|
||||
FelicaFileSystem fs;
|
||||
uint8_t dump[sizeof(FelicaFileSystem)];
|
||||
} FelicaFSUnion;
|
||||
|
||||
/** @brief Structure used to store Felica data and additional values about reading */
|
||||
typedef struct {
|
||||
FelicaIDm idm;
|
||||
FelicaPMm pmm;
|
||||
uint8_t blocks_total;
|
||||
uint8_t blocks_read;
|
||||
FelicaFSUnion data;
|
||||
} FelicaData;
|
||||
|
||||
extern const NfcDeviceBase nfc_device_felica;
|
||||
|
||||
FelicaData* felica_alloc();
|
||||
FelicaData* felica_alloc(void);
|
||||
|
||||
void felica_free(FelicaData* data);
|
||||
|
||||
@@ -74,6 +154,27 @@ bool felica_set_uid(FelicaData* data, const uint8_t* uid, size_t uid_len);
|
||||
|
||||
FelicaData* felica_get_base_data(const FelicaData* data);
|
||||
|
||||
void felica_calculate_session_key(
|
||||
mbedtls_des3_context* ctx,
|
||||
const uint8_t* ck,
|
||||
const uint8_t* rc,
|
||||
uint8_t* out);
|
||||
|
||||
bool felica_check_mac(
|
||||
mbedtls_des3_context* ctx,
|
||||
const uint8_t* session_key,
|
||||
const uint8_t* rc,
|
||||
const uint8_t* blocks,
|
||||
const uint8_t block_count,
|
||||
uint8_t* data);
|
||||
|
||||
void felica_calculate_mac_write(
|
||||
mbedtls_des3_context* ctx,
|
||||
const uint8_t* session_key,
|
||||
const uint8_t* rc,
|
||||
const uint8_t* wcnt,
|
||||
const uint8_t* data,
|
||||
uint8_t* mac);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -3,6 +3,11 @@
|
||||
#include <nfc/protocols/nfc_poller_base.h>
|
||||
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
#define TAG "FelicaPoller"
|
||||
|
||||
typedef NfcCommand (*FelicaPollerReadHandler)(FelicaPoller* instance);
|
||||
|
||||
const FelicaData* felica_poller_get_data(FelicaPoller* instance) {
|
||||
furi_assert(instance);
|
||||
@@ -23,6 +28,8 @@ static FelicaPoller* felica_poller_alloc(Nfc* nfc) {
|
||||
nfc_set_guard_time_us(instance->nfc, FELICA_GUARD_TIME_US);
|
||||
nfc_set_fdt_poll_fc(instance->nfc, FELICA_FDT_POLL_FC);
|
||||
nfc_set_fdt_poll_poll_us(instance->nfc, FELICA_POLL_POLL_MIN_US);
|
||||
|
||||
mbedtls_des3_init(&instance->auth.des_context);
|
||||
instance->data = felica_alloc();
|
||||
|
||||
instance->felica_event.data = &instance->felica_event_data;
|
||||
@@ -40,6 +47,7 @@ static void felica_poller_free(FelicaPoller* instance) {
|
||||
furi_assert(instance->rx_buffer);
|
||||
furi_assert(instance->data);
|
||||
|
||||
mbedtls_des3_free(&instance->auth.des_context);
|
||||
bit_buffer_free(instance->tx_buffer);
|
||||
bit_buffer_free(instance->rx_buffer);
|
||||
felica_free(instance->data);
|
||||
@@ -55,6 +63,212 @@ static void
|
||||
instance->context = context;
|
||||
}
|
||||
|
||||
NfcCommand felica_poller_state_handler_idle(FelicaPoller* instance) {
|
||||
FURI_LOG_D(TAG, "Idle");
|
||||
felica_reset(instance->data);
|
||||
instance->state = FelicaPollerStateActivated;
|
||||
|
||||
return NfcCommandContinue;
|
||||
}
|
||||
|
||||
NfcCommand felica_poller_state_handler_activate(FelicaPoller* instance) {
|
||||
FURI_LOG_D(TAG, "Activate");
|
||||
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
|
||||
FelicaError error = felica_poller_activate(instance, instance->data);
|
||||
if(error == FelicaErrorNone) {
|
||||
furi_hal_random_fill_buf(instance->data->data.fs.rc.data, FELICA_DATA_BLOCK_SIZE);
|
||||
|
||||
instance->felica_event.type = FelicaPollerEventTypeRequestAuthContext;
|
||||
instance->felica_event_data.auth_context = &instance->auth.context;
|
||||
|
||||
instance->callback(instance->general_event, instance->context);
|
||||
|
||||
bool skip_auth = instance->auth.context.skip_auth;
|
||||
instance->state = skip_auth ? FelicaPollerStateReadBlocks :
|
||||
FelicaPollerStateAuthenticateInternal;
|
||||
} else if(error != FelicaErrorTimeout) {
|
||||
instance->felica_event.type = FelicaPollerEventTypeError;
|
||||
instance->felica_event_data.error = error;
|
||||
instance->state = FelicaPollerStateReadFailed;
|
||||
}
|
||||
return command;
|
||||
}
|
||||
|
||||
NfcCommand felica_poller_state_handler_auth_internal(FelicaPoller* instance) {
|
||||
FURI_LOG_D(TAG, "Auth Internal");
|
||||
|
||||
felica_calculate_session_key(
|
||||
&instance->auth.des_context,
|
||||
instance->auth.context.card_key.data,
|
||||
instance->data->data.fs.rc.data,
|
||||
instance->auth.session_key.data);
|
||||
|
||||
instance->state = FelicaPollerStateReadBlocks;
|
||||
|
||||
uint8_t blocks[3] = {FELICA_BLOCK_INDEX_RC, 0, 0};
|
||||
FelicaPollerWriteCommandResponse* tx_resp;
|
||||
do {
|
||||
FelicaError error = felica_poller_write_blocks(
|
||||
instance, 1, blocks, instance->data->data.fs.rc.data, &tx_resp);
|
||||
if((error != FelicaErrorNone) || (tx_resp->SF1 != 0) || (tx_resp->SF2 != 0)) break;
|
||||
|
||||
blocks[0] = FELICA_BLOCK_INDEX_ID;
|
||||
blocks[1] = FELICA_BLOCK_INDEX_WCNT;
|
||||
blocks[2] = FELICA_BLOCK_INDEX_MAC_A;
|
||||
FelicaPollerReadCommandResponse* rx_resp;
|
||||
error = felica_poller_read_blocks(instance, sizeof(blocks), blocks, &rx_resp);
|
||||
if(error != FelicaErrorNone || rx_resp->SF1 != 0 || rx_resp->SF2 != 0) break;
|
||||
|
||||
if(felica_check_mac(
|
||||
&instance->auth.des_context,
|
||||
instance->auth.session_key.data,
|
||||
instance->data->data.fs.rc.data,
|
||||
blocks,
|
||||
rx_resp->block_count,
|
||||
rx_resp->data)) {
|
||||
instance->auth.context.auth_status.internal = true;
|
||||
instance->data->data.fs.wcnt.SF1 = 0;
|
||||
instance->data->data.fs.wcnt.SF2 = 0;
|
||||
memcpy(
|
||||
instance->data->data.fs.wcnt.data,
|
||||
rx_resp->data + FELICA_DATA_BLOCK_SIZE,
|
||||
FELICA_DATA_BLOCK_SIZE);
|
||||
instance->state = FelicaPollerStateAuthenticateExternal;
|
||||
}
|
||||
} while(false);
|
||||
|
||||
return NfcCommandContinue;
|
||||
}
|
||||
|
||||
NfcCommand felica_poller_state_handler_auth_external(FelicaPoller* instance) {
|
||||
FURI_LOG_D(TAG, "Auth External");
|
||||
instance->state = FelicaPollerStateReadBlocks;
|
||||
uint8_t blocks[2];
|
||||
|
||||
instance->data->data.fs.state.data[0] = 1;
|
||||
FelicaAuthentication* auth = &instance->auth;
|
||||
felica_calculate_mac_write(
|
||||
&auth->des_context,
|
||||
auth->session_key.data,
|
||||
instance->data->data.fs.rc.data,
|
||||
instance->data->data.fs.wcnt.data,
|
||||
instance->data->data.fs.state.data,
|
||||
instance->data->data.fs.mac_a.data);
|
||||
|
||||
memcpy(instance->data->data.fs.mac_a.data + 8, instance->data->data.fs.wcnt.data, 3); //-V1086
|
||||
|
||||
uint8_t tx_data[FELICA_DATA_BLOCK_SIZE * 2];
|
||||
memcpy(tx_data, instance->data->data.fs.state.data, FELICA_DATA_BLOCK_SIZE);
|
||||
memcpy(
|
||||
tx_data + FELICA_DATA_BLOCK_SIZE,
|
||||
instance->data->data.fs.mac_a.data,
|
||||
FELICA_DATA_BLOCK_SIZE);
|
||||
|
||||
do {
|
||||
blocks[0] = FELICA_BLOCK_INDEX_STATE;
|
||||
blocks[1] = FELICA_BLOCK_INDEX_MAC_A;
|
||||
FelicaPollerWriteCommandResponse* tx_resp;
|
||||
FelicaError error = felica_poller_write_blocks(instance, 2, blocks, tx_data, &tx_resp);
|
||||
if(error != FelicaErrorNone || tx_resp->SF1 != 0 || tx_resp->SF2 != 0) break;
|
||||
|
||||
FelicaPollerReadCommandResponse* rx_resp;
|
||||
error = felica_poller_read_blocks(instance, 1, blocks, &rx_resp);
|
||||
if(error != FelicaErrorNone || rx_resp->SF1 != 0 || rx_resp->SF2 != 0) break;
|
||||
|
||||
instance->data->data.fs.state.SF1 = 0;
|
||||
instance->data->data.fs.state.SF2 = 0;
|
||||
memcpy(instance->data->data.fs.state.data, rx_resp->data, FELICA_DATA_BLOCK_SIZE);
|
||||
instance->auth.context.auth_status.external = instance->data->data.fs.state.data[0];
|
||||
} while(false);
|
||||
instance->state = FelicaPollerStateReadBlocks;
|
||||
return NfcCommandContinue;
|
||||
}
|
||||
|
||||
NfcCommand felica_poller_state_handler_read_blocks(FelicaPoller* instance) {
|
||||
FURI_LOG_D(TAG, "Read Blocks");
|
||||
|
||||
uint8_t block_count = 1;
|
||||
uint8_t block_list[4] = {0, 0, 0, 0};
|
||||
block_list[0] = instance->block_index;
|
||||
|
||||
instance->block_index++;
|
||||
if(instance->block_index == FELICA_BLOCK_INDEX_REG + 1) {
|
||||
instance->block_index = FELICA_BLOCK_INDEX_RC;
|
||||
} else if(instance->block_index == FELICA_BLOCK_INDEX_MC + 1) {
|
||||
instance->block_index = FELICA_BLOCK_INDEX_WCNT;
|
||||
} else if(instance->block_index == FELICA_BLOCK_INDEX_STATE + 1) {
|
||||
instance->block_index = FELICA_BLOCK_INDEX_CRC_CHECK;
|
||||
}
|
||||
|
||||
FelicaPollerReadCommandResponse* response;
|
||||
FelicaError error = felica_poller_read_blocks(instance, block_count, block_list, &response);
|
||||
if(error == FelicaErrorNone) {
|
||||
block_count = (response->SF1 == 0) ? response->block_count : block_count;
|
||||
uint8_t* data_ptr =
|
||||
instance->data->data.dump + instance->data->blocks_total * sizeof(FelicaBlock);
|
||||
|
||||
*data_ptr++ = response->SF1;
|
||||
*data_ptr++ = response->SF2;
|
||||
|
||||
if(response->SF1 == 0) {
|
||||
uint8_t* response_data_ptr = response->data;
|
||||
instance->data->blocks_read++;
|
||||
memcpy(data_ptr, response_data_ptr, FELICA_DATA_BLOCK_SIZE);
|
||||
} else {
|
||||
memset(data_ptr, 0, FELICA_DATA_BLOCK_SIZE);
|
||||
}
|
||||
instance->data->blocks_total++;
|
||||
|
||||
if(instance->data->blocks_total == FELICA_BLOCKS_TOTAL_COUNT) {
|
||||
instance->state = FelicaPollerStateReadSuccess;
|
||||
}
|
||||
} else {
|
||||
instance->felica_event.type = FelicaPollerEventTypeError;
|
||||
instance->felica_event_data.error = error;
|
||||
instance->state = FelicaPollerStateReadFailed;
|
||||
}
|
||||
|
||||
return NfcCommandContinue;
|
||||
}
|
||||
|
||||
NfcCommand felica_poller_state_handler_read_success(FelicaPoller* instance) {
|
||||
FURI_LOG_D(TAG, "Read Success");
|
||||
|
||||
if(!instance->auth.context.auth_status.internal ||
|
||||
!instance->auth.context.auth_status.external) {
|
||||
instance->data->blocks_read--;
|
||||
instance->felica_event.type = FelicaPollerEventTypeIncomplete;
|
||||
} else {
|
||||
memcpy(
|
||||
instance->data->data.fs.ck.data,
|
||||
instance->auth.context.card_key.data,
|
||||
FELICA_DATA_BLOCK_SIZE);
|
||||
instance->felica_event.type = FelicaPollerEventTypeReady;
|
||||
}
|
||||
|
||||
instance->felica_event_data.error = FelicaErrorNone;
|
||||
return instance->callback(instance->general_event, instance->context);
|
||||
}
|
||||
|
||||
NfcCommand felica_poller_state_handler_read_failed(FelicaPoller* instance) {
|
||||
FURI_LOG_D(TAG, "Read Fail");
|
||||
instance->callback(instance->general_event, instance->context);
|
||||
|
||||
return NfcCommandStop;
|
||||
}
|
||||
|
||||
static const FelicaPollerReadHandler felica_poller_handler[FelicaPollerStateNum] = {
|
||||
[FelicaPollerStateIdle] = felica_poller_state_handler_idle,
|
||||
[FelicaPollerStateActivated] = felica_poller_state_handler_activate,
|
||||
[FelicaPollerStateAuthenticateInternal] = felica_poller_state_handler_auth_internal,
|
||||
[FelicaPollerStateAuthenticateExternal] = felica_poller_state_handler_auth_external,
|
||||
[FelicaPollerStateReadBlocks] = felica_poller_state_handler_read_blocks,
|
||||
[FelicaPollerStateReadSuccess] = felica_poller_state_handler_read_success,
|
||||
[FelicaPollerStateReadFailed] = felica_poller_state_handler_read_failed,
|
||||
};
|
||||
|
||||
static NfcCommand felica_poller_run(NfcGenericEvent event, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(event.protocol == NfcProtocolInvalid);
|
||||
@@ -65,24 +279,7 @@ static NfcCommand felica_poller_run(NfcGenericEvent event, void* context) {
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
|
||||
if(nfc_event->type == NfcEventTypePollerReady) {
|
||||
if(instance->state != FelicaPollerStateActivated) {
|
||||
FelicaError error = felica_poller_activate(instance, instance->data);
|
||||
if(error == FelicaErrorNone) {
|
||||
instance->felica_event.type = FelicaPollerEventTypeReady;
|
||||
instance->felica_event_data.error = error;
|
||||
command = instance->callback(instance->general_event, instance->context);
|
||||
} else {
|
||||
instance->felica_event.type = FelicaPollerEventTypeError;
|
||||
instance->felica_event_data.error = error;
|
||||
command = instance->callback(instance->general_event, instance->context);
|
||||
// Add delay to switch context
|
||||
furi_delay_ms(100);
|
||||
}
|
||||
} else {
|
||||
instance->felica_event.type = FelicaPollerEventTypeReady;
|
||||
instance->felica_event_data.error = FelicaErrorNone;
|
||||
command = instance->callback(instance->general_event, instance->context);
|
||||
}
|
||||
command = felica_poller_handler[instance->state](instance);
|
||||
}
|
||||
|
||||
return command;
|
||||
|
||||
@@ -19,14 +19,33 @@ typedef struct FelicaPoller FelicaPoller;
|
||||
*/
|
||||
typedef enum {
|
||||
FelicaPollerEventTypeError, /**< An error occured during activation procedure. */
|
||||
FelicaPollerEventTypeReady, /**< The card was activated by the poller. */
|
||||
FelicaPollerEventTypeReady, /**< The card was activated and fully read by the poller. */
|
||||
FelicaPollerEventTypeIncomplete, /**< The card was activated and partly read by the poller. */
|
||||
FelicaPollerEventTypeRequestAuthContext, /**< Authentication context was requested by poller. */
|
||||
} FelicaPollerEventType;
|
||||
|
||||
/**
|
||||
* @brief Stucture for holding Felica session key which is calculated from rc and ck.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t data[FELICA_DATA_BLOCK_SIZE];
|
||||
} FelicaSessionKey;
|
||||
|
||||
/**
|
||||
* @brief Structure used to hold authentication related fields.
|
||||
*/
|
||||
typedef struct {
|
||||
mbedtls_des3_context des_context; /**< Context for mbedtls des functions. */
|
||||
FelicaSessionKey session_key; /**< Calculated session key. */
|
||||
FelicaAuthenticationContext context; /**< Public auth context provided to upper levels. */
|
||||
} FelicaAuthentication;
|
||||
|
||||
/**
|
||||
* @brief Felica poller event data.
|
||||
*/
|
||||
typedef union {
|
||||
FelicaError error; /**< Error code indicating card activation fail reason. */
|
||||
FelicaAuthenticationContext* auth_context; /**< Authentication context to be filled by user. */
|
||||
} FelicaPollerEventData;
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,6 +3,11 @@
|
||||
#include <nfc/helpers/felica_crc.h>
|
||||
|
||||
#define TAG "FelicaPoller"
|
||||
#define FELICA_CMD_READ_WITHOUT_ENCRYPTION (0x06U)
|
||||
#define FELICA_CMD_WRITE_WITHOUT_ENCRYPTION (0x08U)
|
||||
|
||||
#define FELICA_SERVICE_RW_ACCESS (0x0009U)
|
||||
#define FELICA_SERVICE_RO_ACCESS (0x000BU)
|
||||
|
||||
static FelicaError felica_poller_process_error(NfcError error) {
|
||||
switch(error) {
|
||||
@@ -15,8 +20,8 @@ static FelicaError felica_poller_process_error(NfcError error) {
|
||||
}
|
||||
}
|
||||
|
||||
static FelicaError felica_poller_frame_exchange(
|
||||
FelicaPoller* instance,
|
||||
FelicaError felica_poller_frame_exchange(
|
||||
const FelicaPoller* instance,
|
||||
const BitBuffer* tx_buffer,
|
||||
BitBuffer* rx_buffer,
|
||||
uint32_t fwt) {
|
||||
@@ -93,11 +98,105 @@ FelicaError felica_poller_polling(
|
||||
return error;
|
||||
}
|
||||
|
||||
static void felica_poller_prepare_tx_buffer(
|
||||
const FelicaPoller* instance,
|
||||
const uint8_t command,
|
||||
const uint16_t service_code,
|
||||
const uint8_t block_count,
|
||||
const uint8_t* const blocks,
|
||||
const uint8_t data_block_count,
|
||||
const uint8_t* data) {
|
||||
FelicaCommandHeader cmd = {
|
||||
.code = command,
|
||||
.idm = instance->data->idm,
|
||||
.service_num = 1,
|
||||
.service_code = service_code,
|
||||
.block_count = block_count,
|
||||
};
|
||||
|
||||
FelicaBlockListElement block_list[4] = {{0}, {0}, {0}, {0}};
|
||||
for(uint8_t i = 0; i < block_count; i++) {
|
||||
block_list[i].length = 1;
|
||||
block_list[i].block_number = blocks[i];
|
||||
}
|
||||
|
||||
uint8_t block_list_count = block_count;
|
||||
uint8_t block_list_size = block_list_count * sizeof(FelicaBlockListElement);
|
||||
uint8_t total_size = sizeof(FelicaCommandHeader) + 1 + block_list_size +
|
||||
data_block_count * FELICA_DATA_BLOCK_SIZE;
|
||||
bit_buffer_reset(instance->tx_buffer);
|
||||
bit_buffer_append_byte(instance->tx_buffer, total_size);
|
||||
bit_buffer_append_bytes(instance->tx_buffer, (uint8_t*)&cmd, sizeof(FelicaCommandHeader));
|
||||
bit_buffer_append_bytes(instance->tx_buffer, (uint8_t*)&block_list, block_list_size);
|
||||
|
||||
if(data_block_count != 0) {
|
||||
bit_buffer_append_bytes(
|
||||
instance->tx_buffer, data, data_block_count * FELICA_DATA_BLOCK_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
FelicaError felica_poller_read_blocks(
|
||||
FelicaPoller* instance,
|
||||
const uint8_t block_count,
|
||||
const uint8_t* const block_numbers,
|
||||
FelicaPollerReadCommandResponse** const response_ptr) {
|
||||
furi_assert(instance);
|
||||
furi_assert(block_count <= 4);
|
||||
furi_assert(block_numbers);
|
||||
furi_assert(response_ptr);
|
||||
|
||||
felica_poller_prepare_tx_buffer(
|
||||
instance,
|
||||
FELICA_CMD_READ_WITHOUT_ENCRYPTION,
|
||||
FELICA_SERVICE_RO_ACCESS,
|
||||
block_count,
|
||||
block_numbers,
|
||||
0,
|
||||
NULL);
|
||||
bit_buffer_reset(instance->rx_buffer);
|
||||
|
||||
FelicaError error = felica_poller_frame_exchange(
|
||||
instance, instance->tx_buffer, instance->rx_buffer, FELICA_POLLER_POLLING_FWT);
|
||||
if(error == FelicaErrorNone) {
|
||||
*response_ptr = (FelicaPollerReadCommandResponse*)bit_buffer_get_data(instance->rx_buffer);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
FelicaError felica_poller_write_blocks(
|
||||
const FelicaPoller* instance,
|
||||
const uint8_t block_count,
|
||||
const uint8_t* const block_numbers,
|
||||
const uint8_t* data,
|
||||
FelicaPollerWriteCommandResponse** const response_ptr) {
|
||||
furi_assert(instance);
|
||||
furi_assert(block_count <= 2);
|
||||
furi_assert(block_numbers);
|
||||
furi_assert(data);
|
||||
furi_assert(response_ptr);
|
||||
|
||||
felica_poller_prepare_tx_buffer(
|
||||
instance,
|
||||
FELICA_CMD_WRITE_WITHOUT_ENCRYPTION,
|
||||
FELICA_SERVICE_RW_ACCESS,
|
||||
block_count,
|
||||
block_numbers,
|
||||
block_count,
|
||||
data);
|
||||
bit_buffer_reset(instance->rx_buffer);
|
||||
|
||||
FelicaError error = felica_poller_frame_exchange(
|
||||
instance, instance->tx_buffer, instance->rx_buffer, FELICA_POLLER_POLLING_FWT);
|
||||
if(error == FelicaErrorNone) {
|
||||
*response_ptr =
|
||||
(FelicaPollerWriteCommandResponse*)bit_buffer_get_data(instance->rx_buffer);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
FelicaError felica_poller_activate(FelicaPoller* instance, FelicaData* data) {
|
||||
furi_assert(instance);
|
||||
|
||||
felica_reset(data);
|
||||
|
||||
FelicaError ret;
|
||||
|
||||
do {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user