Compare commits
219 Commits
8c4716f170
...
d1832d5e90
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d1832d5e90 | ||
|
|
ad66d3b3c6 | ||
|
|
531ba24e9a | ||
|
|
1543170f4c | ||
|
|
c0be669a30 | ||
|
|
17b122990f | ||
|
|
1e1d9fcb69 | ||
|
|
6f6074dc01 | ||
|
|
25d24f1e4c | ||
|
|
7642d67cae | ||
|
|
5dbe1cf0bc | ||
|
|
8a3142da04 | ||
|
|
b0dc8a3940 | ||
|
|
f711b3f929 | ||
|
|
9524a5ef74 | ||
|
|
e487bcd2f8 | ||
|
|
880e7bb1a8 | ||
|
|
fa2d516017 | ||
|
|
e8c6e70a5f | ||
|
|
333f45d2c6 | ||
|
|
4fc6f3b245 | ||
|
|
a3e07586ee | ||
|
|
9fd8d30b6f | ||
|
|
81e490117a | ||
|
|
176c3618b1 | ||
|
|
dba34f25fe | ||
|
|
6ceb71e327 | ||
|
|
60c96b97c6 | ||
|
|
ff41b65077 | ||
|
|
fe637da8fc | ||
|
|
baf661d47d | ||
|
|
384e950ab3 | ||
|
|
0d991e6960 | ||
|
|
d874fcd5cb | ||
|
|
5a58004bbb | ||
|
|
4b5f829375 | ||
|
|
357fbfe63b | ||
|
|
45e78fbdc2 | ||
|
|
bf262efed5 | ||
|
|
12f898f0ff | ||
|
|
c29941aefb | ||
|
|
06b8b9bf1e | ||
|
|
3991db4b36 | ||
|
|
279a33dc8c | ||
|
|
948dafc434 | ||
|
|
27a8f29a68 | ||
|
|
7081d76e7b | ||
|
|
60baf2a608 | ||
|
|
1ac1f0b441 | ||
|
|
406cb8b711 | ||
|
|
dc3d56523a | ||
|
|
e4830a6ebc | ||
|
|
2d8f262dd4 | ||
|
|
96d97af4e6 | ||
|
|
16b976478c | ||
|
|
9cedac9adf | ||
|
|
508dbe4984 | ||
|
|
b7f406d43b | ||
|
|
849aa0f784 | ||
|
|
df78ba8e09 | ||
|
|
31e47e97bd | ||
|
|
085c8008db | ||
|
|
376319cbc8 | ||
|
|
728320b713 | ||
|
|
b55677673f | ||
|
|
c41fe8e4e4 | ||
|
|
9b9dce3676 | ||
|
|
e52e30c56d | ||
|
|
b698126c36 | ||
|
|
f141a67788 | ||
|
|
dec00feb7b | ||
|
|
61744b8d01 | ||
|
|
119c7fe5f1 | ||
|
|
e9984f8b4c | ||
|
|
a38a62fe79 | ||
|
|
e2e4dcc2f8 | ||
|
|
ea5fe0ec86 | ||
|
|
8a08fd5da9 | ||
|
|
13a0a92f0d | ||
|
|
48eb15c79c | ||
|
|
8ee66c3e9b | ||
|
|
e18056ba78 | ||
|
|
b60ba76551 | ||
|
|
5670397c3b | ||
|
|
6ff3f821b2 | ||
|
|
8bc7723faa | ||
|
|
09f3dc74bc | ||
|
|
0d7f305da1 | ||
|
|
c7bf3d3066 | ||
|
|
579e3b5f26 | ||
|
|
a74bcbaeb6 | ||
|
|
3c1d59f152 | ||
|
|
ec218060ac | ||
|
|
303c266eba | ||
|
|
f3904dc5a4 | ||
|
|
04c780f48a | ||
|
|
8d0faae820 | ||
|
|
a50fb2ac5e | ||
|
|
fd0dd34a03 | ||
|
|
3ab17e596b | ||
|
|
33a7478b0a | ||
|
|
747e81fe1e | ||
|
|
cfde6350a6 | ||
|
|
5c52bb7621 | ||
|
|
e40349350d | ||
|
|
a0f6a23062 | ||
|
|
3481252ef7 | ||
|
|
14a180975a | ||
|
|
bb9b52ad3e | ||
|
|
7e86f634ba | ||
|
|
55b463248c | ||
|
|
09148b2d6e | ||
|
|
3d9efa98d4 | ||
|
|
ae9038da36 | ||
|
|
8fb679e098 | ||
|
|
af891bdd4a | ||
|
|
f6d6a626ea | ||
|
|
bf236f5e15 | ||
|
|
2fc2486b91 | ||
|
|
7a6720384f | ||
|
|
be0aa536ba | ||
|
|
df6b81274b | ||
|
|
f785ce1f91 | ||
|
|
0c592ff84a | ||
|
|
8bcd76636e | ||
|
|
86c9b0077c | ||
|
|
e28446de49 | ||
|
|
52434f77a3 | ||
|
|
3e5d499b44 | ||
|
|
577a4ba5a5 | ||
|
|
996b15e204 | ||
|
|
fc15d5ccce | ||
|
|
1edc74acff | ||
|
|
c5fd214f80 | ||
|
|
e82001aaa6 | ||
|
|
e682e02bca | ||
|
|
ae95d75d2e | ||
|
|
84cc3816c4 | ||
|
|
94bb1ad354 | ||
|
|
be4dec77da | ||
|
|
287defdfc5 | ||
|
|
cb6cf95714 | ||
|
|
f82484d447 | ||
|
|
e64de44b73 | ||
|
|
d3c0618699 | ||
|
|
b501d47943 | ||
|
|
d21e5bd56e | ||
|
|
1ad81aaf1f | ||
|
|
5435679420 | ||
|
|
d294b5e256 | ||
|
|
bc77681e65 | ||
|
|
460f573446 | ||
|
|
215466e2d6 | ||
|
|
625eb0a4a5 | ||
|
|
5f582abfe0 | ||
|
|
5c58faa3f5 | ||
|
|
28d9b21483 | ||
|
|
0d35596d96 | ||
|
|
631e532245 | ||
|
|
b29c0d3fb5 | ||
|
|
e74aa2d042 | ||
|
|
e1ff6da6cd | ||
|
|
c02d8beed9 | ||
|
|
f2a8485176 | ||
|
|
dc6da827fa | ||
|
|
3f164ef30d | ||
|
|
afa46b0855 | ||
|
|
e69875954b | ||
|
|
57689a1e0f | ||
|
|
f8c8e63adf | ||
|
|
d4aeee64fa | ||
|
|
661b4b181a | ||
|
|
bb81e86495 | ||
|
|
3cdcd644fe | ||
|
|
fffacfbe26 | ||
|
|
1d5ca45675 | ||
|
|
983537996c | ||
|
|
3e04b73c1e | ||
|
|
830daa8b51 | ||
|
|
543402f64a | ||
|
|
24e7bda854 | ||
|
|
8042f94570 | ||
|
|
bb650c4e87 | ||
|
|
208ea6fbb0 | ||
|
|
a426762605 | ||
|
|
2ee2e8f4ba | ||
|
|
cc285ab05e | ||
|
|
06ad32109d | ||
|
|
5a0f7e20ba | ||
|
|
cf6a1a7301 | ||
|
|
3a70d3b7f6 | ||
|
|
1060f7b037 | ||
|
|
5352e4eb63 | ||
|
|
b0b20392a5 | ||
|
|
14777a7585 | ||
|
|
a5fa342ffa | ||
|
|
90eb608f08 | ||
|
|
be02738c4a | ||
|
|
dad1b0622b | ||
|
|
cb227dafd1 | ||
|
|
f3603e3c04 | ||
|
|
eb74bcd41b | ||
|
|
7b730dd08a | ||
|
|
ce74a35066 | ||
|
|
55692ee82f | ||
|
|
20deb6458a | ||
|
|
cca004a42d | ||
|
|
6c60c96d7c | ||
|
|
b3f1db8f9e | ||
|
|
badf87fe67 | ||
|
|
dc622321b9 | ||
|
|
fd29e190b7 | ||
|
|
3db456da98 | ||
|
|
44d7b5b1ce | ||
|
|
97e0a3026f | ||
|
|
3773428a21 | ||
|
|
b629ae18f2 | ||
|
|
073c87f37d | ||
|
|
0bc3828fd9 |
@ -12,7 +12,7 @@
|
||||
#include <nfc/protocols/mf_ultralight/mf_ultralight_poller_sync.h>
|
||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
||||
|
||||
#include <nfc/helpers/nfc_dict.h>
|
||||
#include <toolbox/keys_dict.h>
|
||||
#include <nfc/nfc.h>
|
||||
|
||||
#include "../minunit.h"
|
||||
@ -443,36 +443,36 @@ MU_TEST(mf_classic_dict_test) {
|
||||
"Remove test dict failed");
|
||||
}
|
||||
|
||||
NfcDict* dict = nfc_dict_alloc(
|
||||
NFC_APP_MF_CLASSIC_DICT_UNIT_TEST_PATH, NfcDictModeOpenAlways, sizeof(MfClassicKey));
|
||||
mu_assert(dict != NULL, "nfc_dict_alloc() failed");
|
||||
KeysDict* dict = keys_dict_alloc(
|
||||
NFC_APP_MF_CLASSIC_DICT_UNIT_TEST_PATH, KeysDictModeOpenAlways, sizeof(MfClassicKey));
|
||||
mu_assert(dict != NULL, "keys_dict_alloc() failed");
|
||||
|
||||
size_t dict_keys_total = nfc_dict_get_total_keys(dict);
|
||||
mu_assert(dict_keys_total == 0, "nfc_dict_keys_total() failed");
|
||||
size_t dict_keys_total = keys_dict_get_total_keys(dict);
|
||||
mu_assert(dict_keys_total == 0, "keys_dict_keys_total() failed");
|
||||
|
||||
const uint32_t test_key_num = 30;
|
||||
MfClassicKey* key_arr_ref = malloc(test_key_num * sizeof(MfClassicKey));
|
||||
for(size_t i = 0; i < test_key_num; i++) {
|
||||
furi_hal_random_fill_buf(key_arr_ref[i].data, sizeof(MfClassicKey));
|
||||
mu_assert(
|
||||
nfc_dict_add_key(dict, key_arr_ref[i].data, sizeof(MfClassicKey)), "add key failed");
|
||||
keys_dict_add_key(dict, key_arr_ref[i].data, sizeof(MfClassicKey)), "add key failed");
|
||||
|
||||
size_t dict_keys_total = nfc_dict_get_total_keys(dict);
|
||||
mu_assert(dict_keys_total == (i + 1), "nfc_dict_keys_total() failed");
|
||||
size_t dict_keys_total = keys_dict_get_total_keys(dict);
|
||||
mu_assert(dict_keys_total == (i + 1), "keys_dict_keys_total() failed");
|
||||
}
|
||||
|
||||
nfc_dict_free(dict);
|
||||
keys_dict_free(dict);
|
||||
|
||||
dict = nfc_dict_alloc(
|
||||
NFC_APP_MF_CLASSIC_DICT_UNIT_TEST_PATH, NfcDictModeOpenAlways, sizeof(MfClassicKey));
|
||||
mu_assert(dict != NULL, "nfc_dict_alloc() failed");
|
||||
dict = keys_dict_alloc(
|
||||
NFC_APP_MF_CLASSIC_DICT_UNIT_TEST_PATH, KeysDictModeOpenAlways, sizeof(MfClassicKey));
|
||||
mu_assert(dict != NULL, "keys_dict_alloc() failed");
|
||||
|
||||
dict_keys_total = nfc_dict_get_total_keys(dict);
|
||||
mu_assert(dict_keys_total == test_key_num, "nfc_dict_keys_total() failed");
|
||||
dict_keys_total = keys_dict_get_total_keys(dict);
|
||||
mu_assert(dict_keys_total == test_key_num, "keys_dict_keys_total() failed");
|
||||
|
||||
MfClassicKey key_dut = {};
|
||||
size_t key_idx = 0;
|
||||
while(nfc_dict_get_next_key(dict, key_dut.data, sizeof(MfClassicKey))) {
|
||||
while(keys_dict_get_next_key(dict, key_dut.data, sizeof(MfClassicKey))) {
|
||||
mu_assert(
|
||||
memcmp(key_arr_ref[key_idx].data, key_dut.data, sizeof(MfClassicKey)) == 0,
|
||||
"Loaded key data mismatch");
|
||||
@ -484,19 +484,19 @@ MU_TEST(mf_classic_dict_test) {
|
||||
for(size_t i = 0; i < COUNT_OF(delete_keys_idx); i++) {
|
||||
MfClassicKey* key = &key_arr_ref[delete_keys_idx[i]];
|
||||
mu_assert(
|
||||
nfc_dict_is_key_present(dict, key->data, sizeof(MfClassicKey)),
|
||||
"nfc_dict_is_key_present() failed");
|
||||
keys_dict_is_key_present(dict, key->data, sizeof(MfClassicKey)),
|
||||
"keys_dict_is_key_present() failed");
|
||||
mu_assert(
|
||||
nfc_dict_delete_key(dict, key->data, sizeof(MfClassicKey)),
|
||||
"nfc_dict_delete_key() failed");
|
||||
keys_dict_delete_key(dict, key->data, sizeof(MfClassicKey)),
|
||||
"keys_dict_delete_key() failed");
|
||||
}
|
||||
|
||||
dict_keys_total = nfc_dict_get_total_keys(dict);
|
||||
dict_keys_total = keys_dict_get_total_keys(dict);
|
||||
mu_assert(
|
||||
dict_keys_total == test_key_num - COUNT_OF(delete_keys_idx),
|
||||
"nfc_dict_keys_total() failed");
|
||||
"keys_dict_keys_total() failed");
|
||||
|
||||
nfc_dict_free(dict);
|
||||
keys_dict_free(dict);
|
||||
free(key_arr_ref);
|
||||
|
||||
mu_assert(
|
||||
|
||||
@ -27,6 +27,7 @@ static const uint32_t baudrate_list[] = {
|
||||
460800,
|
||||
921600,
|
||||
};
|
||||
static const char* software_de_re[] = {"None", "4"};
|
||||
|
||||
bool gpio_scene_usb_uart_cfg_on_event(void* context, SceneManagerEvent event) {
|
||||
GpioApp* app = context;
|
||||
@ -84,6 +85,17 @@ static void line_port_cb(VariableItem* item) {
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, GpioUsbUartEventConfigSet);
|
||||
}
|
||||
|
||||
static void line_software_de_re_cb(VariableItem* item) {
|
||||
GpioApp* app = variable_item_get_context(item);
|
||||
furi_assert(app);
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
|
||||
variable_item_set_current_value_text(item, software_de_re[index]);
|
||||
|
||||
app->usb_uart_cfg->software_de_re = index;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, GpioUsbUartEventConfigSet);
|
||||
}
|
||||
|
||||
static void line_flow_cb(VariableItem* item) {
|
||||
GpioApp* app = variable_item_get_context(item);
|
||||
furi_assert(app);
|
||||
@ -155,6 +167,11 @@ void gpio_scene_usb_uart_cfg_on_enter(void* context) {
|
||||
app->var_item_flow = item;
|
||||
line_ensure_flow_invariant(app);
|
||||
|
||||
item = variable_item_list_add(
|
||||
var_item_list, "DE/RE Pin", COUNT_OF(software_de_re), line_software_de_re_cb, app);
|
||||
variable_item_set_current_value_index(item, app->usb_uart_cfg->software_de_re);
|
||||
variable_item_set_current_value_text(item, software_de_re[app->usb_uart_cfg->software_de_re]);
|
||||
|
||||
variable_item_list_set_selected_item(
|
||||
var_item_list, scene_manager_get_scene_state(app->scene_manager, GpioAppViewUsbUartCfg));
|
||||
|
||||
|
||||
@ -6,11 +6,16 @@
|
||||
#include <furi_hal.h>
|
||||
#include <furi_hal_usb_cdc.h>
|
||||
|
||||
//TODO: FL-3276 port to new USART API
|
||||
#include <stm32wbxx_ll_lpuart.h>
|
||||
#include <stm32wbxx_ll_usart.h>
|
||||
|
||||
#define USB_CDC_PKT_LEN CDC_DATA_SZ
|
||||
#define USB_UART_RX_BUF_SIZE (USB_CDC_PKT_LEN * 5)
|
||||
|
||||
#define USB_CDC_BIT_DTR (1 << 0)
|
||||
#define USB_CDC_BIT_RTS (1 << 1)
|
||||
#define USB_USART_DE_RE_PIN &gpio_ext_pa4
|
||||
|
||||
static const GpioPin* flow_pins[][2] = {
|
||||
{&gpio_ext_pa7, &gpio_ext_pa6}, // 2, 3
|
||||
@ -247,6 +252,17 @@ static int32_t usb_uart_worker(void* context) {
|
||||
usb_uart->cfg.flow_pins = usb_uart->cfg_new.flow_pins;
|
||||
events |= WorkerEvtCtrlLineSet;
|
||||
}
|
||||
if(usb_uart->cfg.software_de_re != usb_uart->cfg_new.software_de_re) {
|
||||
usb_uart->cfg.software_de_re = usb_uart->cfg_new.software_de_re;
|
||||
if(usb_uart->cfg.software_de_re != 0) {
|
||||
furi_hal_gpio_write(USB_USART_DE_RE_PIN, true);
|
||||
furi_hal_gpio_init(
|
||||
USB_USART_DE_RE_PIN, GpioModeOutputPushPull, GpioPullNo, GpioSpeedMedium);
|
||||
} else {
|
||||
furi_hal_gpio_init(
|
||||
USB_USART_DE_RE_PIN, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
}
|
||||
}
|
||||
api_lock_unlock(usb_uart->cfg_lock);
|
||||
}
|
||||
if(events & WorkerEvtLineCfgSet) {
|
||||
@ -260,6 +276,8 @@ static int32_t usb_uart_worker(void* context) {
|
||||
usb_uart_vcp_deinit(usb_uart, usb_uart->cfg.vcp_ch);
|
||||
usb_uart_serial_deinit(usb_uart, usb_uart->cfg.uart_ch);
|
||||
|
||||
furi_hal_gpio_init(USB_USART_DE_RE_PIN, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
|
||||
if(usb_uart->cfg.flow_pins != 0) {
|
||||
furi_hal_gpio_init_simple(flow_pins[usb_uart->cfg.flow_pins - 1][0], GpioModeAnalog);
|
||||
furi_hal_gpio_init_simple(flow_pins[usb_uart->cfg.flow_pins - 1][1], GpioModeAnalog);
|
||||
@ -298,7 +316,24 @@ static int32_t usb_uart_tx_thread(void* context) {
|
||||
|
||||
if(len > 0) {
|
||||
usb_uart->st.tx_cnt += len;
|
||||
|
||||
if(usb_uart->cfg.software_de_re != 0)
|
||||
furi_hal_gpio_write(USB_USART_DE_RE_PIN, false);
|
||||
|
||||
furi_hal_uart_tx(usb_uart->cfg.uart_ch, data, len);
|
||||
|
||||
if(usb_uart->cfg.software_de_re != 0) {
|
||||
//TODO: FL-3276 port to new USART API
|
||||
if(usb_uart->cfg.uart_ch == FuriHalUartIdUSART1) {
|
||||
while(!LL_USART_IsActiveFlag_TC(USART1))
|
||||
;
|
||||
} else if(usb_uart->cfg.uart_ch == FuriHalUartIdLPUART1) {
|
||||
while(!LL_LPUART_IsActiveFlag_TC(LPUART1))
|
||||
;
|
||||
}
|
||||
|
||||
furi_hal_gpio_write(USB_USART_DE_RE_PIN, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ typedef struct {
|
||||
uint8_t flow_pins;
|
||||
uint8_t baudrate_mode;
|
||||
uint32_t baudrate;
|
||||
uint8_t software_de_re;
|
||||
} UsbUartConfig;
|
||||
|
||||
typedef struct {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#include "mf_user_dict.h"
|
||||
|
||||
#include <nfc/helpers/nfc_dict.h>
|
||||
#include <toolbox/keys_dict.h>
|
||||
#include <nfc/protocols/mf_classic/mf_classic.h>
|
||||
#include <furi/furi.h>
|
||||
|
||||
@ -15,22 +15,22 @@ struct MfUserDict {
|
||||
MfUserDict* mf_user_dict_alloc(size_t max_keys_to_load) {
|
||||
MfUserDict* instance = malloc(sizeof(MfUserDict));
|
||||
|
||||
NfcDict* dict = nfc_dict_alloc(
|
||||
NFC_APP_MF_CLASSIC_DICT_USER_PATH, NfcDictModeOpenAlways, sizeof(MfClassicKey));
|
||||
KeysDict* dict = keys_dict_alloc(
|
||||
NFC_APP_MF_CLASSIC_DICT_USER_PATH, KeysDictModeOpenAlways, sizeof(MfClassicKey));
|
||||
furi_assert(dict);
|
||||
|
||||
size_t dict_keys_num = nfc_dict_get_total_keys(dict);
|
||||
size_t dict_keys_num = keys_dict_get_total_keys(dict);
|
||||
instance->keys_num = MIN(max_keys_to_load, dict_keys_num);
|
||||
|
||||
if(instance->keys_num > 0) {
|
||||
instance->keys_arr = malloc(instance->keys_num * sizeof(MfClassicKey));
|
||||
for(size_t i = 0; i < instance->keys_num; i++) {
|
||||
bool key_loaded =
|
||||
nfc_dict_get_next_key(dict, instance->keys_arr[i].data, sizeof(MfClassicKey));
|
||||
keys_dict_get_next_key(dict, instance->keys_arr[i].data, sizeof(MfClassicKey));
|
||||
furi_assert(key_loaded);
|
||||
}
|
||||
}
|
||||
nfc_dict_free(dict);
|
||||
keys_dict_free(dict);
|
||||
|
||||
return instance;
|
||||
}
|
||||
@ -67,13 +67,13 @@ bool mf_user_dict_delete_key(MfUserDict* instance, uint32_t index) {
|
||||
furi_assert(index < instance->keys_num);
|
||||
furi_assert(instance->keys_arr);
|
||||
|
||||
NfcDict* dict = nfc_dict_alloc(
|
||||
NFC_APP_MF_CLASSIC_DICT_USER_PATH, NfcDictModeOpenAlways, sizeof(MfClassicKey));
|
||||
KeysDict* dict = keys_dict_alloc(
|
||||
NFC_APP_MF_CLASSIC_DICT_USER_PATH, KeysDictModeOpenAlways, sizeof(MfClassicKey));
|
||||
furi_assert(dict);
|
||||
|
||||
bool key_delete_success =
|
||||
nfc_dict_delete_key(dict, instance->keys_arr[index].data, sizeof(MfClassicKey));
|
||||
nfc_dict_free(dict);
|
||||
keys_dict_delete_key(dict, instance->keys_arr[index].data, sizeof(MfClassicKey));
|
||||
keys_dict_free(dict);
|
||||
|
||||
if(key_delete_success) {
|
||||
instance->keys_num--;
|
||||
|
||||
@ -343,7 +343,7 @@ bool nfc_load_file(NfcApp* instance, FuriString* path, bool show_dialog) {
|
||||
nfc_supported_cards_load_cache(instance->nfc_supported_cards);
|
||||
|
||||
FuriString* load_path = furi_string_alloc();
|
||||
if(nfc_has_shadow_file_internal(instance, path)) {
|
||||
if(nfc_has_shadow_file_internal(instance, path)) { //-V1051
|
||||
nfc_set_shadow_file_path(path, load_path);
|
||||
} else if(furi_string_end_with(path, NFC_APP_SHADOW_EXTENSION)) {
|
||||
size_t path_len = furi_string_size(path);
|
||||
|
||||
@ -52,7 +52,7 @@
|
||||
|
||||
#include <nfc/nfc_device.h>
|
||||
#include <nfc/helpers/nfc_data_generator.h>
|
||||
#include <nfc/helpers/nfc_dict.h>
|
||||
#include <toolbox/keys_dict.h>
|
||||
|
||||
#include <gui/modules/validators.h>
|
||||
#include <toolbox/path.h>
|
||||
@ -80,7 +80,7 @@ typedef enum {
|
||||
} NfcRpcState;
|
||||
|
||||
typedef struct {
|
||||
NfcDict* dict;
|
||||
KeysDict* dict;
|
||||
uint8_t sectors_total;
|
||||
uint8_t sectors_read;
|
||||
uint8_t current_sector;
|
||||
|
||||
@ -41,7 +41,8 @@ NfcCommand nfc_dict_attack_worker_callback(NfcGenericEvent event, void* context)
|
||||
instance->view_dispatcher, NfcCustomEventDictAttackDataUpdate);
|
||||
} else if(mfc_event->type == MfClassicPollerEventTypeRequestKey) {
|
||||
MfClassicKey key = {};
|
||||
if(nfc_dict_get_next_key(instance->nfc_dict_context.dict, key.data, sizeof(MfClassicKey))) {
|
||||
if(keys_dict_get_next_key(
|
||||
instance->nfc_dict_context.dict, key.data, sizeof(MfClassicKey))) {
|
||||
mfc_event->data->key_request_data.key = key;
|
||||
mfc_event->data->key_request_data.key_provided = true;
|
||||
instance->nfc_dict_context.dict_keys_current++;
|
||||
@ -60,7 +61,7 @@ NfcCommand nfc_dict_attack_worker_callback(NfcGenericEvent event, void* context)
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, NfcCustomEventDictAttackDataUpdate);
|
||||
} else if(mfc_event->type == MfClassicPollerEventTypeNextSector) {
|
||||
nfc_dict_rewind(instance->nfc_dict_context.dict);
|
||||
keys_dict_rewind(instance->nfc_dict_context.dict);
|
||||
instance->nfc_dict_context.dict_keys_current = 0;
|
||||
instance->nfc_dict_context.current_sector =
|
||||
mfc_event->data->next_sector_data.current_sector;
|
||||
@ -79,7 +80,7 @@ NfcCommand nfc_dict_attack_worker_callback(NfcGenericEvent event, void* context)
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, NfcCustomEventDictAttackDataUpdate);
|
||||
} else if(mfc_event->type == MfClassicPollerEventTypeKeyAttackStop) {
|
||||
nfc_dict_rewind(instance->nfc_dict_context.dict);
|
||||
keys_dict_rewind(instance->nfc_dict_context.dict);
|
||||
instance->nfc_dict_context.is_key_attack = false;
|
||||
instance->nfc_dict_context.dict_keys_current = 0;
|
||||
view_dispatcher_send_custom_event(
|
||||
@ -124,15 +125,15 @@ static void nfc_scene_mf_classic_dict_attack_prepare_view(NfcApp* instance) {
|
||||
scene_manager_get_scene_state(instance->scene_manager, NfcSceneMfClassicDictAttack);
|
||||
if(state == DictAttackStateUserDictInProgress) {
|
||||
do {
|
||||
if(!nfc_dict_check_presence(NFC_APP_MF_CLASSIC_DICT_USER_PATH)) {
|
||||
if(!keys_dict_check_presence(NFC_APP_MF_CLASSIC_DICT_USER_PATH)) {
|
||||
state = DictAttackStateSystemDictInProgress;
|
||||
break;
|
||||
}
|
||||
|
||||
instance->nfc_dict_context.dict = nfc_dict_alloc(
|
||||
NFC_APP_MF_CLASSIC_DICT_USER_PATH, NfcDictModeOpenAlways, sizeof(MfClassicKey));
|
||||
if(nfc_dict_get_total_keys(instance->nfc_dict_context.dict) == 0) {
|
||||
nfc_dict_free(instance->nfc_dict_context.dict);
|
||||
instance->nfc_dict_context.dict = keys_dict_alloc(
|
||||
NFC_APP_MF_CLASSIC_DICT_USER_PATH, KeysDictModeOpenAlways, sizeof(MfClassicKey));
|
||||
if(keys_dict_get_total_keys(instance->nfc_dict_context.dict) == 0) {
|
||||
keys_dict_free(instance->nfc_dict_context.dict);
|
||||
state = DictAttackStateSystemDictInProgress;
|
||||
break;
|
||||
}
|
||||
@ -141,13 +142,13 @@ static void nfc_scene_mf_classic_dict_attack_prepare_view(NfcApp* instance) {
|
||||
} while(false);
|
||||
}
|
||||
if(state == DictAttackStateSystemDictInProgress) {
|
||||
instance->nfc_dict_context.dict = nfc_dict_alloc(
|
||||
NFC_APP_MF_CLASSIC_DICT_SYSTEM_PATH, NfcDictModeOpenExisting, sizeof(MfClassicKey));
|
||||
instance->nfc_dict_context.dict = keys_dict_alloc(
|
||||
NFC_APP_MF_CLASSIC_DICT_SYSTEM_PATH, KeysDictModeOpenExisting, sizeof(MfClassicKey));
|
||||
dict_attack_set_header(instance->dict_attack, "MF Classic System Dictionary");
|
||||
}
|
||||
|
||||
instance->nfc_dict_context.dict_keys_total =
|
||||
nfc_dict_get_total_keys(instance->nfc_dict_context.dict);
|
||||
keys_dict_get_total_keys(instance->nfc_dict_context.dict);
|
||||
dict_attack_set_total_dict_keys(
|
||||
instance->dict_attack, instance->nfc_dict_context.dict_keys_total);
|
||||
instance->nfc_dict_context.dict_keys_current = 0;
|
||||
@ -185,7 +186,7 @@ bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent
|
||||
if(state == DictAttackStateUserDictInProgress) {
|
||||
nfc_poller_stop(instance->poller);
|
||||
nfc_poller_free(instance->poller);
|
||||
nfc_dict_free(instance->nfc_dict_context.dict);
|
||||
keys_dict_free(instance->nfc_dict_context.dict);
|
||||
scene_manager_set_scene_state(
|
||||
instance->scene_manager,
|
||||
NfcSceneMfClassicDictAttack,
|
||||
@ -215,7 +216,7 @@ bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent
|
||||
if(instance->nfc_dict_context.is_card_present) {
|
||||
nfc_poller_stop(instance->poller);
|
||||
nfc_poller_free(instance->poller);
|
||||
nfc_dict_free(instance->nfc_dict_context.dict);
|
||||
keys_dict_free(instance->nfc_dict_context.dict);
|
||||
scene_manager_set_scene_state(
|
||||
instance->scene_manager,
|
||||
NfcSceneMfClassicDictAttack,
|
||||
@ -253,7 +254,7 @@ void nfc_scene_mf_classic_dict_attack_on_exit(void* context) {
|
||||
scene_manager_set_scene_state(
|
||||
instance->scene_manager, NfcSceneMfClassicDictAttack, DictAttackStateUserDictInProgress);
|
||||
|
||||
nfc_dict_free(instance->nfc_dict_context.dict);
|
||||
keys_dict_free(instance->nfc_dict_context.dict);
|
||||
|
||||
instance->nfc_dict_context.current_sector = 0;
|
||||
instance->nfc_dict_context.sectors_total = 0;
|
||||
|
||||
@ -14,20 +14,20 @@ void nfc_scene_mf_classic_keys_on_enter(void* context) {
|
||||
|
||||
// Load flipper dict keys total
|
||||
uint32_t flipper_dict_keys_total = 0;
|
||||
NfcDict* dict = nfc_dict_alloc(
|
||||
NFC_APP_MF_CLASSIC_DICT_SYSTEM_PATH, NfcDictModeOpenExisting, sizeof(MfClassicKey));
|
||||
KeysDict* dict = keys_dict_alloc(
|
||||
NFC_APP_MF_CLASSIC_DICT_SYSTEM_PATH, KeysDictModeOpenExisting, sizeof(MfClassicKey));
|
||||
if(dict) {
|
||||
flipper_dict_keys_total = nfc_dict_get_total_keys(dict);
|
||||
nfc_dict_free(dict);
|
||||
flipper_dict_keys_total = keys_dict_get_total_keys(dict);
|
||||
keys_dict_free(dict);
|
||||
}
|
||||
|
||||
// Load user dict keys total
|
||||
uint32_t user_dict_keys_total = 0;
|
||||
dict = nfc_dict_alloc(
|
||||
NFC_APP_MF_CLASSIC_DICT_USER_PATH, NfcDictModeOpenAlways, sizeof(MfClassicKey));
|
||||
dict = keys_dict_alloc(
|
||||
NFC_APP_MF_CLASSIC_DICT_USER_PATH, KeysDictModeOpenAlways, sizeof(MfClassicKey));
|
||||
if(dict) {
|
||||
user_dict_keys_total = nfc_dict_get_total_keys(dict);
|
||||
nfc_dict_free(dict);
|
||||
user_dict_keys_total = keys_dict_get_total_keys(dict);
|
||||
keys_dict_free(dict);
|
||||
}
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
|
||||
@ -29,23 +29,23 @@ bool nfc_scene_mf_classic_keys_add_on_event(void* context, SceneManagerEvent eve
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == NfcCustomEventByteInputDone) {
|
||||
// Add key to dict
|
||||
NfcDict* dict = nfc_dict_alloc(
|
||||
NFC_APP_MF_CLASSIC_DICT_USER_PATH, NfcDictModeOpenAlways, sizeof(MfClassicKey));
|
||||
KeysDict* dict = keys_dict_alloc(
|
||||
NFC_APP_MF_CLASSIC_DICT_USER_PATH, KeysDictModeOpenAlways, sizeof(MfClassicKey));
|
||||
furi_assert(dict);
|
||||
|
||||
MfClassicKey key = {};
|
||||
memcpy(key.data, instance->byte_input_store, sizeof(MfClassicKey));
|
||||
if(nfc_dict_is_key_present(dict, key.data, sizeof(MfClassicKey))) {
|
||||
if(keys_dict_is_key_present(dict, key.data, sizeof(MfClassicKey))) {
|
||||
scene_manager_next_scene(
|
||||
instance->scene_manager, NfcSceneMfClassicKeysWarnDuplicate);
|
||||
} else if(nfc_dict_add_key(dict, key.data, sizeof(MfClassicKey))) {
|
||||
} else if(keys_dict_add_key(dict, key.data, sizeof(MfClassicKey))) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneSaveSuccess);
|
||||
dolphin_deed(DolphinDeedNfcMfcAdd);
|
||||
} else {
|
||||
scene_manager_previous_scene(instance->scene_manager);
|
||||
}
|
||||
|
||||
nfc_dict_free(dict);
|
||||
keys_dict_free(dict);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,7 +48,6 @@ env.Append(
|
||||
File("helpers/iso14443_crc.h"),
|
||||
File("helpers/iso13239_crc.h"),
|
||||
File("helpers/nfc_data_generator.h"),
|
||||
File("helpers/nfc_dict.h"),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@ -1,270 +0,0 @@
|
||||
#include "nfc_dict.h"
|
||||
|
||||
#include <storage/storage.h>
|
||||
#include <flipper_format/flipper_format.h>
|
||||
#include <toolbox/stream/file_stream.h>
|
||||
#include <toolbox/stream/buffered_file_stream.h>
|
||||
#include <toolbox/args.h>
|
||||
|
||||
#include <nfc/helpers/nfc_util.h>
|
||||
|
||||
#define TAG "NfcDict"
|
||||
|
||||
struct NfcDict {
|
||||
Stream* stream;
|
||||
size_t key_size;
|
||||
size_t key_size_symbols;
|
||||
uint32_t total_keys;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
const char* path;
|
||||
FS_OpenMode open_mode;
|
||||
} NfcDictFile;
|
||||
|
||||
bool nfc_dict_check_presence(const char* path) {
|
||||
furi_assert(path);
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
|
||||
bool dict_present = storage_common_stat(storage, path, NULL) == FSE_OK;
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
return dict_present;
|
||||
}
|
||||
|
||||
NfcDict* nfc_dict_alloc(const char* path, NfcDictMode mode, size_t key_size) {
|
||||
furi_assert(path);
|
||||
|
||||
NfcDict* instance = malloc(sizeof(NfcDict));
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
instance->stream = buffered_file_stream_alloc(storage);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
FS_OpenMode open_mode = FSOM_OPEN_EXISTING;
|
||||
if(mode == NfcDictModeOpenAlways) {
|
||||
open_mode = FSOM_OPEN_ALWAYS;
|
||||
}
|
||||
instance->key_size = key_size;
|
||||
// Byte = 2 symbols + 1 end of line
|
||||
instance->key_size_symbols = key_size * 2 + 1;
|
||||
|
||||
bool dict_loaded = false;
|
||||
do {
|
||||
if(!buffered_file_stream_open(instance->stream, path, FSAM_READ_WRITE, open_mode)) {
|
||||
buffered_file_stream_close(instance->stream);
|
||||
break;
|
||||
}
|
||||
|
||||
// Check for new line ending
|
||||
if(!stream_eof(instance->stream)) {
|
||||
if(!stream_seek(instance->stream, -1, StreamOffsetFromEnd)) break;
|
||||
uint8_t last_char = 0;
|
||||
if(stream_read(instance->stream, &last_char, 1) != 1) break;
|
||||
if(last_char != '\n') {
|
||||
FURI_LOG_D(TAG, "Adding new line ending");
|
||||
if(stream_write_char(instance->stream, '\n') != 1) break;
|
||||
}
|
||||
if(!stream_rewind(instance->stream)) break;
|
||||
}
|
||||
|
||||
// Read total amount of keys
|
||||
FuriString* next_line;
|
||||
next_line = furi_string_alloc();
|
||||
while(true) {
|
||||
if(!stream_read_line(instance->stream, next_line)) {
|
||||
FURI_LOG_T(TAG, "No keys left in dict");
|
||||
break;
|
||||
}
|
||||
FURI_LOG_T(
|
||||
TAG,
|
||||
"Read line: %s, len: %zu",
|
||||
furi_string_get_cstr(next_line),
|
||||
furi_string_size(next_line));
|
||||
if(furi_string_get_char(next_line, 0) == '#') continue;
|
||||
if(furi_string_size(next_line) != instance->key_size_symbols) continue;
|
||||
instance->total_keys++;
|
||||
}
|
||||
furi_string_free(next_line);
|
||||
stream_rewind(instance->stream);
|
||||
|
||||
dict_loaded = true;
|
||||
FURI_LOG_I(TAG, "Loaded dictionary with %lu keys", instance->total_keys);
|
||||
} while(false);
|
||||
|
||||
if(!dict_loaded) {
|
||||
buffered_file_stream_close(instance->stream);
|
||||
free(instance);
|
||||
instance = NULL;
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void nfc_dict_free(NfcDict* instance) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->stream);
|
||||
|
||||
buffered_file_stream_close(instance->stream);
|
||||
stream_free(instance->stream);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
static void nfc_dict_int_to_str(NfcDict* instance, const uint8_t* key_int, FuriString* key_str) {
|
||||
furi_string_reset(key_str);
|
||||
for(size_t i = 0; i < instance->key_size; i++) {
|
||||
furi_string_cat_printf(key_str, "%02X", key_int[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void nfc_dict_str_to_int(NfcDict* instance, FuriString* key_str, uint64_t* key_int) {
|
||||
uint8_t key_byte_tmp;
|
||||
|
||||
*key_int = 0ULL;
|
||||
for(uint8_t i = 0; i < instance->key_size * 2; i += 2) {
|
||||
args_char_to_hex(
|
||||
furi_string_get_char(key_str, i), furi_string_get_char(key_str, i + 1), &key_byte_tmp);
|
||||
*key_int |= (uint64_t)key_byte_tmp << (8 * (instance->key_size - 1 - i / 2));
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t nfc_dict_get_total_keys(NfcDict* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
return instance->total_keys;
|
||||
}
|
||||
|
||||
bool nfc_dict_rewind(NfcDict* instance) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->stream);
|
||||
|
||||
return stream_rewind(instance->stream);
|
||||
}
|
||||
|
||||
static bool nfc_dict_get_next_key_str(NfcDict* instance, FuriString* key) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->stream);
|
||||
|
||||
bool key_read = false;
|
||||
furi_string_reset(key);
|
||||
while(!key_read) {
|
||||
if(!stream_read_line(instance->stream, key)) break;
|
||||
if(furi_string_get_char(key, 0) == '#') continue;
|
||||
if(furi_string_size(key) != instance->key_size_symbols) continue;
|
||||
furi_string_left(key, instance->key_size_symbols - 1);
|
||||
key_read = true;
|
||||
}
|
||||
|
||||
return key_read;
|
||||
}
|
||||
|
||||
bool nfc_dict_get_next_key(NfcDict* instance, uint8_t* key, size_t key_size) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->stream);
|
||||
furi_assert(instance->key_size == key_size);
|
||||
|
||||
FuriString* temp_key = furi_string_alloc();
|
||||
uint64_t key_int = 0;
|
||||
bool key_read = nfc_dict_get_next_key_str(instance, temp_key);
|
||||
if(key_read) {
|
||||
nfc_dict_str_to_int(instance, temp_key, &key_int);
|
||||
nfc_util_num2bytes(key_int, key_size, key);
|
||||
}
|
||||
furi_string_free(temp_key);
|
||||
return key_read;
|
||||
}
|
||||
|
||||
static bool nfc_dict_is_key_present_str(NfcDict* instance, FuriString* key) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->stream);
|
||||
|
||||
FuriString* next_line;
|
||||
next_line = furi_string_alloc();
|
||||
|
||||
bool key_found = false;
|
||||
stream_rewind(instance->stream);
|
||||
while(!key_found) { //-V654
|
||||
if(!stream_read_line(instance->stream, next_line)) break;
|
||||
if(furi_string_get_char(next_line, 0) == '#') continue;
|
||||
if(furi_string_size(next_line) != instance->key_size_symbols) continue;
|
||||
furi_string_left(next_line, instance->key_size_symbols - 1);
|
||||
if(!furi_string_equal(key, next_line)) continue;
|
||||
key_found = true;
|
||||
}
|
||||
|
||||
furi_string_free(next_line);
|
||||
return key_found;
|
||||
}
|
||||
|
||||
bool nfc_dict_is_key_present(NfcDict* instance, const uint8_t* key, size_t key_size) {
|
||||
furi_assert(instance);
|
||||
furi_assert(key);
|
||||
furi_assert(instance->stream);
|
||||
furi_assert(instance->key_size == key_size);
|
||||
|
||||
FuriString* temp_key = furi_string_alloc();
|
||||
nfc_dict_int_to_str(instance, key, temp_key);
|
||||
bool key_found = nfc_dict_is_key_present_str(instance, temp_key);
|
||||
furi_string_free(temp_key);
|
||||
|
||||
return key_found;
|
||||
}
|
||||
|
||||
static bool nfc_dict_add_key_str(NfcDict* instance, FuriString* key) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->stream);
|
||||
|
||||
furi_string_cat_printf(key, "\n");
|
||||
|
||||
bool key_added = false;
|
||||
do {
|
||||
if(!stream_seek(instance->stream, 0, StreamOffsetFromEnd)) break;
|
||||
if(!stream_insert_string(instance->stream, key)) break;
|
||||
instance->total_keys++;
|
||||
key_added = true;
|
||||
} while(false);
|
||||
|
||||
furi_string_left(key, instance->key_size_symbols - 1);
|
||||
return key_added;
|
||||
}
|
||||
|
||||
bool nfc_dict_add_key(NfcDict* instance, const uint8_t* key, size_t key_size) {
|
||||
furi_assert(instance);
|
||||
furi_assert(key);
|
||||
furi_assert(instance->stream);
|
||||
furi_assert(instance->key_size == key_size);
|
||||
|
||||
FuriString* temp_key = furi_string_alloc();
|
||||
nfc_dict_int_to_str(instance, key, temp_key);
|
||||
bool key_added = nfc_dict_add_key_str(instance, temp_key);
|
||||
furi_string_free(temp_key);
|
||||
|
||||
return key_added;
|
||||
}
|
||||
|
||||
bool nfc_dict_delete_key(NfcDict* instance, const uint8_t* key, size_t key_size) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->stream);
|
||||
furi_assert(key);
|
||||
furi_assert(instance->key_size == key_size);
|
||||
|
||||
bool key_removed = false;
|
||||
uint8_t* temp_key = malloc(key_size);
|
||||
|
||||
nfc_dict_rewind(instance);
|
||||
while(!key_removed) {
|
||||
if(!nfc_dict_get_next_key(instance, temp_key, key_size)) break;
|
||||
if(memcmp(temp_key, key, key_size) == 0) {
|
||||
int32_t offset = (-1) * (instance->key_size_symbols);
|
||||
stream_seek(instance->stream, offset, StreamOffsetFromCurrent);
|
||||
if(!stream_delete(instance->stream, instance->key_size_symbols)) break;
|
||||
instance->total_keys--;
|
||||
key_removed = true;
|
||||
}
|
||||
}
|
||||
nfc_dict_rewind(instance);
|
||||
free(temp_key);
|
||||
|
||||
return key_removed;
|
||||
}
|
||||
@ -1,103 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
NfcDictModeOpenExisting,
|
||||
NfcDictModeOpenAlways,
|
||||
} NfcDictMode;
|
||||
|
||||
typedef struct NfcDict NfcDict;
|
||||
|
||||
/** Check dictionary presence
|
||||
*
|
||||
* @param path - dictionary path
|
||||
*
|
||||
* @return true if dictionary exists, false otherwise
|
||||
*/
|
||||
bool nfc_dict_check_presence(const char* path);
|
||||
|
||||
/** Open or create dictionary
|
||||
* Depending on mode, dictionary will be opened or created.
|
||||
*
|
||||
* @param path - dictionary path
|
||||
* @param mode - NfcDictMode value
|
||||
* @param key_size - size of dictionary keys in bytes
|
||||
*
|
||||
* @return NfcDict dictionary instance
|
||||
*/
|
||||
NfcDict* nfc_dict_alloc(const char* path, NfcDictMode mode, size_t key_size);
|
||||
|
||||
/** Close dictionary
|
||||
*
|
||||
* @param instance - NfcDict dictionary instance
|
||||
*/
|
||||
void nfc_dict_free(NfcDict* instance);
|
||||
|
||||
/** Get total number of keys in dictionary
|
||||
*
|
||||
* @param instance - NfcDict dictionary instance
|
||||
*
|
||||
* @return total number of keys in dictionary
|
||||
*/
|
||||
uint32_t nfc_dict_get_total_keys(NfcDict* instance);
|
||||
|
||||
/** Rewind dictionary
|
||||
*
|
||||
* @param instance - NfcDict dictionary instance
|
||||
*
|
||||
* @return true if rewind was successful, false otherwise
|
||||
*/
|
||||
bool nfc_dict_rewind(NfcDict* instance);
|
||||
|
||||
/** Check if key is present in dictionary
|
||||
*
|
||||
* @param instance - NfcDict dictionary instance
|
||||
* @param key - key to check
|
||||
* @param key_size - size of key in bytes
|
||||
*
|
||||
* @return true if key is present, false otherwise
|
||||
*/
|
||||
bool nfc_dict_is_key_present(NfcDict* instance, const uint8_t* key, size_t key_size);
|
||||
|
||||
/** Get next key from dictionary
|
||||
* This function will return next key from dictionary. If there are no more
|
||||
* keys, it will return false, and nfc_dict_rewind() should be called.
|
||||
*
|
||||
* @param instance - NfcDict dictionary instance
|
||||
* @param key - buffer to store key
|
||||
* @param key_size - size of key in bytes
|
||||
*
|
||||
* @return true if key was successfully retrieved, false otherwise
|
||||
*/
|
||||
bool nfc_dict_get_next_key(NfcDict* instance, uint8_t* key, size_t key_size);
|
||||
|
||||
/** Add key to dictionary
|
||||
*
|
||||
* @param instance - NfcDict dictionary instance
|
||||
* @param key - key to add
|
||||
* @param key_size - size of key in bytes
|
||||
*
|
||||
* @return true if key was successfully added, false otherwise
|
||||
*/
|
||||
bool nfc_dict_add_key(NfcDict* instance, const uint8_t* key, size_t key_size);
|
||||
|
||||
/** Delete key from dictionary
|
||||
*
|
||||
* @param instance - NfcDict dictionary instance
|
||||
* @param key - key to delete
|
||||
* @param key_size - size of key in bytes
|
||||
*
|
||||
* @return true if key was successfully deleted, false otherwise
|
||||
*/
|
||||
bool nfc_dict_delete_key(NfcDict* instance, const uint8_t* key, size_t key_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -34,6 +34,7 @@ env.Append(
|
||||
File("hex.h"),
|
||||
File("simple_array.h"),
|
||||
File("bit_buffer.h"),
|
||||
File("keys_dict.h"),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
334
lib/toolbox/keys_dict.c
Normal file
334
lib/toolbox/keys_dict.c
Normal file
@ -0,0 +1,334 @@
|
||||
#include "keys_dict.h"
|
||||
|
||||
#include <storage/storage.h>
|
||||
#include <flipper_format/flipper_format.h>
|
||||
#include <toolbox/stream/file_stream.h>
|
||||
#include <toolbox/stream/buffered_file_stream.h>
|
||||
#include <toolbox/args.h>
|
||||
|
||||
#define TAG "KeysDict"
|
||||
|
||||
struct KeysDict {
|
||||
Stream* stream;
|
||||
size_t key_size;
|
||||
size_t key_size_symbols;
|
||||
size_t total_keys;
|
||||
};
|
||||
|
||||
static inline void keys_dict_add_ending_new_line(KeysDict* instance) {
|
||||
if(stream_seek(instance->stream, -1, StreamOffsetFromEnd)) {
|
||||
uint8_t last_char = 0;
|
||||
|
||||
// Check if the last char is new line or add a new line
|
||||
if(stream_read(instance->stream, &last_char, 1) == 1 && last_char != '\n') {
|
||||
FURI_LOG_D(TAG, "Adding new line ending");
|
||||
stream_write_char(instance->stream, '\n');
|
||||
}
|
||||
|
||||
stream_rewind(instance->stream);
|
||||
}
|
||||
}
|
||||
|
||||
static bool keys_dict_read_key_line(KeysDict* instance, FuriString* line, bool* is_endfile) {
|
||||
if(stream_read_line(instance->stream, line) == false) {
|
||||
*is_endfile = true;
|
||||
}
|
||||
|
||||
else {
|
||||
FURI_LOG_T(
|
||||
TAG, "Read line: %s, len: %zu", furi_string_get_cstr(line), furi_string_size(line));
|
||||
|
||||
bool is_comment = furi_string_get_char(line, 0) == '#';
|
||||
|
||||
if(!is_comment) {
|
||||
furi_string_left(line, instance->key_size_symbols - 1);
|
||||
}
|
||||
|
||||
bool is_correct_size = furi_string_size(line) == instance->key_size_symbols - 1;
|
||||
|
||||
return !is_comment && is_correct_size;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool keys_dict_check_presence(const char* path) {
|
||||
furi_assert(path);
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
|
||||
bool dict_present = storage_common_stat(storage, path, NULL) == FSE_OK;
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
return dict_present;
|
||||
}
|
||||
|
||||
KeysDict* keys_dict_alloc(const char* path, KeysDictMode mode, size_t key_size) {
|
||||
furi_assert(path);
|
||||
furi_assert(key_size > 0);
|
||||
|
||||
KeysDict* instance = malloc(sizeof(KeysDict));
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
furi_assert(storage);
|
||||
|
||||
instance->stream = buffered_file_stream_alloc(storage);
|
||||
furi_assert(instance->stream);
|
||||
|
||||
FS_OpenMode open_mode = (mode == KeysDictModeOpenAlways) ? FSOM_OPEN_ALWAYS :
|
||||
FSOM_OPEN_EXISTING;
|
||||
|
||||
// Byte = 2 symbols + 1 end of line
|
||||
instance->key_size = key_size;
|
||||
instance->key_size_symbols = key_size * 2 + 1;
|
||||
|
||||
instance->total_keys = 0;
|
||||
|
||||
bool file_exists =
|
||||
buffered_file_stream_open(instance->stream, path, FSAM_READ_WRITE, open_mode);
|
||||
|
||||
if(!file_exists) {
|
||||
buffered_file_stream_close(instance->stream);
|
||||
} else {
|
||||
// Eventually add new line character in the last line to avoid skipping keys
|
||||
keys_dict_add_ending_new_line(instance);
|
||||
}
|
||||
|
||||
FuriString* line = furi_string_alloc();
|
||||
|
||||
bool is_endfile = false;
|
||||
|
||||
// In this loop we only count the entries in the file
|
||||
// We prefer not to load the whole file in memory for space reasons
|
||||
while(file_exists && !is_endfile) {
|
||||
bool read_key = keys_dict_read_key_line(instance, line, &is_endfile);
|
||||
if(read_key) {
|
||||
instance->total_keys++;
|
||||
}
|
||||
}
|
||||
stream_rewind(instance->stream);
|
||||
FURI_LOG_I(TAG, "Loaded dictionary with %zu keys", instance->total_keys);
|
||||
|
||||
furi_string_free(line);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void keys_dict_free(KeysDict* instance) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->stream);
|
||||
|
||||
buffered_file_stream_close(instance->stream);
|
||||
stream_free(instance->stream);
|
||||
free(instance);
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
static void keys_dict_int_to_str(KeysDict* instance, const uint8_t* key_int, FuriString* key_str) {
|
||||
furi_assert(instance);
|
||||
furi_assert(key_str);
|
||||
furi_assert(key_int);
|
||||
|
||||
furi_string_reset(key_str);
|
||||
|
||||
for(size_t i = 0; i < instance->key_size; i++)
|
||||
furi_string_cat_printf(key_str, "%02X", key_int[i]);
|
||||
}
|
||||
|
||||
static void keys_dict_str_to_int(KeysDict* instance, FuriString* key_str, uint64_t* key_int) {
|
||||
furi_assert(instance);
|
||||
furi_assert(key_str);
|
||||
furi_assert(key_int);
|
||||
|
||||
uint8_t key_byte_tmp;
|
||||
char h, l;
|
||||
|
||||
*key_int = 0ULL;
|
||||
|
||||
for(size_t i = 0; i < instance->key_size_symbols - 1; i += 2) {
|
||||
h = furi_string_get_char(key_str, i);
|
||||
l = furi_string_get_char(key_str, i + 1);
|
||||
|
||||
args_char_to_hex(h, l, &key_byte_tmp);
|
||||
*key_int |= (uint64_t)key_byte_tmp << (8 * (instance->key_size - 1 - i / 2));
|
||||
}
|
||||
}
|
||||
|
||||
size_t keys_dict_get_total_keys(KeysDict* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
return instance->total_keys;
|
||||
}
|
||||
|
||||
bool keys_dict_rewind(KeysDict* instance) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->stream);
|
||||
|
||||
return stream_rewind(instance->stream);
|
||||
}
|
||||
|
||||
static bool keys_dict_get_next_key_str(KeysDict* instance, FuriString* key) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->stream);
|
||||
furi_assert(key);
|
||||
|
||||
bool key_read = false;
|
||||
bool is_endfile = false;
|
||||
|
||||
furi_string_reset(key);
|
||||
|
||||
while(!key_read && !is_endfile) key_read = keys_dict_read_key_line(instance, key, &is_endfile);
|
||||
|
||||
return key_read;
|
||||
}
|
||||
|
||||
bool keys_dict_get_next_key(KeysDict* instance, uint8_t* key, size_t key_size) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->stream);
|
||||
furi_assert(instance->key_size == key_size);
|
||||
furi_assert(key);
|
||||
|
||||
FuriString* temp_key = furi_string_alloc();
|
||||
|
||||
bool key_read = keys_dict_get_next_key_str(instance, temp_key);
|
||||
|
||||
if(key_read) {
|
||||
size_t tmp_len = key_size;
|
||||
uint64_t key_int = 0;
|
||||
|
||||
keys_dict_str_to_int(instance, temp_key, &key_int);
|
||||
|
||||
while(tmp_len--) {
|
||||
key[tmp_len] = (uint8_t)key_int;
|
||||
key_int >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
furi_string_free(temp_key);
|
||||
return key_read;
|
||||
}
|
||||
|
||||
static bool keys_dict_is_key_present_str(KeysDict* instance, FuriString* key) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->stream);
|
||||
furi_assert(key);
|
||||
|
||||
FuriString* line = furi_string_alloc();
|
||||
|
||||
bool is_endfile = false;
|
||||
bool line_found = false;
|
||||
|
||||
uint32_t actual_pos = stream_tell(instance->stream);
|
||||
stream_rewind(instance->stream);
|
||||
|
||||
while(!line_found && !is_endfile)
|
||||
line_found = // The line is found if the line was read and the key is equal to the line
|
||||
(keys_dict_read_key_line(instance, line, &is_endfile)) &&
|
||||
(furi_string_equal(key, line));
|
||||
|
||||
furi_string_free(line);
|
||||
|
||||
// Restore the position of the stream
|
||||
stream_seek(instance->stream, actual_pos, StreamOffsetFromStart);
|
||||
|
||||
return line_found;
|
||||
}
|
||||
|
||||
bool keys_dict_is_key_present(KeysDict* instance, const uint8_t* key, size_t key_size) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->stream);
|
||||
furi_assert(instance->key_size == key_size);
|
||||
furi_assert(key);
|
||||
|
||||
FuriString* temp_key = furi_string_alloc();
|
||||
|
||||
keys_dict_int_to_str(instance, key, temp_key);
|
||||
bool key_found = keys_dict_is_key_present_str(instance, temp_key);
|
||||
furi_string_free(temp_key);
|
||||
|
||||
return key_found;
|
||||
}
|
||||
|
||||
static bool keys_dict_add_key_str(KeysDict* instance, FuriString* key) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->stream);
|
||||
furi_assert(key);
|
||||
|
||||
furi_string_cat_str(key, "\n");
|
||||
|
||||
bool key_added = false;
|
||||
|
||||
uint32_t actual_pos = stream_tell(instance->stream);
|
||||
|
||||
if(stream_seek(instance->stream, 0, StreamOffsetFromEnd) &&
|
||||
stream_insert_string(instance->stream, key)) {
|
||||
instance->total_keys++;
|
||||
key_added = true;
|
||||
}
|
||||
|
||||
stream_seek(instance->stream, actual_pos, StreamOffsetFromStart);
|
||||
|
||||
return key_added;
|
||||
}
|
||||
|
||||
bool keys_dict_add_key(KeysDict* instance, const uint8_t* key, size_t key_size) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->stream);
|
||||
furi_assert(instance->key_size == key_size);
|
||||
furi_assert(key);
|
||||
|
||||
FuriString* temp_key = furi_string_alloc();
|
||||
furi_assert(temp_key);
|
||||
|
||||
keys_dict_int_to_str(instance, key, temp_key);
|
||||
bool key_added = keys_dict_add_key_str(instance, temp_key);
|
||||
|
||||
FURI_LOG_I(TAG, "Added key %s", furi_string_get_cstr(temp_key));
|
||||
|
||||
furi_string_free(temp_key);
|
||||
|
||||
return key_added;
|
||||
}
|
||||
|
||||
bool keys_dict_delete_key(KeysDict* instance, const uint8_t* key, size_t key_size) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->stream);
|
||||
furi_assert(instance->key_size == key_size);
|
||||
furi_assert(key);
|
||||
|
||||
bool key_removed = false;
|
||||
|
||||
uint8_t* temp_key = malloc(key_size);
|
||||
|
||||
stream_rewind(instance->stream);
|
||||
|
||||
while(!key_removed) {
|
||||
if(!keys_dict_get_next_key(instance, temp_key, key_size)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(memcmp(temp_key, key, key_size) == 0) {
|
||||
stream_seek(instance->stream, -instance->key_size_symbols, StreamOffsetFromCurrent);
|
||||
if(stream_delete(instance->stream, instance->key_size_symbols) == false) {
|
||||
break;
|
||||
}
|
||||
instance->total_keys--;
|
||||
key_removed = true;
|
||||
}
|
||||
}
|
||||
|
||||
FuriString* tmp = furi_string_alloc();
|
||||
|
||||
keys_dict_int_to_str(instance, key, tmp);
|
||||
|
||||
FURI_LOG_I(TAG, "Removed key %s", furi_string_get_cstr(tmp));
|
||||
|
||||
furi_string_free(tmp);
|
||||
|
||||
stream_rewind(instance->stream);
|
||||
free(temp_key);
|
||||
|
||||
return key_removed;
|
||||
}
|
||||
103
lib/toolbox/keys_dict.h
Normal file
103
lib/toolbox/keys_dict.h
Normal file
@ -0,0 +1,103 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
KeysDictModeOpenExisting,
|
||||
KeysDictModeOpenAlways,
|
||||
} KeysDictMode;
|
||||
|
||||
typedef struct KeysDict KeysDict;
|
||||
|
||||
/** Check if the file list exists
|
||||
*
|
||||
* @param path - list path
|
||||
*
|
||||
* @return true if list exists, false otherwise
|
||||
*/
|
||||
bool keys_dict_check_presence(const char* path);
|
||||
|
||||
/** Open or create list
|
||||
* Depending on mode, list will be opened or created.
|
||||
*
|
||||
* @param path - Path of the file that contain the list
|
||||
* @param mode - ListKeysMode value
|
||||
* @param key_size - Size of each key in bytes
|
||||
*
|
||||
* @return Returns KeysDict list instance
|
||||
*/
|
||||
KeysDict* keys_dict_alloc(const char* path, KeysDictMode mode, size_t key_size);
|
||||
|
||||
/** Close list
|
||||
*
|
||||
* @param instance - KeysDict list instance
|
||||
*/
|
||||
void keys_dict_free(KeysDict* instance);
|
||||
|
||||
/** Get total number of keys in list
|
||||
*
|
||||
* @param instance - KeysDict list instance
|
||||
*
|
||||
* @return Returns total number of keys in list
|
||||
*/
|
||||
size_t keys_dict_get_total_keys(KeysDict* instance);
|
||||
|
||||
/** Rewind list
|
||||
*
|
||||
* @param instance - KeysDict list instance
|
||||
*
|
||||
* @return Returns true if rewind was successful, false otherwise
|
||||
*/
|
||||
bool keys_dict_rewind(KeysDict* instance);
|
||||
|
||||
/** Check if key is present in list
|
||||
*
|
||||
* @param instance - KeysDict list instance
|
||||
* @param key - key to check
|
||||
* @param key_size - Size of the key in bytes
|
||||
*
|
||||
* @return Returns true if key is present, false otherwise
|
||||
*/
|
||||
bool keys_dict_is_key_present(KeysDict* instance, const uint8_t* key, size_t key_size);
|
||||
|
||||
/** Get next key from the list
|
||||
* This function will return next key from list. If there are no more
|
||||
* keys, it will return false, and keys_dict_rewind() should be called.
|
||||
*
|
||||
* @param instance - KeysDict list instance
|
||||
* @param key - Array where to store key
|
||||
* @param key_size - Size of key in bytes
|
||||
*
|
||||
* @return Returns true if key was successfully retrieved, false otherwise
|
||||
*/
|
||||
bool keys_dict_get_next_key(KeysDict* instance, uint8_t* key, size_t key_size);
|
||||
|
||||
/** Add key to list
|
||||
*
|
||||
* @param instance - KeysDict list instance
|
||||
* @param key - Key to add
|
||||
* @param key_size - Size of the key in bytes
|
||||
*
|
||||
* @return Returns true if key was successfully added, false otherwise
|
||||
*/
|
||||
bool keys_dict_add_key(KeysDict* instance, const uint8_t* key, size_t key_size);
|
||||
|
||||
/** Delete key from list
|
||||
*
|
||||
* @param instance - KeysDict list instance
|
||||
* @param key - Key to delete
|
||||
* @param key_size - Size of the key in bytes
|
||||
*
|
||||
* @return Returns true if key was successfully deleted, false otherwise
|
||||
*/
|
||||
bool keys_dict_delete_key(KeysDict* instance, const uint8_t* key, size_t key_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -11,6 +11,27 @@ WINPATHSEP_RE = re.compile(r"\\([^\"'\\]|$)")
|
||||
# Excludes all files ending with ~, usually created by editors as backup files
|
||||
GLOB_FILE_EXCLUSION = ["*~"]
|
||||
|
||||
# List of environment variables to proxy to child processes
|
||||
FORWARDED_ENV_VARIABLES = [
|
||||
# CI/CD variables
|
||||
"WORKFLOW_BRANCH_OR_TAG",
|
||||
"DIST_SUFFIX",
|
||||
# Python & other tools
|
||||
"HOME",
|
||||
"APPDATA",
|
||||
"PYTHONHOME",
|
||||
"PYTHONNOUSERSITE",
|
||||
"TMP",
|
||||
"TEMP",
|
||||
# ccache
|
||||
"CCACHE_DISABLE",
|
||||
# Colors for tools
|
||||
"TERM",
|
||||
# Toolchain
|
||||
"FBT_TOOLCHAIN_PATH",
|
||||
"UFBT_HOME",
|
||||
]
|
||||
|
||||
|
||||
def tempfile_arg_esc_func(arg):
|
||||
arg = quote_spaces(arg)
|
||||
|
||||
@ -25,33 +25,10 @@ forward_os_env = {
|
||||
"PATH": os.environ["PATH"],
|
||||
}
|
||||
|
||||
# Proxying environment to child processes & scripts
|
||||
variables_to_forward = [
|
||||
# CI/CD variables
|
||||
"WORKFLOW_BRANCH_OR_TAG",
|
||||
"DIST_SUFFIX",
|
||||
# Python & other tools
|
||||
"HOME",
|
||||
"APPDATA",
|
||||
"PYTHONHOME",
|
||||
"PYTHONNOUSERSITE",
|
||||
"TMP",
|
||||
"TEMP",
|
||||
# Colors for tools
|
||||
"TERM",
|
||||
]
|
||||
|
||||
if proxy_env := GetOption("proxy_env"):
|
||||
variables_to_forward.extend(proxy_env.split(","))
|
||||
|
||||
for env_value_name in variables_to_forward:
|
||||
if environ_value := os.environ.get(env_value_name, None):
|
||||
forward_os_env[env_value_name] = environ_value
|
||||
|
||||
# Core environment init - loads SDK state, sets up paths, etc.
|
||||
core_env = Environment(
|
||||
variables=ufbt_variables,
|
||||
ENV=forward_os_env,
|
||||
UFBT_STATE_DIR=ufbt_state_dir,
|
||||
UFBT_CURRENT_SDK_DIR=ufbt_current_sdk_dir,
|
||||
UFBT_SCRIPT_DIR=ufbt_script_dir,
|
||||
@ -69,6 +46,7 @@ core_env.Append(CPPDEFINES=GetOption("extra_defines"))
|
||||
from fbt.appmanifest import FlipperApplication, FlipperAppType
|
||||
from fbt.sdk.cache import SdkCache
|
||||
from fbt.util import (
|
||||
FORWARDED_ENV_VARIABLES,
|
||||
path_as_posix,
|
||||
resolve_real_dir_node,
|
||||
single_quote,
|
||||
@ -76,8 +54,19 @@ from fbt.util import (
|
||||
wrap_tempfile,
|
||||
)
|
||||
|
||||
variables_to_forward = list(FORWARDED_ENV_VARIABLES)
|
||||
|
||||
if proxy_env := GetOption("proxy_env"):
|
||||
variables_to_forward.extend(proxy_env.split(","))
|
||||
|
||||
for env_value_name in variables_to_forward:
|
||||
if environ_value := os.environ.get(env_value_name, None):
|
||||
forward_os_env[env_value_name] = environ_value
|
||||
|
||||
|
||||
# Base environment with all tools loaded from SDK
|
||||
env = core_env.Clone(
|
||||
ENV=forward_os_env,
|
||||
toolpath=[core_env["FBT_SCRIPT_DIR"].Dir("fbt_tools")],
|
||||
tools=[
|
||||
"fbt_tweaks",
|
||||
@ -477,9 +466,12 @@ else:
|
||||
|
||||
dist_env.PhonyTarget("dolphin_ext", Action(missing_dolphin_folder, None))
|
||||
|
||||
# print(env.Dump())
|
||||
dist_env.PhonyTarget(
|
||||
"env",
|
||||
"@echo $( ${FBT_SCRIPT_DIR.abspath}/toolchain/fbtenv.sh $)",
|
||||
'@echo "FBT_TOOLCHAIN_PATH='
|
||||
+ forward_os_env["FBT_TOOLCHAIN_PATH"]
|
||||
+ '" source $( "${FBT_SCRIPT_DIR.abspath}/toolchain/fbtenv.sh" $)',
|
||||
)
|
||||
|
||||
dist_env.PostConfigureUfbtEnvionment()
|
||||
|
||||
4
scripts/ufbt/project_template/.gitignore
vendored
4
scripts/ufbt/project_template/.gitignore
vendored
@ -1,4 +1,6 @@
|
||||
dist/*
|
||||
.vscode
|
||||
.clang-format
|
||||
.editorconfig
|
||||
.editorconfig
|
||||
.env
|
||||
.ufbt
|
||||
|
||||
@ -44,7 +44,11 @@ How to create a new application:
|
||||
4. Run `ufbt launch` to build and upload your application.
|
||||
|
||||
How to open a shell with toolchain environment and other build tools:
|
||||
In your shell, type "source `ufbt -s env`". You can also use "." instead of "source".
|
||||
In your shell, type "eval `ufbt -s env`".
|
||||
|
||||
How to update uFBT SDK:
|
||||
Run "ufbt update" to fetch latest SDK.
|
||||
You can also specify branch, target and/or channel options. See "ufbt update -h" for details.
|
||||
"""
|
||||
|
||||
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import json
|
||||
import os
|
||||
import pathlib
|
||||
import sys
|
||||
from functools import reduce
|
||||
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
from SCons.Platform import TempFileMunge
|
||||
from fbt.util import (
|
||||
tempfile_arg_esc_func,
|
||||
single_quote,
|
||||
wrap_tempfile,
|
||||
resolve_real_dir_node,
|
||||
)
|
||||
|
||||
import os
|
||||
import multiprocessing
|
||||
import os
|
||||
|
||||
from fbt.util import (
|
||||
FORWARDED_ENV_VARIABLES,
|
||||
resolve_real_dir_node,
|
||||
single_quote,
|
||||
tempfile_arg_esc_func,
|
||||
wrap_tempfile,
|
||||
)
|
||||
from SCons.Platform import TempFileMunge
|
||||
|
||||
Import("VAR_ENV")
|
||||
|
||||
@ -15,23 +16,9 @@ forward_os_env = {
|
||||
# Import PATH from OS env - scons doesn't do that by default
|
||||
"PATH": os.environ["PATH"],
|
||||
}
|
||||
# Proxying CI environment to child processes & scripts
|
||||
variables_to_forward = [
|
||||
# CI/CD variables
|
||||
"WORKFLOW_BRANCH_OR_TAG",
|
||||
"DIST_SUFFIX",
|
||||
# Python & other tools
|
||||
"HOME",
|
||||
"APPDATA",
|
||||
"PYTHONHOME",
|
||||
"PYTHONNOUSERSITE",
|
||||
"TMP",
|
||||
"TEMP",
|
||||
# ccache
|
||||
"CCACHE_DISABLE",
|
||||
# Colors for tools
|
||||
"TERM",
|
||||
]
|
||||
|
||||
variables_to_forward = list(FORWARDED_ENV_VARIABLES)
|
||||
|
||||
if proxy_env := GetOption("proxy_env"):
|
||||
variables_to_forward.extend(proxy_env.split(","))
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
entry,status,name,type,params
|
||||
Version,+,49.3,,
|
||||
Version,+,50.0,,
|
||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||
Header,+,applications/services/cli/cli.h,,
|
||||
Header,+,applications/services/cli/cli_vcp.h,,
|
||||
@ -139,6 +139,7 @@ Header,+,lib/toolbox/crc32_calc.h,,
|
||||
Header,+,lib/toolbox/dir_walk.h,,
|
||||
Header,+,lib/toolbox/float_tools.h,,
|
||||
Header,+,lib/toolbox/hex.h,,
|
||||
Header,+,lib/toolbox/keys_dict.h,,
|
||||
Header,+,lib/toolbox/manchester_decoder.h,,
|
||||
Header,+,lib/toolbox/manchester_encoder.h,,
|
||||
Header,+,lib/toolbox/name_generator.h,,
|
||||
@ -1592,6 +1593,15 @@ Function,-,j1f,float,float
|
||||
Function,-,jn,double,"int, double"
|
||||
Function,-,jnf,float,"int, float"
|
||||
Function,-,jrand48,long,unsigned short[3]
|
||||
Function,+,keys_dict_add_key,_Bool,"KeysDict*, const uint8_t*, size_t"
|
||||
Function,+,keys_dict_alloc,KeysDict*,"const char*, KeysDictMode, size_t"
|
||||
Function,+,keys_dict_check_presence,_Bool,const char*
|
||||
Function,+,keys_dict_delete_key,_Bool,"KeysDict*, const uint8_t*, size_t"
|
||||
Function,+,keys_dict_free,void,KeysDict*
|
||||
Function,+,keys_dict_get_next_key,_Bool,"KeysDict*, uint8_t*, size_t"
|
||||
Function,+,keys_dict_get_total_keys,size_t,KeysDict*
|
||||
Function,+,keys_dict_is_key_present,_Bool,"KeysDict*, const uint8_t*, size_t"
|
||||
Function,+,keys_dict_rewind,_Bool,KeysDict*
|
||||
Function,-,l64a,char*,long
|
||||
Function,-,labs,long,long
|
||||
Function,-,lcong48,void,unsigned short[7]
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
entry,status,name,type,params
|
||||
Version,+,49.3,,
|
||||
Version,+,50.0,,
|
||||
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
|
||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||
Header,+,applications/services/cli/cli.h,,
|
||||
@ -114,7 +114,6 @@ Header,+,lib/nanopb/pb_encode.h,,
|
||||
Header,+,lib/nfc/helpers/iso13239_crc.h,,
|
||||
Header,+,lib/nfc/helpers/iso14443_crc.h,,
|
||||
Header,+,lib/nfc/helpers/nfc_data_generator.h,,
|
||||
Header,+,lib/nfc/helpers/nfc_dict.h,,
|
||||
Header,+,lib/nfc/helpers/nfc_util.h,,
|
||||
Header,+,lib/nfc/nfc.h,,
|
||||
Header,+,lib/nfc/nfc_device.h,,
|
||||
@ -204,6 +203,7 @@ Header,+,lib/toolbox/crc32_calc.h,,
|
||||
Header,+,lib/toolbox/dir_walk.h,,
|
||||
Header,+,lib/toolbox/float_tools.h,,
|
||||
Header,+,lib/toolbox/hex.h,,
|
||||
Header,+,lib/toolbox/keys_dict.h,,
|
||||
Header,+,lib/toolbox/manchester_decoder.h,,
|
||||
Header,+,lib/toolbox/manchester_encoder.h,,
|
||||
Header,+,lib/toolbox/name_generator.h,,
|
||||
@ -1967,6 +1967,15 @@ Function,-,j1f,float,float
|
||||
Function,-,jn,double,"int, double"
|
||||
Function,-,jnf,float,"int, float"
|
||||
Function,-,jrand48,long,unsigned short[3]
|
||||
Function,+,keys_dict_add_key,_Bool,"KeysDict*, const uint8_t*, size_t"
|
||||
Function,+,keys_dict_alloc,KeysDict*,"const char*, KeysDictMode, size_t"
|
||||
Function,+,keys_dict_check_presence,_Bool,const char*
|
||||
Function,+,keys_dict_delete_key,_Bool,"KeysDict*, const uint8_t*, size_t"
|
||||
Function,+,keys_dict_free,void,KeysDict*
|
||||
Function,+,keys_dict_get_next_key,_Bool,"KeysDict*, uint8_t*, size_t"
|
||||
Function,+,keys_dict_get_total_keys,size_t,KeysDict*
|
||||
Function,+,keys_dict_is_key_present,_Bool,"KeysDict*, const uint8_t*, size_t"
|
||||
Function,+,keys_dict_rewind,_Bool,KeysDict*
|
||||
Function,-,l64a,char*,long
|
||||
Function,-,labs,long,long
|
||||
Function,-,lcong48,void,unsigned short[7]
|
||||
@ -2441,15 +2450,6 @@ Function,+,nfc_device_save,_Bool,"NfcDevice*, const char*"
|
||||
Function,+,nfc_device_set_data,void,"NfcDevice*, NfcProtocol, const NfcDeviceData*"
|
||||
Function,+,nfc_device_set_loading_callback,void,"NfcDevice*, NfcLoadingCallback, void*"
|
||||
Function,+,nfc_device_set_uid,_Bool,"NfcDevice*, const uint8_t*, size_t"
|
||||
Function,+,nfc_dict_add_key,_Bool,"NfcDict*, const uint8_t*, size_t"
|
||||
Function,+,nfc_dict_alloc,NfcDict*,"const char*, NfcDictMode, size_t"
|
||||
Function,+,nfc_dict_check_presence,_Bool,const char*
|
||||
Function,+,nfc_dict_delete_key,_Bool,"NfcDict*, const uint8_t*, size_t"
|
||||
Function,+,nfc_dict_free,void,NfcDict*
|
||||
Function,+,nfc_dict_get_next_key,_Bool,"NfcDict*, uint8_t*, size_t"
|
||||
Function,+,nfc_dict_get_total_keys,uint32_t,NfcDict*
|
||||
Function,+,nfc_dict_is_key_present,_Bool,"NfcDict*, const uint8_t*, size_t"
|
||||
Function,+,nfc_dict_rewind,_Bool,NfcDict*
|
||||
Function,+,nfc_felica_listener_set_sensf_res_data,NfcError,"Nfc*, const uint8_t*, const uint8_t, const uint8_t*, const uint8_t"
|
||||
Function,+,nfc_free,void,Nfc*
|
||||
Function,+,nfc_iso14443a_listener_set_col_res_data,NfcError,"Nfc*, uint8_t*, uint8_t, uint8_t*, uint8_t"
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user