mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-16 04:24:45 -07:00
fmt
This commit is contained in:
@@ -38,7 +38,8 @@ static void nfc_scene_emulate_nfcv_widget_config(Nfc* nfc, bool data_received) {
|
|||||||
info_str = furi_string_alloc();
|
info_str = furi_string_alloc();
|
||||||
|
|
||||||
widget_add_icon_element(widget, 0, 3, &I_RFIDDolphinSend_97x61);
|
widget_add_icon_element(widget, 0, 3, &I_RFIDDolphinSend_97x61);
|
||||||
widget_add_string_element(widget, 89, 32, AlignCenter, AlignTop, FontPrimary, "Emulating NfcV");
|
widget_add_string_element(
|
||||||
|
widget, 89, 32, AlignCenter, AlignTop, FontPrimary, "Emulating NfcV");
|
||||||
if(strcmp(nfc->dev->dev_name, "")) {
|
if(strcmp(nfc->dev->dev_name, "")) {
|
||||||
furi_string_printf(info_str, "%s", nfc->dev->dev_name);
|
furi_string_printf(info_str, "%s", nfc->dev->dev_name);
|
||||||
} else {
|
} else {
|
||||||
@@ -97,7 +98,8 @@ bool nfc_scene_emulate_nfcv_on_event(void* context, SceneManagerEvent event) {
|
|||||||
}
|
}
|
||||||
if(strlen(nfcv_data->last_command) > 0) {
|
if(strlen(nfcv_data->last_command) > 0) {
|
||||||
/* use the last n bytes from the log so there's enough space for the new log entry */
|
/* use the last n bytes from the log so there's enough space for the new log entry */
|
||||||
size_t maxSize = NFC_SCENE_EMULATE_NFCV_LOG_SIZE_MAX - (strlen(nfcv_data->last_command) + 1);
|
size_t maxSize =
|
||||||
|
NFC_SCENE_EMULATE_NFCV_LOG_SIZE_MAX - (strlen(nfcv_data->last_command) + 1);
|
||||||
if(furi_string_size(nfc->text_box_store) >= maxSize) {
|
if(furi_string_size(nfc->text_box_store) >= maxSize) {
|
||||||
furi_string_right(nfc->text_box_store, (strlen(nfcv_data->last_command) + 1));
|
furi_string_right(nfc->text_box_store, (strlen(nfcv_data->last_command) + 1));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ void nfc_scene_nfc_data_info_on_enter(void* context) {
|
|||||||
NfcDeviceData* dev_data = &nfc->dev->dev_data;
|
NfcDeviceData* dev_data = &nfc->dev->dev_data;
|
||||||
NfcProtocol protocol = dev_data->protocol;
|
NfcProtocol protocol = dev_data->protocol;
|
||||||
uint8_t text_scroll_height = 0;
|
uint8_t text_scroll_height = 0;
|
||||||
if((protocol == NfcDeviceProtocolMifareDesfire) || (protocol == NfcDeviceProtocolMifareUl)
|
if((protocol == NfcDeviceProtocolMifareDesfire) || (protocol == NfcDeviceProtocolMifareUl) ||
|
||||||
|| (protocol == NfcDeviceProtocolNfcV)) {
|
(protocol == NfcDeviceProtocolNfcV)) {
|
||||||
widget_add_button_element(
|
widget_add_button_element(
|
||||||
widget, GuiButtonTypeRight, "More", nfc_scene_nfc_data_info_widget_callback, nfc);
|
widget, GuiButtonTypeRight, "More", nfc_scene_nfc_data_info_widget_callback, nfc);
|
||||||
text_scroll_height = 52;
|
text_scroll_height = 52;
|
||||||
@@ -55,8 +55,7 @@ void nfc_scene_nfc_data_info_on_enter(void* context) {
|
|||||||
} else if(protocol == NfcDeviceProtocolMifareDesfire) {
|
} else if(protocol == NfcDeviceProtocolMifareDesfire) {
|
||||||
furi_string_cat_printf(temp_str, "\e#MIFARE DESfire\n");
|
furi_string_cat_printf(temp_str, "\e#MIFARE DESfire\n");
|
||||||
} else if(protocol == NfcDeviceProtocolNfcV) {
|
} else if(protocol == NfcDeviceProtocolNfcV) {
|
||||||
switch (dev_data->nfcv_data.type)
|
switch(dev_data->nfcv_data.type) {
|
||||||
{
|
|
||||||
case NfcVTypePlain:
|
case NfcVTypePlain:
|
||||||
furi_string_cat_printf(temp_str, "\e#ISO15693\n");
|
furi_string_cat_printf(temp_str, "\e#ISO15693\n");
|
||||||
break;
|
break;
|
||||||
@@ -96,7 +95,8 @@ void nfc_scene_nfc_data_info_on_enter(void* context) {
|
|||||||
furi_string_cat_printf(temp_str, "Blocks: %02X\n", nfcv_data->block_num);
|
furi_string_cat_printf(temp_str, "Blocks: %02X\n", nfcv_data->block_num);
|
||||||
furi_string_cat_printf(temp_str, "Blocksize: %02X\n", nfcv_data->block_size);
|
furi_string_cat_printf(temp_str, "Blocksize: %02X\n", nfcv_data->block_size);
|
||||||
|
|
||||||
furi_string_cat_printf(temp_str, "Data (%d byte)\n", nfcv_data->block_num * nfcv_data->block_size);
|
furi_string_cat_printf(
|
||||||
|
temp_str, "Data (%d byte)\n", nfcv_data->block_num * nfcv_data->block_size);
|
||||||
|
|
||||||
int maxBlocks = nfcv_data->block_num;
|
int maxBlocks = nfcv_data->block_num;
|
||||||
if(maxBlocks > 32) {
|
if(maxBlocks > 32) {
|
||||||
@@ -106,46 +106,88 @@ void nfc_scene_nfc_data_info_on_enter(void* context) {
|
|||||||
|
|
||||||
for(int block = 0; block < maxBlocks; block++) {
|
for(int block = 0; block < maxBlocks; block++) {
|
||||||
for(int pos = 0; pos < nfcv_data->block_size; pos++) {
|
for(int pos = 0; pos < nfcv_data->block_size; pos++) {
|
||||||
furi_string_cat_printf(temp_str, " %02X", nfcv_data->data[block * nfcv_data->block_size + pos]);
|
furi_string_cat_printf(
|
||||||
|
temp_str, " %02X", nfcv_data->data[block * nfcv_data->block_size + pos]);
|
||||||
}
|
}
|
||||||
furi_string_cat_printf(temp_str, "\n");
|
furi_string_cat_printf(temp_str, "\n");
|
||||||
}
|
}
|
||||||
furi_string_cat_printf(temp_str, "\n");
|
furi_string_cat_printf(temp_str, "\n");
|
||||||
|
|
||||||
switch (dev_data->nfcv_data.type)
|
switch(dev_data->nfcv_data.type) {
|
||||||
{
|
|
||||||
case NfcVTypePlain:
|
case NfcVTypePlain:
|
||||||
furi_string_cat_printf(temp_str, "Type: Plain\n");
|
furi_string_cat_printf(temp_str, "Type: Plain\n");
|
||||||
break;
|
break;
|
||||||
case NfcVTypeSlix:
|
case NfcVTypeSlix:
|
||||||
furi_string_cat_printf(temp_str, "Type: SLIX\n");
|
furi_string_cat_printf(temp_str, "Type: SLIX\n");
|
||||||
furi_string_cat_printf(temp_str, "Keys:\n");
|
furi_string_cat_printf(temp_str, "Keys:\n");
|
||||||
furi_string_cat_printf(temp_str, " EAS %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_eas));
|
furi_string_cat_printf(
|
||||||
|
temp_str,
|
||||||
|
" EAS %08lX\n",
|
||||||
|
nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_eas));
|
||||||
break;
|
break;
|
||||||
case NfcVTypeSlixS:
|
case NfcVTypeSlixS:
|
||||||
furi_string_cat_printf(temp_str, "Type: SLIX-S\n");
|
furi_string_cat_printf(temp_str, "Type: SLIX-S\n");
|
||||||
furi_string_cat_printf(temp_str, "Keys:\n");
|
furi_string_cat_printf(temp_str, "Keys:\n");
|
||||||
furi_string_cat_printf(temp_str, " Read %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix_s.key_read));
|
furi_string_cat_printf(
|
||||||
furi_string_cat_printf(temp_str, " Write %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix_s.key_write));
|
temp_str,
|
||||||
furi_string_cat_printf(temp_str, " Privacy %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix_s.key_privacy));
|
" Read %08lX\n",
|
||||||
furi_string_cat_printf(temp_str, " Destroy %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix_s.key_destroy));
|
nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix_s.key_read));
|
||||||
furi_string_cat_printf(temp_str, " EAS %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix_s.key_eas));
|
furi_string_cat_printf(
|
||||||
|
temp_str,
|
||||||
|
" Write %08lX\n",
|
||||||
|
nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix_s.key_write));
|
||||||
|
furi_string_cat_printf(
|
||||||
|
temp_str,
|
||||||
|
" Privacy %08lX\n",
|
||||||
|
nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix_s.key_privacy));
|
||||||
|
furi_string_cat_printf(
|
||||||
|
temp_str,
|
||||||
|
" Destroy %08lX\n",
|
||||||
|
nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix_s.key_destroy));
|
||||||
|
furi_string_cat_printf(
|
||||||
|
temp_str,
|
||||||
|
" EAS %08lX\n",
|
||||||
|
nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix_s.key_eas));
|
||||||
break;
|
break;
|
||||||
case NfcVTypeSlixL:
|
case NfcVTypeSlixL:
|
||||||
furi_string_cat_printf(temp_str, "Type: SLIX-L\n");
|
furi_string_cat_printf(temp_str, "Type: SLIX-L\n");
|
||||||
furi_string_cat_printf(temp_str, "Keys:\n");
|
furi_string_cat_printf(temp_str, "Keys:\n");
|
||||||
furi_string_cat_printf(temp_str, " Privacy %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix_l.key_privacy));
|
furi_string_cat_printf(
|
||||||
furi_string_cat_printf(temp_str, " Destroy %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix_l.key_destroy));
|
temp_str,
|
||||||
furi_string_cat_printf(temp_str, " EAS %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix_l.key_eas));
|
" Privacy %08lX\n",
|
||||||
|
nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix_l.key_privacy));
|
||||||
|
furi_string_cat_printf(
|
||||||
|
temp_str,
|
||||||
|
" Destroy %08lX\n",
|
||||||
|
nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix_l.key_destroy));
|
||||||
|
furi_string_cat_printf(
|
||||||
|
temp_str,
|
||||||
|
" EAS %08lX\n",
|
||||||
|
nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix_l.key_eas));
|
||||||
break;
|
break;
|
||||||
case NfcVTypeSlix2:
|
case NfcVTypeSlix2:
|
||||||
furi_string_cat_printf(temp_str, "Type: SLIX2\n");
|
furi_string_cat_printf(temp_str, "Type: SLIX2\n");
|
||||||
furi_string_cat_printf(temp_str, "Keys:\n");
|
furi_string_cat_printf(temp_str, "Keys:\n");
|
||||||
furi_string_cat_printf(temp_str, " Read %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix2.key_read));
|
furi_string_cat_printf(
|
||||||
furi_string_cat_printf(temp_str, " Write %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix2.key_write));
|
temp_str,
|
||||||
furi_string_cat_printf(temp_str, " Privacy %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix2.key_privacy));
|
" Read %08lX\n",
|
||||||
furi_string_cat_printf(temp_str, " Destroy %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix2.key_destroy));
|
nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix2.key_read));
|
||||||
furi_string_cat_printf(temp_str, " EAS %08lX\n", nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix2.key_eas));
|
furi_string_cat_printf(
|
||||||
|
temp_str,
|
||||||
|
" Write %08lX\n",
|
||||||
|
nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix2.key_write));
|
||||||
|
furi_string_cat_printf(
|
||||||
|
temp_str,
|
||||||
|
" Privacy %08lX\n",
|
||||||
|
nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix2.key_privacy));
|
||||||
|
furi_string_cat_printf(
|
||||||
|
temp_str,
|
||||||
|
" Destroy %08lX\n",
|
||||||
|
nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix2.key_destroy));
|
||||||
|
furi_string_cat_printf(
|
||||||
|
temp_str,
|
||||||
|
" EAS %08lX\n",
|
||||||
|
nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix2.key_eas));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
furi_string_cat_printf(temp_str, "\e#ISO15693 (unknown)\n");
|
furi_string_cat_printf(temp_str, "\e#ISO15693 (unknown)\n");
|
||||||
@@ -158,7 +200,8 @@ void nfc_scene_nfc_data_info_on_enter(void* context) {
|
|||||||
for(size_t i = 0; i < nfc_data->uid_len; i++) {
|
for(size_t i = 0; i < nfc_data->uid_len; i++) {
|
||||||
furi_string_cat_printf(temp_str, " %02X", nfc_data->uid[i]);
|
furi_string_cat_printf(temp_str, " %02X", nfc_data->uid[i]);
|
||||||
}
|
}
|
||||||
furi_string_cat_printf(temp_str, "\nATQA: %02X %02X ", nfc_data->atqa[1], nfc_data->atqa[0]);
|
furi_string_cat_printf(
|
||||||
|
temp_str, "\nATQA: %02X %02X ", nfc_data->atqa[1], nfc_data->atqa[0]);
|
||||||
furi_string_cat_printf(temp_str, " SAK: %02X", nfc_data->sak);
|
furi_string_cat_printf(temp_str, " SAK: %02X", nfc_data->sak);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,8 +16,7 @@ void nfc_scene_nfcv_menu_on_enter(void* context) {
|
|||||||
Nfc* nfc = context;
|
Nfc* nfc = context;
|
||||||
Submenu* submenu = nfc->submenu;
|
Submenu* submenu = nfc->submenu;
|
||||||
|
|
||||||
submenu_add_item(
|
submenu_add_item(submenu, "Save", SubmenuIndexSave, nfc_scene_nfcv_menu_submenu_callback, nfc);
|
||||||
submenu, "Save", SubmenuIndexSave, nfc_scene_nfcv_menu_submenu_callback, nfc);
|
|
||||||
submenu_add_item(
|
submenu_add_item(
|
||||||
submenu, "Emulate", SubmenuIndexEmulate, nfc_scene_nfcv_menu_submenu_callback, nfc);
|
submenu, "Emulate", SubmenuIndexEmulate, nfc_scene_nfcv_menu_submenu_callback, nfc);
|
||||||
|
|
||||||
|
|||||||
@@ -30,29 +30,36 @@ void nfc_scene_nfcv_unlock_set_state(Nfc* nfc, NfcSceneNfcVUnlockState state) {
|
|||||||
FuriHalNfcDevData* nfc_data = &(nfc->dev->dev_data.nfc_data);
|
FuriHalNfcDevData* nfc_data = &(nfc->dev->dev_data.nfc_data);
|
||||||
NfcVData* nfcv_data = &(nfc->dev->dev_data.nfcv_data);
|
NfcVData* nfcv_data = &(nfc->dev->dev_data.nfcv_data);
|
||||||
|
|
||||||
uint32_t curr_state =
|
uint32_t curr_state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneNfcVUnlock);
|
||||||
scene_manager_get_scene_state(nfc->scene_manager, NfcSceneNfcVUnlock);
|
|
||||||
if(curr_state != state) {
|
if(curr_state != state) {
|
||||||
Popup* popup = nfc->popup;
|
Popup* popup = nfc->popup;
|
||||||
if(state == NfcSceneNfcVUnlockStateDetecting) {
|
if(state == NfcSceneNfcVUnlockStateDetecting) {
|
||||||
popup_reset(popup);
|
popup_reset(popup);
|
||||||
popup_set_text(
|
popup_set_text(popup, "Put Tonie On\nFlipper's Back", 97, 24, AlignCenter, AlignTop);
|
||||||
popup, "Put Tonie On\nFlipper's Back", 97, 24, AlignCenter, AlignTop);
|
|
||||||
popup_set_icon(popup, 0, 8, &I_NFC_manual_60x50);
|
popup_set_icon(popup, 0, 8, &I_NFC_manual_60x50);
|
||||||
} else if(state == NfcSceneNfcVUnlockStateUnlocked) {
|
} else if(state == NfcSceneNfcVUnlockStateUnlocked) {
|
||||||
popup_reset(popup);
|
popup_reset(popup);
|
||||||
|
|
||||||
if(nfc_worker_get_state(nfc->worker) == NfcWorkerStateNfcVUnlockAndSave) {
|
if(nfc_worker_get_state(nfc->worker) == NfcWorkerStateNfcVUnlockAndSave) {
|
||||||
nfc_text_store_set(nfc, "SLIX_%02X%02X%02X%02X%02X%02X%02X%02X",
|
nfc_text_store_set(
|
||||||
nfc_data->uid[0], nfc_data->uid[1], nfc_data->uid[2], nfc_data->uid[3],
|
nfc,
|
||||||
nfc_data->uid[4], nfc_data->uid[5], nfc_data->uid[6], nfc_data->uid[7]);
|
"SLIX_%02X%02X%02X%02X%02X%02X%02X%02X",
|
||||||
|
nfc_data->uid[0],
|
||||||
|
nfc_data->uid[1],
|
||||||
|
nfc_data->uid[2],
|
||||||
|
nfc_data->uid[3],
|
||||||
|
nfc_data->uid[4],
|
||||||
|
nfc_data->uid[5],
|
||||||
|
nfc_data->uid[6],
|
||||||
|
nfc_data->uid[7]);
|
||||||
|
|
||||||
nfc->dev->format = NfcDeviceSaveFormatNfcV;
|
nfc->dev->format = NfcDeviceSaveFormatNfcV;
|
||||||
|
|
||||||
if(nfc_device_save(nfc->dev, nfc->text_store)) {
|
if(nfc_device_save(nfc->dev, nfc->text_store)) {
|
||||||
popup_set_header(popup, "Successfully\nsaved", 94, 3, AlignCenter, AlignTop);
|
popup_set_header(popup, "Successfully\nsaved", 94, 3, AlignCenter, AlignTop);
|
||||||
} else {
|
} else {
|
||||||
popup_set_header(popup, "Unlocked but\nsave failed!", 94, 3, AlignCenter, AlignTop);
|
popup_set_header(
|
||||||
|
popup, "Unlocked but\nsave failed!", 94, 3, AlignCenter, AlignTop);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
popup_set_header(popup, "Successfully\nunlocked", 94, 3, AlignCenter, AlignTop);
|
popup_set_header(popup, "Successfully\nunlocked", 94, 3, AlignCenter, AlignTop);
|
||||||
@@ -82,13 +89,7 @@ void nfc_scene_nfcv_unlock_set_state(Nfc* nfc, NfcSceneNfcVUnlockState state) {
|
|||||||
} else if(state == NfcSceneNfcVUnlockStateNotSupportedCard) {
|
} else if(state == NfcSceneNfcVUnlockStateNotSupportedCard) {
|
||||||
popup_reset(popup);
|
popup_reset(popup);
|
||||||
popup_set_header(popup, "Wrong Type Of Card!", 64, 3, AlignCenter, AlignTop);
|
popup_set_header(popup, "Wrong Type Of Card!", 64, 3, AlignCenter, AlignTop);
|
||||||
popup_set_text(
|
popup_set_text(popup, nfcv_data->error, 4, 22, AlignLeft, AlignTop);
|
||||||
popup,
|
|
||||||
nfcv_data->error,
|
|
||||||
4,
|
|
||||||
22,
|
|
||||||
AlignLeft,
|
|
||||||
AlignTop);
|
|
||||||
popup_set_icon(popup, 73, 20, &I_DolphinCommon_56x48);
|
popup_set_icon(popup, 73, 20, &I_DolphinCommon_56x48);
|
||||||
}
|
}
|
||||||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneNfcVUnlock, state);
|
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneNfcVUnlock, state);
|
||||||
|
|||||||
@@ -16,8 +16,7 @@ void nfc_scene_nfcv_unlock_menu_on_enter(void* context) {
|
|||||||
Nfc* nfc = context;
|
Nfc* nfc = context;
|
||||||
Submenu* submenu = nfc->submenu;
|
Submenu* submenu = nfc->submenu;
|
||||||
|
|
||||||
uint32_t state =
|
uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneNfcVUnlockMenu);
|
||||||
scene_manager_get_scene_state(nfc->scene_manager, NfcSceneNfcVUnlockMenu);
|
|
||||||
submenu_add_item(
|
submenu_add_item(
|
||||||
submenu,
|
submenu,
|
||||||
"Enter PWD Manually",
|
"Enter PWD Manually",
|
||||||
@@ -49,8 +48,7 @@ bool nfc_scene_nfcv_unlock_menu_on_event(void* context, SceneManagerEvent event)
|
|||||||
DOLPHIN_DEED(DolphinDeedNfcRead);
|
DOLPHIN_DEED(DolphinDeedNfcRead);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
scene_manager_set_scene_state(
|
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneNfcVUnlockMenu, event.event);
|
||||||
nfc->scene_manager, NfcSceneNfcVUnlockMenu, event.event);
|
|
||||||
}
|
}
|
||||||
return consumed;
|
return consumed;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,20 +18,21 @@
|
|||||||
#define MAX_ADDR 6
|
#define MAX_ADDR 6
|
||||||
|
|
||||||
#define SCAN_APP_PATH_FOLDER "/ext/nrf24scan"
|
#define SCAN_APP_PATH_FOLDER "/ext/nrf24scan"
|
||||||
#define ADDR_FILENAME "addr.txt" // File format (1 parameter per line):
|
#define ADDR_FILENAME \
|
||||||
// Rate: 0/1/2 - rate in Mbps (=0.25/1/2)
|
"addr.txt" // File format (1 parameter per line): \
|
||||||
// Ch: 0..125 - default channel
|
// Rate: 0/1/2 - rate in Mbps (=0.25/1/2) \
|
||||||
// ESB: 0/1 (1 - Enhanced ShockBurst)
|
// Ch: 0..125 - default channel \
|
||||||
// DPL: 0/1 (1 - Dynamic Payload Length)
|
// ESB: 0/1 (1 - Enhanced ShockBurst) \
|
||||||
// CRC: 0/1/2 (CRC length)
|
// DPL: 0/1 (1 - Dynamic Payload Length) \
|
||||||
// Payload: 1..32 (bytes)
|
// CRC: 0/1/2 (CRC length) \
|
||||||
// P0: address P0 in hex (5 byte, LSB last)
|
// Payload: 1..32 (bytes) \
|
||||||
// P1: address P1 in hex (5 byte, LSB last)
|
// P0: address P0 in hex (5 byte, LSB last) \
|
||||||
// P2: address P2, LSB in hex (1 byte)
|
// P1: address P1 in hex (5 byte, LSB last) \
|
||||||
// P3: address P3, LSB in hex (1 byte)
|
// P2: address P2, LSB in hex (1 byte) \
|
||||||
// P4: address P4, LSB in hex (1 byte)
|
// P3: address P3, LSB in hex (1 byte) \
|
||||||
// P5: address P5, LSB in hex (1 byte)
|
// P4: address P4, LSB in hex (1 byte) \
|
||||||
// captured data in raw format, first byte = address # 0..5, Payload len if DPL
|
// P5: address P5, LSB in hex (1 byte) \
|
||||||
|
// captured data in raw format, first byte = address # 0..5, Payload len if DPL \
|
||||||
// ... up to MAX_LOG_RECORDS-1
|
// ... up to MAX_LOG_RECORDS-1
|
||||||
#define LOG_FILENAME "log"
|
#define LOG_FILENAME "log"
|
||||||
#define LOG_FILEEXT ".txt"
|
#define LOG_FILEEXT ".txt"
|
||||||
@@ -110,8 +111,7 @@ static uint8_t ConvertHexToArray(char * hex, uint8_t * array, uint8_t maxlen) {
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_to_str_hex_bytes(char *out, char *arr, int bytes)
|
static void add_to_str_hex_bytes(char* out, char* arr, int bytes) {
|
||||||
{
|
|
||||||
if(bytes <= 0) return;
|
if(bytes <= 0) return;
|
||||||
out += strlen(out);
|
out += strlen(out);
|
||||||
do {
|
do {
|
||||||
@@ -120,23 +120,20 @@ static void add_to_str_hex_bytes(char *out, char *arr, int bytes)
|
|||||||
} while(--bytes);
|
} while(--bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_to_furi_str_hex_bytes(FuriString* str, char *arr, int bytes)
|
static void add_to_furi_str_hex_bytes(FuriString* str, char* arr, int bytes) {
|
||||||
{
|
|
||||||
if(!bytes) return;
|
if(!bytes) return;
|
||||||
do {
|
do {
|
||||||
furi_string_cat_printf(str, "%02X", *arr++);
|
furi_string_cat_printf(str, "%02X", *arr++);
|
||||||
} while(--bytes);
|
} while(--bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear_log()
|
void clear_log() {
|
||||||
{
|
|
||||||
log_arr_idx = 0;
|
log_arr_idx = 0;
|
||||||
view_log_arr_idx = 0;
|
view_log_arr_idx = 0;
|
||||||
last_packet_send = -1;
|
last_packet_send = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void allocate_log_array()
|
void allocate_log_array() {
|
||||||
{
|
|
||||||
APP->log_arr = malloc(LOG_REC_SIZE * MAX_LOG_RECORDS);
|
APP->log_arr = malloc(LOG_REC_SIZE * MAX_LOG_RECORDS);
|
||||||
if(APP->log_arr == NULL) {
|
if(APP->log_arr == NULL) {
|
||||||
FURI_LOG_E(TAG, "Not enouch memory: %d", LOG_REC_SIZE * MAX_LOG_RECORDS);
|
FURI_LOG_E(TAG, "Not enouch memory: %d", LOG_REC_SIZE * MAX_LOG_RECORDS);
|
||||||
@@ -145,8 +142,7 @@ void allocate_log_array()
|
|||||||
clear_log();
|
clear_log();
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_to_log_file(Storage* storage)
|
void write_to_log_file(Storage* storage) {
|
||||||
{
|
|
||||||
if(log_arr_idx == 0) return;
|
if(log_arr_idx == 0) return;
|
||||||
Stream* file_stream = file_stream_alloc(storage);
|
Stream* file_stream = file_stream_alloc(storage);
|
||||||
FuriString* str = furi_string_alloc();
|
FuriString* str = furi_string_alloc();
|
||||||
@@ -158,7 +154,8 @@ void write_to_log_file(Storage* storage)
|
|||||||
if(save_to_new_log) {
|
if(save_to_new_log) {
|
||||||
int cnt = 1;
|
int cnt = 1;
|
||||||
do {
|
do {
|
||||||
fl = file_stream_open(file_stream, furi_string_get_cstr(str), FSAM_READ_WRITE, FSOM_CREATE_NEW);
|
fl = file_stream_open(
|
||||||
|
file_stream, furi_string_get_cstr(str), FSAM_READ_WRITE, FSOM_CREATE_NEW);
|
||||||
if(fl) break;
|
if(fl) break;
|
||||||
file_stream_close(file_stream);
|
file_stream_close(file_stream);
|
||||||
furi_string_set(str, SCAN_APP_PATH_FOLDER);
|
furi_string_set(str, SCAN_APP_PATH_FOLDER);
|
||||||
@@ -172,23 +169,58 @@ void write_to_log_file(Storage* storage)
|
|||||||
notification_message(APP->notification, &sequence_blink_red_100);
|
notification_message(APP->notification, &sequence_blink_red_100);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fl = file_stream_open(file_stream, furi_string_get_cstr(str), FSAM_READ_WRITE, FSOM_OPEN_APPEND);
|
fl = file_stream_open(
|
||||||
|
file_stream, furi_string_get_cstr(str), FSAM_READ_WRITE, FSOM_OPEN_APPEND);
|
||||||
if(fl) {
|
if(fl) {
|
||||||
if(stream_size(file_stream) == 0) save_to_new_log = true;
|
if(stream_size(file_stream) == 0) save_to_new_log = true;
|
||||||
} else file_stream_close(file_stream);
|
} else
|
||||||
|
file_stream_close(file_stream);
|
||||||
}
|
}
|
||||||
if(fl) {
|
if(fl) {
|
||||||
FURI_LOG_D(TAG, "Save to log %s", furi_string_get_cstr(str));
|
FURI_LOG_D(TAG, "Save to log %s", furi_string_get_cstr(str));
|
||||||
if(save_to_new_log) {
|
if(save_to_new_log) {
|
||||||
furi_string_printf(str, "%s %d\n%s %d\n%s %d\n", SettingsFld_Rate, NRF_rate, SettingsFld_Ch, NRF_channel, SettingsFld_ESB, NRF_ESB);
|
furi_string_printf(
|
||||||
furi_string_cat_printf(str, "%s %d\n%s %d\n%s %d\n", SettingsFld_DPL, NRF_DPL, SettingsFld_CRC, NRF_CRC, SettingsFld_Payload, NRF_Payload);
|
str,
|
||||||
|
"%s %d\n%s %d\n%s %d\n",
|
||||||
|
SettingsFld_Rate,
|
||||||
|
NRF_rate,
|
||||||
|
SettingsFld_Ch,
|
||||||
|
NRF_channel,
|
||||||
|
SettingsFld_ESB,
|
||||||
|
NRF_ESB);
|
||||||
|
furi_string_cat_printf(
|
||||||
|
str,
|
||||||
|
"%s %d\n%s %d\n%s %d\n",
|
||||||
|
SettingsFld_DPL,
|
||||||
|
NRF_DPL,
|
||||||
|
SettingsFld_CRC,
|
||||||
|
NRF_CRC,
|
||||||
|
SettingsFld_Payload,
|
||||||
|
NRF_Payload);
|
||||||
furi_string_cat_printf(str, "P0: ");
|
furi_string_cat_printf(str, "P0: ");
|
||||||
add_to_furi_str_hex_bytes(str, (char*)addrs.addr_P0, addrs.addr_len); furi_string_cat(str, "\n");
|
add_to_furi_str_hex_bytes(str, (char*)addrs.addr_P0, addrs.addr_len);
|
||||||
if(addrs.addr_count > 1) { furi_string_cat_printf(str, "P1: "); add_to_furi_str_hex_bytes(str, (char*)addrs.addr_P1, addrs.addr_len); furi_string_cat(str, "\n"); }
|
furi_string_cat(str, "\n");
|
||||||
if(addrs.addr_count > 2) { furi_string_cat_printf(str, "P2: "); furi_string_cat_printf(str, "%02X\n", addrs.addr_P2); }
|
if(addrs.addr_count > 1) {
|
||||||
if(addrs.addr_count > 3) { furi_string_cat_printf(str, "P3: "); furi_string_cat_printf(str, "%02X\n", addrs.addr_P3); }
|
furi_string_cat_printf(str, "P1: ");
|
||||||
if(addrs.addr_count > 4) { furi_string_cat_printf(str, "P4: "); furi_string_cat_printf(str, "%02X\n", addrs.addr_P4); }
|
add_to_furi_str_hex_bytes(str, (char*)addrs.addr_P1, addrs.addr_len);
|
||||||
if(addrs.addr_count > 5) { furi_string_cat_printf(str, "P5: "); furi_string_cat_printf(str, "%02X\n", addrs.addr_P5); }
|
furi_string_cat(str, "\n");
|
||||||
|
}
|
||||||
|
if(addrs.addr_count > 2) {
|
||||||
|
furi_string_cat_printf(str, "P2: ");
|
||||||
|
furi_string_cat_printf(str, "%02X\n", addrs.addr_P2);
|
||||||
|
}
|
||||||
|
if(addrs.addr_count > 3) {
|
||||||
|
furi_string_cat_printf(str, "P3: ");
|
||||||
|
furi_string_cat_printf(str, "%02X\n", addrs.addr_P3);
|
||||||
|
}
|
||||||
|
if(addrs.addr_count > 4) {
|
||||||
|
furi_string_cat_printf(str, "P4: ");
|
||||||
|
furi_string_cat_printf(str, "%02X\n", addrs.addr_P4);
|
||||||
|
}
|
||||||
|
if(addrs.addr_count > 5) {
|
||||||
|
furi_string_cat_printf(str, "P5: ");
|
||||||
|
furi_string_cat_printf(str, "%02X\n", addrs.addr_P5);
|
||||||
|
}
|
||||||
if(!(fl = stream_write_string(file_stream, str) == furi_string_size(str))) {
|
if(!(fl = stream_write_string(file_stream, str) == furi_string_size(str))) {
|
||||||
FURI_LOG_E(TAG, "Failed to write header to log!");
|
FURI_LOG_E(TAG, "Failed to write header to log!");
|
||||||
notification_message(APP->notification, &sequence_blink_red_100);
|
notification_message(APP->notification, &sequence_blink_red_100);
|
||||||
@@ -198,7 +230,8 @@ void write_to_log_file(Storage* storage)
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
for(; i < log_arr_idx; i++) {
|
for(; i < log_arr_idx; i++) {
|
||||||
furi_string_reset(str);
|
furi_string_reset(str);
|
||||||
add_to_furi_str_hex_bytes(str, (char*)APP->log_arr + i * LOG_REC_SIZE, LOG_REC_SIZE);
|
add_to_furi_str_hex_bytes(
|
||||||
|
str, (char*)APP->log_arr + i * LOG_REC_SIZE, LOG_REC_SIZE);
|
||||||
furi_string_cat(str, "\n");
|
furi_string_cat(str, "\n");
|
||||||
if(stream_write_string(file_stream, str) != furi_string_size(str)) {
|
if(stream_write_string(file_stream, str) != furi_string_size(str)) {
|
||||||
FURI_LOG_E(TAG, "Failed to write to log!");
|
FURI_LOG_E(TAG, "Failed to write to log!");
|
||||||
@@ -240,7 +273,10 @@ static bool select_settings_file(Stream* stream) {
|
|||||||
file_stream_close(stream);
|
file_stream_close(stream);
|
||||||
} else {
|
} else {
|
||||||
FURI_LOG_D(TAG, "Open file \"%s\"", furi_string_get_cstr(path));
|
FURI_LOG_D(TAG, "Open file \"%s\"", furi_string_get_cstr(path));
|
||||||
strncpy(addr_file_name, furi_string_get_cstr(path) + sizeof(SCAN_APP_PATH_FOLDER), sizeof(addr_file_name));
|
strncpy(
|
||||||
|
addr_file_name,
|
||||||
|
furi_string_get_cstr(path) + sizeof(SCAN_APP_PATH_FOLDER),
|
||||||
|
sizeof(addr_file_name));
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -272,7 +308,10 @@ static uint8_t load_settings_file(Stream* file_stream) {
|
|||||||
bool log_loaded = 3;
|
bool log_loaded = 3;
|
||||||
while(line_ptr && line_ptr - file_buf < file_size) {
|
while(line_ptr && line_ptr - file_buf < file_size) {
|
||||||
char* end_ptr = strstr((char*)line_ptr, "\n");
|
char* end_ptr = strstr((char*)line_ptr, "\n");
|
||||||
if(end_ptr == NULL) end_ptr = file_buf + file_size; else *end_ptr = '\0';
|
if(end_ptr == NULL)
|
||||||
|
end_ptr = file_buf + file_size;
|
||||||
|
else
|
||||||
|
*end_ptr = '\0';
|
||||||
int line_len = end_ptr - line_ptr;
|
int line_len = end_ptr - line_ptr;
|
||||||
if(*line_ptr == '\r' || line_len == 0) {
|
if(*line_ptr == '\r' || line_len == 0) {
|
||||||
line_ptr = end_ptr + 1;
|
line_ptr = end_ptr + 1;
|
||||||
@@ -302,12 +341,23 @@ static uint8_t load_settings_file(Stream* file_stream) {
|
|||||||
switch(a) {
|
switch(a) {
|
||||||
case '0':
|
case '0':
|
||||||
addrs.addr_len = ConvertHexToArray(line_ptr, addrs.addr_P0, 5);
|
addrs.addr_len = ConvertHexToArray(line_ptr, addrs.addr_P0, 5);
|
||||||
FURI_LOG_D(TAG, " +Addr(%d): %02X%02X%02X...", addrs.addr_len, addrs.addr_P0[0], addrs.addr_P0[1], addrs.addr_P0[2]);
|
FURI_LOG_D(
|
||||||
|
TAG,
|
||||||
|
" +Addr(%d): %02X%02X%02X...",
|
||||||
|
addrs.addr_len,
|
||||||
|
addrs.addr_P0[0],
|
||||||
|
addrs.addr_P0[1],
|
||||||
|
addrs.addr_P0[2]);
|
||||||
loaded = true;
|
loaded = true;
|
||||||
break;
|
break;
|
||||||
case '1':
|
case '1':
|
||||||
ConvertHexToArray(line_ptr, addrs.addr_P1, 5);
|
ConvertHexToArray(line_ptr, addrs.addr_P1, 5);
|
||||||
FURI_LOG_D(TAG, " +Addr: %02X%02X%02X...", addrs.addr_P0[1], addrs.addr_P1[1], addrs.addr_P1[2]);
|
FURI_LOG_D(
|
||||||
|
TAG,
|
||||||
|
" +Addr: %02X%02X%02X...",
|
||||||
|
addrs.addr_P0[1],
|
||||||
|
addrs.addr_P1[1],
|
||||||
|
addrs.addr_P1[2]);
|
||||||
break;
|
break;
|
||||||
case '2':
|
case '2':
|
||||||
ConvertHexToArray(line_ptr, &addrs.addr_P2, 1);
|
ConvertHexToArray(line_ptr, &addrs.addr_P2, 1);
|
||||||
@@ -333,7 +383,8 @@ static uint8_t load_settings_file(Stream* file_stream) {
|
|||||||
log_loaded = 0;
|
log_loaded = 0;
|
||||||
}
|
}
|
||||||
if(log_arr_idx < MAX_LOG_RECORDS - 1) {
|
if(log_arr_idx < MAX_LOG_RECORDS - 1) {
|
||||||
ConvertHexToArray(line_ptr, APP->log_arr + log_arr_idx * LOG_REC_SIZE, LOG_REC_SIZE);
|
ConvertHexToArray(
|
||||||
|
line_ptr, APP->log_arr + log_arr_idx * LOG_REC_SIZE, LOG_REC_SIZE);
|
||||||
log_arr_idx++;
|
log_arr_idx++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -354,52 +405,64 @@ static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queu
|
|||||||
furi_message_queue_put(event_queue, &event, FuriWaitForever);
|
furi_message_queue_put(event_queue, &event, FuriWaitForever);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void prepare_nrf24()
|
static void prepare_nrf24() {
|
||||||
{
|
|
||||||
uint8_t addr[5];
|
uint8_t addr[5];
|
||||||
uint8_t erx_addr = (1 << 0); // Enable RX_P0
|
uint8_t erx_addr = (1 << 0); // Enable RX_P0
|
||||||
if(addrs.addr_count == 0) return;
|
if(addrs.addr_count == 0) return;
|
||||||
nrf24_write_reg(nrf24_HANDLE, REG_CONFIG, NRF_CRC == 1 ? 0b1000 : NRF_CRC == 2 ? 0b1100 : 0);
|
nrf24_write_reg(nrf24_HANDLE, REG_CONFIG, NRF_CRC == 1 ? 0b1000 : NRF_CRC == 2 ? 0b1100 : 0);
|
||||||
nrf24_write_reg(nrf24_HANDLE, REG_STATUS, 0x70); // clear interrupts
|
nrf24_write_reg(nrf24_HANDLE, REG_STATUS, 0x70); // clear interrupts
|
||||||
nrf24_write_reg(nrf24_HANDLE, REG_SETUP_RETR, NRF_ESB ? 1 : 0); // Disable Automatic Retransmission
|
nrf24_write_reg(
|
||||||
|
nrf24_HANDLE, REG_SETUP_RETR, NRF_ESB ? 1 : 0); // Disable Automatic Retransmission
|
||||||
nrf24_write_reg(nrf24_HANDLE, REG_EN_AA, NRF_ESB ? 0x3F : 0); // Auto acknowledgement
|
nrf24_write_reg(nrf24_HANDLE, REG_EN_AA, NRF_ESB ? 0x3F : 0); // Auto acknowledgement
|
||||||
nrf24_write_reg(nrf24_HANDLE, REG_FEATURE, 1 + (NRF_DPL || NRF_ESB ? 4 : 1)); // Enables the W_TX_PAYLOAD_NOACK command, Disable Payload with ACK, set Dynamic Payload
|
nrf24_write_reg(
|
||||||
|
nrf24_HANDLE,
|
||||||
|
REG_FEATURE,
|
||||||
|
1 + (NRF_DPL || NRF_ESB ?
|
||||||
|
4 :
|
||||||
|
1)); // Enables the W_TX_PAYLOAD_NOACK command, Disable Payload with ACK, set Dynamic Payload
|
||||||
nrf24_set_maclen(nrf24_HANDLE, addrs.addr_len);
|
nrf24_set_maclen(nrf24_HANDLE, addrs.addr_len);
|
||||||
for(int i = 0; i < addrs.addr_len; i++) addr[i] = addrs.addr_P0[addrs.addr_len - i - 1];
|
for(int i = 0; i < addrs.addr_len; i++) addr[i] = addrs.addr_P0[addrs.addr_len - i - 1];
|
||||||
nrf24_write_buf_reg(nrf24_HANDLE, REG_RX_ADDR_P0, &addr[0], addrs.addr_len);
|
nrf24_write_buf_reg(nrf24_HANDLE, REG_RX_ADDR_P0, &addr[0], addrs.addr_len);
|
||||||
nrf24_write_reg(nrf24_HANDLE, RX_PW_P0, NRF_Payload);
|
nrf24_write_reg(nrf24_HANDLE, RX_PW_P0, NRF_Payload);
|
||||||
if(addrs.addr_count == 1) nrf24_write_reg(nrf24_HANDLE, REG_DYNPD, NRF_DPL ? (1<<0) : 0); // Enable dynamic payload reg
|
if(addrs.addr_count == 1)
|
||||||
|
nrf24_write_reg(
|
||||||
|
nrf24_HANDLE, REG_DYNPD, NRF_DPL ? (1 << 0) : 0); // Enable dynamic payload reg
|
||||||
if(addrs.addr_count > 1) {
|
if(addrs.addr_count > 1) {
|
||||||
for(int i = 0; i < addrs.addr_len; i++) addr[i] = addrs.addr_P1[addrs.addr_len - i - 1];
|
for(int i = 0; i < addrs.addr_len; i++) addr[i] = addrs.addr_P1[addrs.addr_len - i - 1];
|
||||||
nrf24_write_buf_reg(nrf24_HANDLE, REG_RX_ADDR_P1, &addr[0], addrs.addr_len);
|
nrf24_write_buf_reg(nrf24_HANDLE, REG_RX_ADDR_P1, &addr[0], addrs.addr_len);
|
||||||
nrf24_write_reg(nrf24_HANDLE, RX_PW_P1, NRF_Payload);
|
nrf24_write_reg(nrf24_HANDLE, RX_PW_P1, NRF_Payload);
|
||||||
nrf24_write_reg(nrf24_HANDLE, REG_DYNPD, NRF_DPL ? (1 << 1) : 0);
|
nrf24_write_reg(nrf24_HANDLE, REG_DYNPD, NRF_DPL ? (1 << 1) : 0);
|
||||||
erx_addr |= (1 << 1); // Enable RX_P1
|
erx_addr |= (1 << 1); // Enable RX_P1
|
||||||
} else nrf24_write_reg(nrf24_HANDLE, RX_PW_P1, 0);
|
} else
|
||||||
|
nrf24_write_reg(nrf24_HANDLE, RX_PW_P1, 0);
|
||||||
if(addrs.addr_count > 2) {
|
if(addrs.addr_count > 2) {
|
||||||
nrf24_write_buf_reg(nrf24_HANDLE, REG_RX_ADDR_P2, &addrs.addr_P2, 1);
|
nrf24_write_buf_reg(nrf24_HANDLE, REG_RX_ADDR_P2, &addrs.addr_P2, 1);
|
||||||
nrf24_write_reg(nrf24_HANDLE, RX_PW_P2, NRF_Payload);
|
nrf24_write_reg(nrf24_HANDLE, RX_PW_P2, NRF_Payload);
|
||||||
nrf24_write_reg(nrf24_HANDLE, REG_DYNPD, NRF_DPL ? (1 << 2) : 0);
|
nrf24_write_reg(nrf24_HANDLE, REG_DYNPD, NRF_DPL ? (1 << 2) : 0);
|
||||||
erx_addr |= (1 << 2); // Enable RX_P2
|
erx_addr |= (1 << 2); // Enable RX_P2
|
||||||
} else nrf24_write_reg(nrf24_HANDLE, RX_PW_P2, 0);
|
} else
|
||||||
|
nrf24_write_reg(nrf24_HANDLE, RX_PW_P2, 0);
|
||||||
if(addrs.addr_count > 3) {
|
if(addrs.addr_count > 3) {
|
||||||
nrf24_write_buf_reg(nrf24_HANDLE, REG_RX_ADDR_P3, &addrs.addr_P3, 1);
|
nrf24_write_buf_reg(nrf24_HANDLE, REG_RX_ADDR_P3, &addrs.addr_P3, 1);
|
||||||
nrf24_write_reg(nrf24_HANDLE, RX_PW_P3, NRF_Payload);
|
nrf24_write_reg(nrf24_HANDLE, RX_PW_P3, NRF_Payload);
|
||||||
nrf24_write_reg(nrf24_HANDLE, REG_DYNPD, NRF_DPL ? (1 << 3) : 0);
|
nrf24_write_reg(nrf24_HANDLE, REG_DYNPD, NRF_DPL ? (1 << 3) : 0);
|
||||||
erx_addr |= (1 << 3); // Enable RX_P3
|
erx_addr |= (1 << 3); // Enable RX_P3
|
||||||
} else nrf24_write_reg(nrf24_HANDLE, RX_PW_P3, 0);
|
} else
|
||||||
|
nrf24_write_reg(nrf24_HANDLE, RX_PW_P3, 0);
|
||||||
if(addrs.addr_count > 4) {
|
if(addrs.addr_count > 4) {
|
||||||
nrf24_write_buf_reg(nrf24_HANDLE, REG_RX_ADDR_P4, &addrs.addr_P4, 1);
|
nrf24_write_buf_reg(nrf24_HANDLE, REG_RX_ADDR_P4, &addrs.addr_P4, 1);
|
||||||
nrf24_write_reg(nrf24_HANDLE, RX_PW_P4, NRF_Payload);
|
nrf24_write_reg(nrf24_HANDLE, RX_PW_P4, NRF_Payload);
|
||||||
nrf24_write_reg(nrf24_HANDLE, REG_DYNPD, NRF_DPL ? (1 << 4) : 0);
|
nrf24_write_reg(nrf24_HANDLE, REG_DYNPD, NRF_DPL ? (1 << 4) : 0);
|
||||||
erx_addr |= (1 << 4); // Enable RX_P4
|
erx_addr |= (1 << 4); // Enable RX_P4
|
||||||
} else nrf24_write_reg(nrf24_HANDLE, RX_PW_P4, 0);
|
} else
|
||||||
|
nrf24_write_reg(nrf24_HANDLE, RX_PW_P4, 0);
|
||||||
if(addrs.addr_count > 5) {
|
if(addrs.addr_count > 5) {
|
||||||
nrf24_write_buf_reg(nrf24_HANDLE, REG_RX_ADDR_P5, &addrs.addr_P5, 1);
|
nrf24_write_buf_reg(nrf24_HANDLE, REG_RX_ADDR_P5, &addrs.addr_P5, 1);
|
||||||
nrf24_write_reg(nrf24_HANDLE, RX_PW_P5, NRF_Payload);
|
nrf24_write_reg(nrf24_HANDLE, RX_PW_P5, NRF_Payload);
|
||||||
nrf24_write_reg(nrf24_HANDLE, REG_DYNPD, NRF_DPL ? (1 << 5) : 0);
|
nrf24_write_reg(nrf24_HANDLE, REG_DYNPD, NRF_DPL ? (1 << 5) : 0);
|
||||||
erx_addr |= (1 << 5); // Enable RX_P5
|
erx_addr |= (1 << 5); // Enable RX_P5
|
||||||
} else nrf24_write_reg(nrf24_HANDLE, RX_PW_P5, 0);
|
} else
|
||||||
|
nrf24_write_reg(nrf24_HANDLE, RX_PW_P5, 0);
|
||||||
nrf24_write_reg(nrf24_HANDLE, REG_STATUS, 0x50); // clear RX_DR, MAX_RT.
|
nrf24_write_reg(nrf24_HANDLE, REG_STATUS, 0x50); // clear RX_DR, MAX_RT.
|
||||||
nrf24_write_reg(nrf24_HANDLE, REG_EN_RXADDR, erx_addr);
|
nrf24_write_reg(nrf24_HANDLE, REG_EN_RXADDR, erx_addr);
|
||||||
nrf24_write_reg(nrf24_HANDLE, REG_RF_CH, NRF_channel);
|
nrf24_write_reg(nrf24_HANDLE, REG_RF_CH, NRF_channel);
|
||||||
@@ -409,8 +472,7 @@ static void prepare_nrf24()
|
|||||||
nrf24_set_idle(nrf24_HANDLE);
|
nrf24_set_idle(nrf24_HANDLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void start_scanning()
|
static void start_scanning() {
|
||||||
{
|
|
||||||
prepare_nrf24();
|
prepare_nrf24();
|
||||||
nrf24_set_rx_mode(nrf24_HANDLE);
|
nrf24_set_rx_mode(nrf24_HANDLE);
|
||||||
start_time = furi_get_tick();
|
start_time = furi_get_tick();
|
||||||
@@ -444,13 +506,15 @@ bool nrf24_read_newpacket() {
|
|||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nrf24_send_packet()
|
bool nrf24_send_packet() {
|
||||||
{
|
|
||||||
if(log_arr_idx == 0) return false;
|
if(log_arr_idx == 0) return false;
|
||||||
if(!what_to_do) prepare_nrf24();
|
if(!what_to_do) prepare_nrf24();
|
||||||
last_packet_send_st = nrf24_txpacket(nrf24_HANDLE, APP->log_arr + view_log_arr_idx * LOG_REC_SIZE + 1, 32, false);
|
last_packet_send_st = nrf24_txpacket(
|
||||||
|
nrf24_HANDLE, APP->log_arr + view_log_arr_idx * LOG_REC_SIZE + 1, 32, false);
|
||||||
last_packet_send = view_log_arr_idx;
|
last_packet_send = view_log_arr_idx;
|
||||||
notification_message(APP->notification, last_packet_send_st ? &sequence_blink_blue_100 : &sequence_blink_red_100);
|
notification_message(
|
||||||
|
APP->notification,
|
||||||
|
last_packet_send_st ? &sequence_blink_blue_100 : &sequence_blink_red_100);
|
||||||
if(what_to_do) start_scanning();
|
if(what_to_do) start_scanning();
|
||||||
return last_packet_send_st;
|
return last_packet_send_st;
|
||||||
}
|
}
|
||||||
@@ -461,7 +525,8 @@ static void render_callback(Canvas* const canvas, void* ctx) {
|
|||||||
//canvas_draw_frame(canvas, 0, 0, 128, 64); // border around the edge of the screen
|
//canvas_draw_frame(canvas, 0, 0, 128, 64); // border around the edge of the screen
|
||||||
if(what_doing == 0) {
|
if(what_doing == 0) {
|
||||||
canvas_set_font(canvas, FontSecondary); // 8x10 font
|
canvas_set_font(canvas, FontSecondary); // 8x10 font
|
||||||
snprintf(screen_buf, sizeof(screen_buf), "Settings: %s", addr_file_name); // menu_selected = 0
|
snprintf(
|
||||||
|
screen_buf, sizeof(screen_buf), "Settings: %s", addr_file_name); // menu_selected = 0
|
||||||
canvas_draw_str(canvas, 10, 10, screen_buf);
|
canvas_draw_str(canvas, 10, 10, screen_buf);
|
||||||
snprintf(screen_buf, sizeof(screen_buf), "Ch: %d", NRF_channel); // menu_selected = 1
|
snprintf(screen_buf, sizeof(screen_buf), "Ch: %d", NRF_channel); // menu_selected = 1
|
||||||
canvas_draw_str(canvas, 10, 20, screen_buf);
|
canvas_draw_str(canvas, 10, 20, screen_buf);
|
||||||
@@ -470,39 +535,79 @@ static void render_callback(Canvas* const canvas, void* ctx) {
|
|||||||
if(NRF_DPL) strcat(screen_buf, " DPL");
|
if(NRF_DPL) strcat(screen_buf, " DPL");
|
||||||
canvas_draw_str(canvas, 80, 20, screen_buf);
|
canvas_draw_str(canvas, 80, 20, screen_buf);
|
||||||
}
|
}
|
||||||
snprintf(screen_buf, sizeof(screen_buf), "Rate: %sbps", NRF_rate == 2 ? "2M" : NRF_rate == 1 ? "1M" : "250K"); // menu_selected = 2
|
snprintf(
|
||||||
|
screen_buf,
|
||||||
|
sizeof(screen_buf),
|
||||||
|
"Rate: %sbps",
|
||||||
|
NRF_rate == 2 ? "2M" :
|
||||||
|
NRF_rate == 1 ? "1M" :
|
||||||
|
"250K"); // menu_selected = 2
|
||||||
canvas_draw_str(canvas, 10, 30, screen_buf);
|
canvas_draw_str(canvas, 10, 30, screen_buf);
|
||||||
canvas_set_font(canvas, FontBatteryPercent);
|
canvas_set_font(canvas, FontBatteryPercent);
|
||||||
snprintf(screen_buf, sizeof(screen_buf), "R:%d", NRF_Payload);
|
snprintf(screen_buf, sizeof(screen_buf), "R:%d", NRF_Payload);
|
||||||
canvas_draw_str(canvas, 80, 30, screen_buf);
|
canvas_draw_str(canvas, 80, 30, screen_buf);
|
||||||
if(NRF_CRC == 1) canvas_draw_str(canvas, 105, 30, "CRC1");
|
if(NRF_CRC == 1)
|
||||||
else if(NRF_CRC == 2) canvas_draw_str(canvas, 105, 30, "CRC2");
|
canvas_draw_str(canvas, 105, 30, "CRC1");
|
||||||
|
else if(NRF_CRC == 2)
|
||||||
|
canvas_draw_str(canvas, 105, 30, "CRC2");
|
||||||
canvas_set_font(canvas, FontSecondary);
|
canvas_set_font(canvas, FontSecondary);
|
||||||
strcpy(screen_buf, "Find channel period: "); // menu_selected = 3
|
strcpy(screen_buf, "Find channel period: "); // menu_selected = 3
|
||||||
if(find_channel_period == 0) strcat(screen_buf, "off"); else snprintf(screen_buf + strlen(screen_buf), sizeof(screen_buf), "%d s", find_channel_period);
|
if(find_channel_period == 0)
|
||||||
|
strcat(screen_buf, "off");
|
||||||
|
else
|
||||||
|
snprintf(
|
||||||
|
screen_buf + strlen(screen_buf), sizeof(screen_buf), "%d s", find_channel_period);
|
||||||
canvas_draw_str(canvas, 10, 40, screen_buf);
|
canvas_draw_str(canvas, 10, 40, screen_buf);
|
||||||
snprintf(screen_buf, sizeof(screen_buf), "Log: %s", log_to_file == 0 ? "No" : log_to_file == 1 ? "Yes" : log_to_file == 2 ? "Append" : "Clear");// menu_selected = 4
|
snprintf(
|
||||||
|
screen_buf,
|
||||||
|
sizeof(screen_buf),
|
||||||
|
"Log: %s",
|
||||||
|
log_to_file == 0 ? "No" :
|
||||||
|
log_to_file == 1 ? "Yes" :
|
||||||
|
log_to_file == 2 ? "Append" :
|
||||||
|
"Clear"); // menu_selected = 4
|
||||||
canvas_draw_str(canvas, 10, 50, screen_buf);
|
canvas_draw_str(canvas, 10, 50, screen_buf);
|
||||||
snprintf(screen_buf, sizeof(screen_buf), "%s (pipes: %d)", what_to_do ? "Start scan" : "View log", addrs.addr_count); // menu_selected = 5
|
snprintf(
|
||||||
|
screen_buf,
|
||||||
|
sizeof(screen_buf),
|
||||||
|
"%s (pipes: %d)",
|
||||||
|
what_to_do ? "Start scan" : "View log",
|
||||||
|
addrs.addr_count); // menu_selected = 5
|
||||||
canvas_draw_str(canvas, 10, 60, screen_buf);
|
canvas_draw_str(canvas, 10, 60, screen_buf);
|
||||||
canvas_draw_str(canvas, 0, menu_selected * 10 + 10, ">");
|
canvas_draw_str(canvas, 0, menu_selected * 10 + 10, ">");
|
||||||
} else {
|
} else {
|
||||||
canvas_set_font(canvas, FontBatteryPercent); // 5x7 font, 9 lines
|
canvas_set_font(canvas, FontBatteryPercent); // 5x7 font, 9 lines
|
||||||
bool ch2 = false;
|
bool ch2 = false;
|
||||||
screen_buf[0] = '\0';
|
screen_buf[0] = '\0';
|
||||||
if(view_log_arr_x == 0) { strcat(screen_buf, " "); ch2 = true;
|
if(view_log_arr_x == 0) {
|
||||||
|
strcat(screen_buf, " ");
|
||||||
|
ch2 = true;
|
||||||
} else {
|
} else {
|
||||||
snprintf(screen_buf, sizeof(screen_buf), "<%d", view_log_arr_x);
|
snprintf(screen_buf, sizeof(screen_buf), "<%d", view_log_arr_x);
|
||||||
if(view_log_arr_x < VIEW_LOG_MAX_X) ch2 = true;
|
if(view_log_arr_x < VIEW_LOG_MAX_X) ch2 = true;
|
||||||
}
|
}
|
||||||
snprintf(screen_buf + strlen(screen_buf), sizeof(screen_buf), " %s ch: %d - %d.", what_to_do ? "Read" : "View", NRF_channel, log_arr_idx);
|
snprintf(
|
||||||
|
screen_buf + strlen(screen_buf),
|
||||||
|
sizeof(screen_buf),
|
||||||
|
" %s ch: %d - %d.",
|
||||||
|
what_to_do ? "Read" : "View",
|
||||||
|
NRF_channel,
|
||||||
|
log_arr_idx);
|
||||||
canvas_draw_str(canvas, 0, 7, screen_buf);
|
canvas_draw_str(canvas, 0, 7, screen_buf);
|
||||||
if(ch2) canvas_draw_str(canvas, 121, 7, ">");
|
if(ch2) canvas_draw_str(canvas, 121, 7, ">");
|
||||||
if(log_arr_idx) {
|
if(log_arr_idx) {
|
||||||
if(view_log_arr_idx >= log_arr_idx) view_log_arr_idx = log_arr_idx - 1;
|
if(view_log_arr_idx >= log_arr_idx) view_log_arr_idx = log_arr_idx - 1;
|
||||||
uint16_t page = view_log_arr_idx & ~7;
|
uint16_t page = view_log_arr_idx & ~7;
|
||||||
for(uint8_t i = 0; i < 8 && page + i < log_arr_idx; i++) {
|
for(uint8_t i = 0; i < 8 && page + i < log_arr_idx; i++) {
|
||||||
snprintf(screen_buf, sizeof(screen_buf), "%d:%c", page + i + 1, (view_log_arr_idx & 7) != i ? ' ' : last_packet_send != view_log_arr_idx ? '>' : last_packet_send_st ? '+' : '!');
|
snprintf(
|
||||||
|
screen_buf,
|
||||||
|
sizeof(screen_buf),
|
||||||
|
"%d:%c",
|
||||||
|
page + i + 1,
|
||||||
|
(view_log_arr_idx & 7) != i ? ' ' :
|
||||||
|
last_packet_send != view_log_arr_idx ? '>' :
|
||||||
|
last_packet_send_st ? '+' :
|
||||||
|
'!');
|
||||||
char* ptr = (char*)APP->log_arr + (page + i) * LOG_REC_SIZE;
|
char* ptr = (char*)APP->log_arr + (page + i) * LOG_REC_SIZE;
|
||||||
uint8_t dpl = *ptr++;
|
uint8_t dpl = *ptr++;
|
||||||
uint8_t pipe = dpl & 7;
|
uint8_t pipe = dpl & 7;
|
||||||
@@ -559,7 +664,10 @@ int32_t nrf24scan_app(void* p) {
|
|||||||
furi_string_cat(path, ADDR_FILENAME);
|
furi_string_cat(path, ADDR_FILENAME);
|
||||||
if(file_stream_open(file_stream, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
|
if(file_stream_open(file_stream, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||||
uint8_t err = load_settings_file(file_stream);
|
uint8_t err = load_settings_file(file_stream);
|
||||||
if(!err) strcpy(addr_file_name, ADDR_FILENAME); else snprintf(addr_file_name, sizeof(addr_file_name), "LOAD ERROR#%d", err);
|
if(!err)
|
||||||
|
strcpy(addr_file_name, ADDR_FILENAME);
|
||||||
|
else
|
||||||
|
snprintf(addr_file_name, sizeof(addr_file_name), "LOAD ERROR#%d", err);
|
||||||
} else {
|
} else {
|
||||||
strcpy(addr_file_name, "NONE");
|
strcpy(addr_file_name, "NONE");
|
||||||
}
|
}
|
||||||
@@ -580,7 +688,10 @@ int32_t nrf24scan_app(void* p) {
|
|||||||
case InputKeyUp:
|
case InputKeyUp:
|
||||||
if(event.input.type == InputTypePress || event.input.type == InputTypeRepeat) {
|
if(event.input.type == InputTypePress || event.input.type == InputTypeRepeat) {
|
||||||
if(what_doing == 0) {
|
if(what_doing == 0) {
|
||||||
if(menu_selected > 0) menu_selected--; else menu_selected = menu_selected_max;
|
if(menu_selected > 0)
|
||||||
|
menu_selected--;
|
||||||
|
else
|
||||||
|
menu_selected = menu_selected_max;
|
||||||
} else {
|
} else {
|
||||||
view_log_arr_idx -= event.input.type == InputTypeRepeat ? 10 : 1;
|
view_log_arr_idx -= event.input.type == InputTypeRepeat ? 10 : 1;
|
||||||
if(view_log_arr_idx >= log_arr_idx) view_log_arr_idx = 0;
|
if(view_log_arr_idx >= log_arr_idx) view_log_arr_idx = 0;
|
||||||
@@ -590,7 +701,10 @@ int32_t nrf24scan_app(void* p) {
|
|||||||
case InputKeyDown:
|
case InputKeyDown:
|
||||||
if(event.input.type == InputTypePress || event.input.type == InputTypeRepeat) {
|
if(event.input.type == InputTypePress || event.input.type == InputTypeRepeat) {
|
||||||
if(what_doing == 0) {
|
if(what_doing == 0) {
|
||||||
if(menu_selected < menu_selected_max) menu_selected++; else menu_selected = 0;
|
if(menu_selected < menu_selected_max)
|
||||||
|
menu_selected++;
|
||||||
|
else
|
||||||
|
menu_selected = 0;
|
||||||
} else {
|
} else {
|
||||||
view_log_arr_idx += event.input.type == InputTypeRepeat ? 10 : 1;
|
view_log_arr_idx += event.input.type == InputTypeRepeat ? 10 : 1;
|
||||||
if(view_log_arr_idx >= log_arr_idx) view_log_arr_idx = log_arr_idx - 1;
|
if(view_log_arr_idx >= log_arr_idx) view_log_arr_idx = log_arr_idx - 1;
|
||||||
@@ -610,7 +724,8 @@ int32_t nrf24scan_app(void* p) {
|
|||||||
if(NRF_rate > 2) NRF_rate = 0;
|
if(NRF_rate > 2) NRF_rate = 0;
|
||||||
break;
|
break;
|
||||||
case Menu_enter_scan_period:
|
case Menu_enter_scan_period:
|
||||||
find_channel_period += event.input.type == InputTypeRepeat ? 10 : 1;
|
find_channel_period += event.input.type == InputTypeRepeat ? 10 :
|
||||||
|
1;
|
||||||
break;
|
break;
|
||||||
case Menu_log:
|
case Menu_log:
|
||||||
if(++log_to_file > 2) log_to_file = -1;
|
if(++log_to_file > 2) log_to_file = -1;
|
||||||
@@ -637,7 +752,8 @@ int32_t nrf24scan_app(void* p) {
|
|||||||
if(NRF_Payload == 0 || NRF_Payload > 32) NRF_Payload = 32;
|
if(NRF_Payload == 0 || NRF_Payload > 32) NRF_Payload = 32;
|
||||||
break;
|
break;
|
||||||
case Menu_enter_scan_period:
|
case Menu_enter_scan_period:
|
||||||
find_channel_period -= event.input.type == InputTypeRepeat ? 10 : 1;
|
find_channel_period -= event.input.type == InputTypeRepeat ? 10 :
|
||||||
|
1;
|
||||||
if(find_channel_period < 0) find_channel_period = 0;
|
if(find_channel_period < 0) find_channel_period = 0;
|
||||||
break;
|
break;
|
||||||
case Menu_log:
|
case Menu_log:
|
||||||
@@ -660,15 +776,26 @@ int32_t nrf24scan_app(void* p) {
|
|||||||
file_stream = file_stream_alloc(APP->storage);
|
file_stream = file_stream_alloc(APP->storage);
|
||||||
if(select_settings_file(file_stream)) {
|
if(select_settings_file(file_stream)) {
|
||||||
uint8_t err = load_settings_file(file_stream);
|
uint8_t err = load_settings_file(file_stream);
|
||||||
if(!err) save_to_new_log = true; else snprintf(addr_file_name, sizeof(addr_file_name), "LOAD ERROR#%d", err);
|
if(!err)
|
||||||
|
save_to_new_log = true;
|
||||||
|
else
|
||||||
|
snprintf(
|
||||||
|
addr_file_name,
|
||||||
|
sizeof(addr_file_name),
|
||||||
|
"LOAD ERROR#%d",
|
||||||
|
err);
|
||||||
file_stream_close(file_stream);
|
file_stream_close(file_stream);
|
||||||
}
|
}
|
||||||
stream_free(file_stream);
|
stream_free(file_stream);
|
||||||
break;
|
break;
|
||||||
case Menu_enter_channel:
|
case Menu_enter_channel:
|
||||||
if(NRF_ESB) {
|
if(NRF_ESB) {
|
||||||
if(NRF_DPL) NRF_DPL = NRF_ESB = 0; else NRF_DPL = 1;
|
if(NRF_DPL)
|
||||||
} else NRF_ESB = 1;
|
NRF_DPL = NRF_ESB = 0;
|
||||||
|
else
|
||||||
|
NRF_DPL = 1;
|
||||||
|
} else
|
||||||
|
NRF_ESB = 1;
|
||||||
break;
|
break;
|
||||||
case Menu_enter_rate:
|
case Menu_enter_rate:
|
||||||
if(++NRF_CRC > 2) NRF_CRC = 0;
|
if(++NRF_CRC > 2) NRF_CRC = 0;
|
||||||
@@ -677,16 +804,19 @@ int32_t nrf24scan_app(void* p) {
|
|||||||
what_doing = !what_doing;
|
what_doing = !what_doing;
|
||||||
if(what_doing) {
|
if(what_doing) {
|
||||||
if(what_to_do) {
|
if(what_to_do) {
|
||||||
if(addrs.addr_count == 0) what_doing = 0;
|
if(addrs.addr_count == 0)
|
||||||
|
what_doing = 0;
|
||||||
else {
|
else {
|
||||||
if(log_to_file == -1) {
|
if(log_to_file == -1) {
|
||||||
clear_log();
|
clear_log();
|
||||||
save_to_new_log = true;
|
save_to_new_log = true;
|
||||||
} else if(log_to_file == 1) save_to_new_log = true;
|
} else if(log_to_file == 1)
|
||||||
|
save_to_new_log = true;
|
||||||
start_scanning();
|
start_scanning();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else nrf24_set_idle(nrf24_HANDLE);
|
} else
|
||||||
|
nrf24_set_idle(nrf24_HANDLE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else { // Send
|
} else { // Send
|
||||||
@@ -702,12 +832,14 @@ int32_t nrf24scan_app(void* p) {
|
|||||||
}
|
}
|
||||||
nrf24_set_idle(nrf24_HANDLE);
|
nrf24_set_idle(nrf24_HANDLE);
|
||||||
} else if(what_doing == 1) {
|
} else if(what_doing == 1) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case InputKeyBack:
|
case InputKeyBack:
|
||||||
if(event.input.type == InputTypeLong) processing = false; else what_doing = 0;
|
if(event.input.type == InputTypeLong)
|
||||||
|
processing = false;
|
||||||
|
else
|
||||||
|
what_doing = 0;
|
||||||
nrf24_set_idle(nrf24_HANDLE);
|
nrf24_set_idle(nrf24_HANDLE);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -717,7 +849,8 @@ int32_t nrf24scan_app(void* p) {
|
|||||||
}
|
}
|
||||||
if(what_to_do) {
|
if(what_to_do) {
|
||||||
nrf24_read_newpacket();
|
nrf24_read_newpacket();
|
||||||
if(find_channel_period && furi_get_tick() - start_time >= (uint32_t)find_channel_period * 1000UL) {
|
if(find_channel_period &&
|
||||||
|
furi_get_tick() - start_time >= (uint32_t)find_channel_period * 1000UL) {
|
||||||
if(++NRF_channel > MAX_CHANNEL) NRF_channel = 0;
|
if(++NRF_channel > MAX_CHANNEL) NRF_channel = 0;
|
||||||
start_scanning();
|
start_scanning();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,12 +6,10 @@
|
|||||||
|
|
||||||
#define TAG "DigitalSignal"
|
#define TAG "DigitalSignal"
|
||||||
|
|
||||||
|
|
||||||
#define F_TIM (64000000.0)
|
#define F_TIM (64000000.0)
|
||||||
#define T_TIM 1562 /* 15.625 ns *100 */
|
#define T_TIM 1562 /* 15.625 ns *100 */
|
||||||
#define T_TIM_DIV2 781 /* 15.625 ns / 2 *100 */
|
#define T_TIM_DIV2 781 /* 15.625 ns / 2 *100 */
|
||||||
|
|
||||||
|
|
||||||
DigitalSignal* digital_signal_alloc(uint32_t max_edges_cnt) {
|
DigitalSignal* digital_signal_alloc(uint32_t max_edges_cnt) {
|
||||||
DigitalSignal* signal = malloc(sizeof(DigitalSignal));
|
DigitalSignal* signal = malloc(sizeof(DigitalSignal));
|
||||||
signal->start_level = true;
|
signal->start_level = true;
|
||||||
@@ -198,7 +196,6 @@ static bool digital_signal_setup_dma(DigitalSignal* signal) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void digital_signal_setup_timer() {
|
static void digital_signal_setup_timer() {
|
||||||
|
|
||||||
digital_signal_stop_timer();
|
digital_signal_stop_timer();
|
||||||
|
|
||||||
LL_TIM_SetCounterMode(TIM2, LL_TIM_COUNTERMODE_UP);
|
LL_TIM_SetCounterMode(TIM2, LL_TIM_COUNTERMODE_UP);
|
||||||
@@ -256,7 +253,6 @@ void digital_sequence_alloc_sequence(DigitalSequence* sequence, uint32_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DigitalSequence* digital_sequence_alloc(uint32_t size, const GpioPin* gpio) {
|
DigitalSequence* digital_sequence_alloc(uint32_t size, const GpioPin* gpio) {
|
||||||
|
|
||||||
DigitalSequence* sequence = malloc(sizeof(DigitalSequence));
|
DigitalSequence* sequence = malloc(sizeof(DigitalSequence));
|
||||||
|
|
||||||
sequence->gpio = gpio;
|
sequence->gpio = gpio;
|
||||||
@@ -276,7 +272,10 @@ void digital_sequence_free(DigitalSequence* sequence) {
|
|||||||
free(sequence);
|
free(sequence);
|
||||||
}
|
}
|
||||||
|
|
||||||
void digital_sequence_set_signal(DigitalSequence* sequence, uint8_t signal_index, DigitalSignal* signal) {
|
void digital_sequence_set_signal(
|
||||||
|
DigitalSequence* sequence,
|
||||||
|
uint8_t signal_index,
|
||||||
|
DigitalSignal* signal) {
|
||||||
furi_assert(sequence);
|
furi_assert(sequence);
|
||||||
furi_assert(signal);
|
furi_assert(signal);
|
||||||
furi_assert(signal_index < sequence->signals_size);
|
furi_assert(signal_index < sequence->signals_size);
|
||||||
@@ -301,7 +300,6 @@ void digital_sequence_add(DigitalSequence* sequence, uint8_t signal_index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void digital_signal_update_dma(DigitalSignal* signal) {
|
void digital_signal_update_dma(DigitalSignal* signal) {
|
||||||
|
|
||||||
volatile uint32_t dma1_data[] = {
|
volatile uint32_t dma1_data[] = {
|
||||||
/* R6 */ (uint32_t) & (DMA1_Channel1->CCR),
|
/* R6 */ (uint32_t) & (DMA1_Channel1->CCR),
|
||||||
/* R7 */ DMA1_Channel1->CCR & ~DMA_CCR_EN,
|
/* R7 */ DMA1_Channel1->CCR & ~DMA_CCR_EN,
|
||||||
@@ -318,7 +316,6 @@ void digital_signal_update_dma(DigitalSignal* signal) {
|
|||||||
/* R4 */ (uint32_t)signal->reload_reg_buff,
|
/* R4 */ (uint32_t)signal->reload_reg_buff,
|
||||||
/* R5 */ DMA1_Channel2->CCR | DMA_CCR_EN};
|
/* R5 */ DMA1_Channel2->CCR | DMA_CCR_EN};
|
||||||
|
|
||||||
|
|
||||||
/* hurry when setting up next transfer */
|
/* hurry when setting up next transfer */
|
||||||
asm volatile("\t"
|
asm volatile("\t"
|
||||||
"MOV r6, %[data1]\n\t"
|
"MOV r6, %[data1]\n\t"
|
||||||
@@ -343,11 +340,9 @@ void digital_signal_update_dma(DigitalSignal* signal) {
|
|||||||
|
|
||||||
: /* no outputs*/
|
: /* no outputs*/
|
||||||
: /* inputs */
|
: /* inputs */
|
||||||
[data1] "r" (dma1_data),
|
[data1] "r"(dma1_data), [data2] "r"(dma2_data)
|
||||||
[data2] "r" (dma2_data)
|
|
||||||
: "r6", "r7");
|
: "r6", "r7");
|
||||||
|
|
||||||
|
|
||||||
LL_DMA_ClearFlag_TC1(DMA1);
|
LL_DMA_ClearFlag_TC1(DMA1);
|
||||||
LL_DMA_ClearFlag_TC2(DMA1);
|
LL_DMA_ClearFlag_TC2(DMA1);
|
||||||
}
|
}
|
||||||
@@ -372,7 +367,6 @@ static bool digital_sequence_send_signal(DigitalSignal* signal) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DigitalSignal* digital_sequence_bake(DigitalSequence* sequence) {
|
DigitalSignal* digital_sequence_bake(DigitalSequence* sequence) {
|
||||||
|
|
||||||
uint32_t edges = 0;
|
uint32_t edges = 0;
|
||||||
|
|
||||||
for(uint32_t pos = 0; pos < sequence->sequence_used; pos++) {
|
for(uint32_t pos = 0; pos < sequence->sequence_used; pos++) {
|
||||||
@@ -415,7 +409,11 @@ bool digital_sequence_send(DigitalSequence* sequence) {
|
|||||||
DigitalSignal* sig = sequence->signals[signal_index];
|
DigitalSignal* sig = sequence->signals[signal_index];
|
||||||
|
|
||||||
if(!sig) {
|
if(!sig) {
|
||||||
FURI_LOG_D(TAG, "digital_sequence_send: Signal at index %u, used at pos %lu is NULL, aborting", signal_index, pos);
|
FURI_LOG_D(
|
||||||
|
TAG,
|
||||||
|
"digital_sequence_send: Signal at index %u, used at pos %lu is NULL, aborting",
|
||||||
|
signal_index,
|
||||||
|
pos);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ extern "C" {
|
|||||||
#define DIGITAL_SIGNAL_NS(x) (x * 100UL)
|
#define DIGITAL_SIGNAL_NS(x) (x * 100UL)
|
||||||
#define DIGITAL_SIGNAL_PS(x) (x / 10UL)
|
#define DIGITAL_SIGNAL_PS(x) (x / 10UL)
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool start_level;
|
bool start_level;
|
||||||
uint32_t edge_cnt;
|
uint32_t edge_cnt;
|
||||||
@@ -44,7 +43,6 @@ typedef struct {
|
|||||||
const GpioPin* gpio;
|
const GpioPin* gpio;
|
||||||
} DigitalSequence;
|
} DigitalSequence;
|
||||||
|
|
||||||
|
|
||||||
DigitalSignal* digital_signal_alloc(uint32_t max_edges_cnt);
|
DigitalSignal* digital_signal_alloc(uint32_t max_edges_cnt);
|
||||||
|
|
||||||
void digital_signal_free(DigitalSignal* signal);
|
void digital_signal_free(DigitalSignal* signal);
|
||||||
@@ -65,16 +63,16 @@ uint32_t digital_signal_get_edge(DigitalSignal* signal, uint32_t edge_num);
|
|||||||
|
|
||||||
void digital_signal_send(DigitalSignal* signal, const GpioPin* gpio);
|
void digital_signal_send(DigitalSignal* signal, const GpioPin* gpio);
|
||||||
|
|
||||||
|
|
||||||
DigitalSequence* digital_sequence_alloc(uint32_t size, const GpioPin* gpio);
|
DigitalSequence* digital_sequence_alloc(uint32_t size, const GpioPin* gpio);
|
||||||
void digital_sequence_free(DigitalSequence* sequence);
|
void digital_sequence_free(DigitalSequence* sequence);
|
||||||
void digital_sequence_set_signal(DigitalSequence* sequence, uint8_t signal_index, DigitalSignal* signal);
|
void digital_sequence_set_signal(
|
||||||
|
DigitalSequence* sequence,
|
||||||
|
uint8_t signal_index,
|
||||||
|
DigitalSignal* signal);
|
||||||
void digital_sequence_add(DigitalSequence* sequence, uint8_t signal_index);
|
void digital_sequence_add(DigitalSequence* sequence, uint8_t signal_index);
|
||||||
bool digital_sequence_send(DigitalSequence* sequence);
|
bool digital_sequence_send(DigitalSequence* sequence);
|
||||||
void digital_sequence_clear(DigitalSequence* sequence);
|
void digital_sequence_clear(DigitalSequence* sequence);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -656,7 +656,8 @@ static bool nfc_device_save_slix_data(FlipperFormat* file, NfcDevice* dev) {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
if(!flipper_format_write_comment_cstr(file, "SLIX specific data")) break;
|
if(!flipper_format_write_comment_cstr(file, "SLIX specific data")) break;
|
||||||
if(!flipper_format_write_hex(file, "Password EAS", data->key_eas, sizeof(data->key_eas))) break;
|
if(!flipper_format_write_hex(file, "Password EAS", data->key_eas, sizeof(data->key_eas)))
|
||||||
|
break;
|
||||||
saved = true;
|
saved = true;
|
||||||
} while(false);
|
} while(false);
|
||||||
|
|
||||||
@@ -669,8 +670,7 @@ bool nfc_device_load_slix_data(FlipperFormat* file, NfcDevice* dev) {
|
|||||||
memset(data, 0, sizeof(NfcVData));
|
memset(data, 0, sizeof(NfcVData));
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if(!flipper_format_read_hex(
|
if(!flipper_format_read_hex(file, "Password EAS", data->key_eas, sizeof(data->key_eas)))
|
||||||
file, "Password EAS", data->key_eas, sizeof(data->key_eas)))
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
parsed = true;
|
parsed = true;
|
||||||
@@ -685,11 +685,19 @@ static bool nfc_device_save_slix_s_data(FlipperFormat* file, NfcDevice* dev) {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
if(!flipper_format_write_comment_cstr(file, "SLIX-S specific data")) break;
|
if(!flipper_format_write_comment_cstr(file, "SLIX-S specific data")) break;
|
||||||
if(!flipper_format_write_hex(file, "Password Read", data->key_read, sizeof(data->key_read))) break;
|
if(!flipper_format_write_hex(file, "Password Read", data->key_read, sizeof(data->key_read)))
|
||||||
if(!flipper_format_write_hex(file, "Password Write", data->key_write, sizeof(data->key_write))) break;
|
break;
|
||||||
if(!flipper_format_write_hex(file, "Password Privacy", data->key_privacy, sizeof(data->key_privacy))) break;
|
if(!flipper_format_write_hex(
|
||||||
if(!flipper_format_write_hex(file, "Password Destroy", data->key_destroy, sizeof(data->key_destroy))) break;
|
file, "Password Write", data->key_write, sizeof(data->key_write)))
|
||||||
if(!flipper_format_write_hex(file, "Password EAS", data->key_eas, sizeof(data->key_eas))) break;
|
break;
|
||||||
|
if(!flipper_format_write_hex(
|
||||||
|
file, "Password Privacy", data->key_privacy, sizeof(data->key_privacy)))
|
||||||
|
break;
|
||||||
|
if(!flipper_format_write_hex(
|
||||||
|
file, "Password Destroy", data->key_destroy, sizeof(data->key_destroy)))
|
||||||
|
break;
|
||||||
|
if(!flipper_format_write_hex(file, "Password EAS", data->key_eas, sizeof(data->key_eas)))
|
||||||
|
break;
|
||||||
if(!flipper_format_write_bool(file, "Privacy Mode", &data->privacy, 1)) break;
|
if(!flipper_format_write_bool(file, "Privacy Mode", &data->privacy, 1)) break;
|
||||||
saved = true;
|
saved = true;
|
||||||
} while(false);
|
} while(false);
|
||||||
@@ -703,8 +711,7 @@ bool nfc_device_load_slix_s_data(FlipperFormat* file, NfcDevice* dev) {
|
|||||||
memset(data, 0, sizeof(NfcVData));
|
memset(data, 0, sizeof(NfcVData));
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if(!flipper_format_read_hex(
|
if(!flipper_format_read_hex(file, "Password Read", data->key_read, sizeof(data->key_read)))
|
||||||
file, "Password Read", data->key_read, sizeof(data->key_read)))
|
|
||||||
break;
|
break;
|
||||||
if(!flipper_format_read_hex(
|
if(!flipper_format_read_hex(
|
||||||
file, "Password Write", data->key_write, sizeof(data->key_write)))
|
file, "Password Write", data->key_write, sizeof(data->key_write)))
|
||||||
@@ -715,8 +722,7 @@ bool nfc_device_load_slix_s_data(FlipperFormat* file, NfcDevice* dev) {
|
|||||||
if(!flipper_format_read_hex(
|
if(!flipper_format_read_hex(
|
||||||
file, "Password Destroy", data->key_destroy, sizeof(data->key_destroy)))
|
file, "Password Destroy", data->key_destroy, sizeof(data->key_destroy)))
|
||||||
break;
|
break;
|
||||||
if(!flipper_format_read_hex(
|
if(!flipper_format_read_hex(file, "Password EAS", data->key_eas, sizeof(data->key_eas)))
|
||||||
file, "Password EAS", data->key_eas, sizeof(data->key_eas)))
|
|
||||||
break;
|
break;
|
||||||
if(!flipper_format_read_bool(file, "Privacy Mode", &data->privacy, 1)) break;
|
if(!flipper_format_read_bool(file, "Privacy Mode", &data->privacy, 1)) break;
|
||||||
|
|
||||||
@@ -732,9 +738,14 @@ static bool nfc_device_save_slix_l_data(FlipperFormat* file, NfcDevice* dev) {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
if(!flipper_format_write_comment_cstr(file, "SLIX-L specific data")) break;
|
if(!flipper_format_write_comment_cstr(file, "SLIX-L specific data")) break;
|
||||||
if(!flipper_format_write_hex(file, "Password Privacy", data->key_privacy, sizeof(data->key_privacy))) break;
|
if(!flipper_format_write_hex(
|
||||||
if(!flipper_format_write_hex(file, "Password Destroy", data->key_destroy, sizeof(data->key_destroy))) break;
|
file, "Password Privacy", data->key_privacy, sizeof(data->key_privacy)))
|
||||||
if(!flipper_format_write_hex(file, "Password EAS", data->key_eas, sizeof(data->key_eas))) break;
|
break;
|
||||||
|
if(!flipper_format_write_hex(
|
||||||
|
file, "Password Destroy", data->key_destroy, sizeof(data->key_destroy)))
|
||||||
|
break;
|
||||||
|
if(!flipper_format_write_hex(file, "Password EAS", data->key_eas, sizeof(data->key_eas)))
|
||||||
|
break;
|
||||||
if(!flipper_format_write_bool(file, "Privacy Mode", &data->privacy, 1)) break;
|
if(!flipper_format_write_bool(file, "Privacy Mode", &data->privacy, 1)) break;
|
||||||
saved = true;
|
saved = true;
|
||||||
} while(false);
|
} while(false);
|
||||||
@@ -754,8 +765,7 @@ bool nfc_device_load_slix_l_data(FlipperFormat* file, NfcDevice* dev) {
|
|||||||
if(!flipper_format_read_hex(
|
if(!flipper_format_read_hex(
|
||||||
file, "Password Destroy", data->key_destroy, sizeof(data->key_destroy)))
|
file, "Password Destroy", data->key_destroy, sizeof(data->key_destroy)))
|
||||||
break;
|
break;
|
||||||
if(!flipper_format_read_hex(
|
if(!flipper_format_read_hex(file, "Password EAS", data->key_eas, sizeof(data->key_eas)))
|
||||||
file, "Password EAS", data->key_eas, sizeof(data->key_eas)))
|
|
||||||
break;
|
break;
|
||||||
if(!flipper_format_read_bool(file, "Privacy Mode", &data->privacy, 1)) break;
|
if(!flipper_format_read_bool(file, "Privacy Mode", &data->privacy, 1)) break;
|
||||||
|
|
||||||
@@ -771,11 +781,19 @@ static bool nfc_device_save_slix2_data(FlipperFormat* file, NfcDevice* dev) {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
if(!flipper_format_write_comment_cstr(file, "SLIX2 specific data")) break;
|
if(!flipper_format_write_comment_cstr(file, "SLIX2 specific data")) break;
|
||||||
if(!flipper_format_write_hex(file, "Password Read", data->key_read, sizeof(data->key_read))) break;
|
if(!flipper_format_write_hex(file, "Password Read", data->key_read, sizeof(data->key_read)))
|
||||||
if(!flipper_format_write_hex(file, "Password Write", data->key_write, sizeof(data->key_write))) break;
|
break;
|
||||||
if(!flipper_format_write_hex(file, "Password Privacy", data->key_privacy, sizeof(data->key_privacy))) break;
|
if(!flipper_format_write_hex(
|
||||||
if(!flipper_format_write_hex(file, "Password Destroy", data->key_destroy, sizeof(data->key_destroy))) break;
|
file, "Password Write", data->key_write, sizeof(data->key_write)))
|
||||||
if(!flipper_format_write_hex(file, "Password EAS", data->key_eas, sizeof(data->key_eas))) break;
|
break;
|
||||||
|
if(!flipper_format_write_hex(
|
||||||
|
file, "Password Privacy", data->key_privacy, sizeof(data->key_privacy)))
|
||||||
|
break;
|
||||||
|
if(!flipper_format_write_hex(
|
||||||
|
file, "Password Destroy", data->key_destroy, sizeof(data->key_destroy)))
|
||||||
|
break;
|
||||||
|
if(!flipper_format_write_hex(file, "Password EAS", data->key_eas, sizeof(data->key_eas)))
|
||||||
|
break;
|
||||||
if(!flipper_format_write_bool(file, "Privacy Mode", &data->privacy, 1)) break;
|
if(!flipper_format_write_bool(file, "Privacy Mode", &data->privacy, 1)) break;
|
||||||
saved = true;
|
saved = true;
|
||||||
} while(false);
|
} while(false);
|
||||||
@@ -789,8 +807,7 @@ bool nfc_device_load_slix2_data(FlipperFormat* file, NfcDevice* dev) {
|
|||||||
memset(data, 0, sizeof(NfcVData));
|
memset(data, 0, sizeof(NfcVData));
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if(!flipper_format_read_hex(
|
if(!flipper_format_read_hex(file, "Password Read", data->key_read, sizeof(data->key_read)))
|
||||||
file, "Password Read", data->key_read, sizeof(data->key_read)))
|
|
||||||
break;
|
break;
|
||||||
if(!flipper_format_read_hex(
|
if(!flipper_format_read_hex(
|
||||||
file, "Password Write", data->key_write, sizeof(data->key_write)))
|
file, "Password Write", data->key_write, sizeof(data->key_write)))
|
||||||
@@ -801,8 +818,7 @@ bool nfc_device_load_slix2_data(FlipperFormat* file, NfcDevice* dev) {
|
|||||||
if(!flipper_format_read_hex(
|
if(!flipper_format_read_hex(
|
||||||
file, "Password Destroy", data->key_destroy, sizeof(data->key_destroy)))
|
file, "Password Destroy", data->key_destroy, sizeof(data->key_destroy)))
|
||||||
break;
|
break;
|
||||||
if(!flipper_format_read_hex(
|
if(!flipper_format_read_hex(file, "Password EAS", data->key_eas, sizeof(data->key_eas)))
|
||||||
file, "Password EAS", data->key_eas, sizeof(data->key_eas)))
|
|
||||||
break;
|
break;
|
||||||
if(!flipper_format_read_bool(file, "Privacy Mode", &data->privacy, 1)) break;
|
if(!flipper_format_read_bool(file, "Privacy Mode", &data->privacy, 1)) break;
|
||||||
|
|
||||||
@@ -826,12 +842,19 @@ static bool nfc_device_save_nfcv_data(FlipperFormat* file, NfcDevice* dev) {
|
|||||||
if(!flipper_format_write_hex(file, "AFI", &(data->afi), 1)) break;
|
if(!flipper_format_write_hex(file, "AFI", &(data->afi), 1)) break;
|
||||||
if(!flipper_format_write_hex(file, "IC Reference", &(data->ic_ref), 1)) break;
|
if(!flipper_format_write_hex(file, "IC Reference", &(data->ic_ref), 1)) break;
|
||||||
temp_uint32 = data->block_num;
|
temp_uint32 = data->block_num;
|
||||||
if(!flipper_format_write_comment_cstr(file, "Number of memory blocks, usually 0 to 256")) break;
|
if(!flipper_format_write_comment_cstr(file, "Number of memory blocks, usually 0 to 256"))
|
||||||
|
break;
|
||||||
if(!flipper_format_write_uint32(file, "Block Count", &temp_uint32, 1)) break;
|
if(!flipper_format_write_uint32(file, "Block Count", &temp_uint32, 1)) break;
|
||||||
if(!flipper_format_write_comment_cstr(file, "Size of a single memory block, usually 4")) break;
|
if(!flipper_format_write_comment_cstr(file, "Size of a single memory block, usually 4"))
|
||||||
|
break;
|
||||||
if(!flipper_format_write_hex(file, "Block Size", &(data->block_size), 1)) break;
|
if(!flipper_format_write_hex(file, "Block Size", &(data->block_size), 1)) break;
|
||||||
if(!flipper_format_write_hex(file, "Data Content", data->data, data->block_num * data->block_size)) break;
|
if(!flipper_format_write_hex(
|
||||||
if(!flipper_format_write_comment_cstr(file, "Subtype of this card (0 = ISO15693, 1 = SLIX, 2 = SLIX-S, 3 = SLIX-L, 4 = SLIX2)")) break;
|
file, "Data Content", data->data, data->block_num * data->block_size))
|
||||||
|
break;
|
||||||
|
if(!flipper_format_write_comment_cstr(
|
||||||
|
file,
|
||||||
|
"Subtype of this card (0 = ISO15693, 1 = SLIX, 2 = SLIX-S, 3 = SLIX-L, 4 = SLIX2)"))
|
||||||
|
break;
|
||||||
temp_uint8 = (uint8_t)data->type;
|
temp_uint8 = (uint8_t)data->type;
|
||||||
if(!flipper_format_write_hex(file, "Subtype", &temp_uint8, 1)) break;
|
if(!flipper_format_write_hex(file, "Subtype", &temp_uint8, 1)) break;
|
||||||
|
|
||||||
@@ -1325,14 +1348,12 @@ bool nfc_device_save(NfcDevice* dev, const char* dev_name) {
|
|||||||
nfc_device_prepare_format_string(dev, temp_str);
|
nfc_device_prepare_format_string(dev, temp_str);
|
||||||
if(!flipper_format_write_string(file, "Device type", temp_str)) break;
|
if(!flipper_format_write_string(file, "Device type", temp_str)) break;
|
||||||
// Write UID
|
// Write UID
|
||||||
if(!flipper_format_write_comment_cstr(file, "UID is common for all formats"))
|
if(!flipper_format_write_comment_cstr(file, "UID is common for all formats")) break;
|
||||||
break;
|
|
||||||
if(!flipper_format_write_hex(file, "UID", data->uid, data->uid_len)) break;
|
if(!flipper_format_write_hex(file, "UID", data->uid, data->uid_len)) break;
|
||||||
|
|
||||||
if(dev->format != NfcDeviceSaveFormatNfcV) {
|
if(dev->format != NfcDeviceSaveFormatNfcV) {
|
||||||
// Write ATQA, SAK
|
// Write ATQA, SAK
|
||||||
if(!flipper_format_write_comment_cstr(file, "ISO14443 specific fields"))
|
if(!flipper_format_write_comment_cstr(file, "ISO14443 specific fields")) break;
|
||||||
break;
|
|
||||||
if(!flipper_format_write_hex(file, "ATQA", data->atqa, 2)) break;
|
if(!flipper_format_write_hex(file, "ATQA", data->atqa, 2)) break;
|
||||||
if(!flipper_format_write_hex(file, "SAK", &data->sak, 1)) break;
|
if(!flipper_format_write_hex(file, "SAK", &data->sak, 1)) break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -169,14 +169,14 @@ void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker) {
|
|||||||
|
|
||||||
furi_hal_nfc_sleep();
|
furi_hal_nfc_sleep();
|
||||||
|
|
||||||
|
|
||||||
while((nfc_worker->state == NfcWorkerStateNfcVUnlock) ||
|
while((nfc_worker->state == NfcWorkerStateNfcVUnlock) ||
|
||||||
(nfc_worker->state == NfcWorkerStateNfcVUnlockAndSave)) {
|
(nfc_worker->state == NfcWorkerStateNfcVUnlockAndSave)) {
|
||||||
|
|
||||||
furi_hal_nfc_exit_sleep();
|
furi_hal_nfc_exit_sleep();
|
||||||
furi_hal_nfc_ll_txrx_on();
|
furi_hal_nfc_ll_txrx_on();
|
||||||
furi_hal_nfc_ll_poll();
|
furi_hal_nfc_ll_poll();
|
||||||
if(furi_hal_nfc_ll_set_mode(FuriHalNfcModePollNfcv, FuriHalNfcBitrate26p48, FuriHalNfcBitrate26p48) != FuriHalNfcReturnOk) {
|
if(furi_hal_nfc_ll_set_mode(
|
||||||
|
FuriHalNfcModePollNfcv, FuriHalNfcBitrate26p48, FuriHalNfcBitrate26p48) !=
|
||||||
|
FuriHalNfcReturnOk) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,7 +216,8 @@ void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker) {
|
|||||||
furi_delay_ms(100);
|
furi_delay_ms(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
furi_hal_console_printf(" => chip is already visible, wait for chip to disappear.\r\n");
|
furi_hal_console_printf(
|
||||||
|
" => chip is already visible, wait for chip to disappear.\r\n");
|
||||||
nfc_worker->callback(NfcWorkerEventAborted, nfc_worker->context);
|
nfc_worker->callback(NfcWorkerEventAborted, nfc_worker->context);
|
||||||
while(slix_l_get_random(NULL) == ERR_NONE) {
|
while(slix_l_get_random(NULL) == ERR_NONE) {
|
||||||
furi_delay_ms(100);
|
furi_delay_ms(100);
|
||||||
@@ -232,7 +233,6 @@ void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker) {
|
|||||||
furi_hal_console_printf(" chip is invisible, unlocking\r\n");
|
furi_hal_console_printf(" chip is invisible, unlocking\r\n");
|
||||||
|
|
||||||
if(nfcv_data->auth_method == NfcVAuthMethodManual) {
|
if(nfcv_data->auth_method == NfcVAuthMethodManual) {
|
||||||
|
|
||||||
key |= key_data[0] << 24;
|
key |= key_data[0] << 24;
|
||||||
key |= key_data[1] << 16;
|
key |= key_data[1] << 16;
|
||||||
key |= key_data[2] << 8;
|
key |= key_data[2] << 8;
|
||||||
@@ -271,7 +271,8 @@ void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker) {
|
|||||||
if(ret != ERR_NONE) {
|
if(ret != ERR_NONE) {
|
||||||
/* unlock failed */
|
/* unlock failed */
|
||||||
furi_hal_console_printf(" => failed, wait for chip to disappear.\r\n");
|
furi_hal_console_printf(" => failed, wait for chip to disappear.\r\n");
|
||||||
snprintf(nfcv_data->error, sizeof(nfcv_data->error), "Passwords not\naccepted");
|
snprintf(
|
||||||
|
nfcv_data->error, sizeof(nfcv_data->error), "Passwords not\naccepted");
|
||||||
nfc_worker->callback(NfcWorkerEventWrongCardDetected, nfc_worker->context);
|
nfc_worker->callback(NfcWorkerEventWrongCardDetected, nfc_worker->context);
|
||||||
|
|
||||||
/* reset chip */
|
/* reset chip */
|
||||||
@@ -299,8 +300,6 @@ void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static bool nfc_worker_read_mf_ultralight(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) {
|
static bool nfc_worker_read_mf_ultralight(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) {
|
||||||
bool read_success = false;
|
bool read_success = false;
|
||||||
MfUltralightReader reader = {};
|
MfUltralightReader reader = {};
|
||||||
|
|||||||
@@ -96,4 +96,3 @@ void nfc_worker_start(
|
|||||||
void nfc_worker_stop(NfcWorker* nfc_worker);
|
void nfc_worker_stop(NfcWorker* nfc_worker);
|
||||||
void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker);
|
void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker);
|
||||||
void nfc_worker_emulate_nfcv(NfcWorker* nfc_worker);
|
void nfc_worker_emulate_nfcv(NfcWorker* nfc_worker);
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
|
|
||||||
#define TAG "NfcA-trans-rx"
|
#define TAG "NfcA-trans-rx"
|
||||||
|
|
||||||
|
|
||||||
void nfca_trans_rx_init(NfcaTransRxState* state) {
|
void nfca_trans_rx_init(NfcaTransRxState* state) {
|
||||||
FURI_LOG_D(TAG, "Starting NfcA transparent rx");
|
FURI_LOG_D(TAG, "Starting NfcA transparent rx");
|
||||||
|
|
||||||
@@ -52,7 +51,6 @@ void nfca_trans_rx_continue(NfcaTransRxState *state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void nfca_bit_received(NfcaTransRxState* state, uint8_t bit) {
|
static void nfca_bit_received(NfcaTransRxState* state, uint8_t bit) {
|
||||||
|
|
||||||
/* According to ISO14443-3 short frames have 7 bits and standard 9 bits per byte,
|
/* According to ISO14443-3 short frames have 7 bits and standard 9 bits per byte,
|
||||||
where the 9th bit is odd parity. Data is transmitted LSB first. */
|
where the 9th bit is odd parity. Data is transmitted LSB first. */
|
||||||
uint32_t byte_num = (state->bits_received / 9);
|
uint32_t byte_num = (state->bits_received / 9);
|
||||||
@@ -75,7 +73,6 @@ static void nfca_bit_received(NfcaTransRxState *state, uint8_t bit) {
|
|||||||
state->bits_received++;
|
state->bits_received++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool nfca_trans_rx_loop(NfcaTransRxState* state, uint32_t timeout_ms) {
|
bool nfca_trans_rx_loop(NfcaTransRxState* state, uint32_t timeout_ms) {
|
||||||
furi_assert(state);
|
furi_assert(state);
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,6 @@
|
|||||||
#define NFCA_FRAME_LENGTH 32
|
#define NFCA_FRAME_LENGTH 32
|
||||||
#define NFCA_DEBUG_LENGTH 128
|
#define NFCA_DEBUG_LENGTH 128
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool have_sof;
|
bool have_sof;
|
||||||
bool valid_frame;
|
bool valid_frame;
|
||||||
|
|||||||
@@ -22,8 +22,7 @@ ReturnCode nfcv_inventory(uint8_t* uid) {
|
|||||||
|
|
||||||
for(int tries = 0; tries < 5; tries++) {
|
for(int tries = 0; tries < 5; tries++) {
|
||||||
/* TODO: needs proper abstraction via fury_hal(_ll)_* */
|
/* TODO: needs proper abstraction via fury_hal(_ll)_* */
|
||||||
ret = rfalNfcvPollerInventory(
|
ret = rfalNfcvPollerInventory(RFAL_NFCV_NUM_SLOTS_1, 0, NULL, &res, &received);
|
||||||
RFAL_NFCV_NUM_SLOTS_1, 0, NULL, &res, &received);
|
|
||||||
|
|
||||||
if(ret == ERR_NONE) {
|
if(ret == ERR_NONE) {
|
||||||
break;
|
break;
|
||||||
@@ -39,10 +38,7 @@ ReturnCode nfcv_inventory(uint8_t* uid) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode nfcv_read_blocks(
|
ReturnCode nfcv_read_blocks(NfcVReader* reader, NfcVData* data) {
|
||||||
NfcVReader* reader,
|
|
||||||
NfcVData* data) {
|
|
||||||
|
|
||||||
UNUSED(reader);
|
UNUSED(reader);
|
||||||
|
|
||||||
uint16_t received = 0;
|
uint16_t received = 0;
|
||||||
@@ -53,8 +49,7 @@ ReturnCode nfcv_read_blocks(
|
|||||||
ReturnCode ret = ERR_NONE;
|
ReturnCode ret = ERR_NONE;
|
||||||
for(int tries = 0; tries < 5; tries++) {
|
for(int tries = 0; tries < 5; tries++) {
|
||||||
ret = rfalNfcvPollerReadSingleBlock(
|
ret = rfalNfcvPollerReadSingleBlock(
|
||||||
RFAL_NFCV_REQ_FLAG_DEFAULT, NULL, block,
|
RFAL_NFCV_REQ_FLAG_DEFAULT, NULL, block, rxBuf, sizeof(rxBuf), &received);
|
||||||
rxBuf, sizeof(rxBuf), &received);
|
|
||||||
|
|
||||||
if(ret == ERR_NONE) {
|
if(ret == ERR_NONE) {
|
||||||
break;
|
break;
|
||||||
@@ -65,9 +60,13 @@ ReturnCode nfcv_read_blocks(
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
memcpy(&(data->data[block * data->block_size]), &rxBuf[1], data->block_size);
|
memcpy(&(data->data[block * data->block_size]), &rxBuf[1], data->block_size);
|
||||||
FURI_LOG_D(TAG, " %02X %02X %02X %02X",
|
FURI_LOG_D(
|
||||||
data->data[block * data->block_size + 0], data->data[block * data->block_size + 1],
|
TAG,
|
||||||
data->data[block * data->block_size + 2], data->data[block * data->block_size + 3]);
|
" %02X %02X %02X %02X",
|
||||||
|
data->data[block * data->block_size + 0],
|
||||||
|
data->data[block * data->block_size + 1],
|
||||||
|
data->data[block * data->block_size + 2],
|
||||||
|
data->data[block * data->block_size + 3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERR_NONE;
|
return ERR_NONE;
|
||||||
@@ -102,10 +101,25 @@ ReturnCode nfcv_read_sysinfo(FuriHalNfcDevData* nfc_data, NfcVData* data) {
|
|||||||
data->block_num = rxBuf[12] + 1;
|
data->block_num = rxBuf[12] + 1;
|
||||||
data->block_size = rxBuf[13] + 1;
|
data->block_size = rxBuf[13] + 1;
|
||||||
data->ic_ref = rxBuf[14];
|
data->ic_ref = rxBuf[14];
|
||||||
FURI_LOG_D(TAG, " UID: %02X %02X %02X %02X %02X %02X %02X %02X",
|
FURI_LOG_D(
|
||||||
nfc_data->uid[0], nfc_data->uid[1], nfc_data->uid[2], nfc_data->uid[3],
|
TAG,
|
||||||
nfc_data->uid[4], nfc_data->uid[5], nfc_data->uid[6], nfc_data->uid[7]);
|
" UID: %02X %02X %02X %02X %02X %02X %02X %02X",
|
||||||
FURI_LOG_D(TAG, " DSFID %d, AFI %d, Blocks %d, Size %d, IC Ref %d", data->dsfid, data->afi, data->block_num, data->block_size, data->ic_ref);
|
nfc_data->uid[0],
|
||||||
|
nfc_data->uid[1],
|
||||||
|
nfc_data->uid[2],
|
||||||
|
nfc_data->uid[3],
|
||||||
|
nfc_data->uid[4],
|
||||||
|
nfc_data->uid[5],
|
||||||
|
nfc_data->uid[6],
|
||||||
|
nfc_data->uid[7]);
|
||||||
|
FURI_LOG_D(
|
||||||
|
TAG,
|
||||||
|
" DSFID %d, AFI %d, Blocks %d, Size %d, IC Ref %d",
|
||||||
|
data->dsfid,
|
||||||
|
data->afi,
|
||||||
|
data->block_num,
|
||||||
|
data->block_size,
|
||||||
|
data->ic_ref);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
FURI_LOG_D(TAG, "Failed: %d", ret);
|
FURI_LOG_D(TAG, "Failed: %d", ret);
|
||||||
@@ -113,10 +127,7 @@ ReturnCode nfcv_read_sysinfo(FuriHalNfcDevData* nfc_data, NfcVData* data) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nfcv_read_card(
|
bool nfcv_read_card(NfcVReader* reader, FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data) {
|
||||||
NfcVReader* reader,
|
|
||||||
FuriHalNfcDevData* nfc_data,
|
|
||||||
NfcVData* nfcv_data) {
|
|
||||||
furi_assert(reader);
|
furi_assert(reader);
|
||||||
furi_assert(nfc_data);
|
furi_assert(nfc_data);
|
||||||
furi_assert(nfcv_data);
|
furi_assert(nfcv_data);
|
||||||
@@ -148,8 +159,6 @@ bool nfcv_read_card(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void nfcv_crc(uint8_t* data, uint32_t length) {
|
void nfcv_crc(uint8_t* data, uint32_t length) {
|
||||||
uint32_t reg = 0xFFFF;
|
uint32_t reg = 0xFFFF;
|
||||||
|
|
||||||
@@ -198,15 +207,18 @@ void nfcv_emu_alloc(NfcVData* data) {
|
|||||||
/* unmodulated 256/fc signal as building block */
|
/* unmodulated 256/fc signal as building block */
|
||||||
data->emulation.nfcv_resp_unmod_256 = digital_signal_alloc(4);
|
data->emulation.nfcv_resp_unmod_256 = digital_signal_alloc(4);
|
||||||
data->emulation.nfcv_resp_unmod_256->start_level = false;
|
data->emulation.nfcv_resp_unmod_256->start_level = false;
|
||||||
data->emulation.nfcv_resp_unmod_256->edge_timings[0] = (uint32_t)(NFCV_RESP_SUBC1_UNMOD_256 * DIGITAL_SIGNAL_UNIT_S);
|
data->emulation.nfcv_resp_unmod_256->edge_timings[0] =
|
||||||
|
(uint32_t)(NFCV_RESP_SUBC1_UNMOD_256 * DIGITAL_SIGNAL_UNIT_S);
|
||||||
data->emulation.nfcv_resp_unmod_256->edge_cnt = 1;
|
data->emulation.nfcv_resp_unmod_256->edge_cnt = 1;
|
||||||
}
|
}
|
||||||
if(!data->emulation.nfcv_resp_pulse_32) {
|
if(!data->emulation.nfcv_resp_pulse_32) {
|
||||||
/* modulated fc/32 pulse as building block */
|
/* modulated fc/32 pulse as building block */
|
||||||
data->emulation.nfcv_resp_pulse_32 = digital_signal_alloc(4);
|
data->emulation.nfcv_resp_pulse_32 = digital_signal_alloc(4);
|
||||||
data->emulation.nfcv_resp_pulse_32->start_level = true;
|
data->emulation.nfcv_resp_pulse_32->start_level = true;
|
||||||
data->emulation.nfcv_resp_pulse_32->edge_timings[0] = (uint32_t)(NFCV_RESP_SUBC1_PULSE_32 * DIGITAL_SIGNAL_UNIT_S);
|
data->emulation.nfcv_resp_pulse_32->edge_timings[0] =
|
||||||
data->emulation.nfcv_resp_pulse_32->edge_timings[1] = (uint32_t)(NFCV_RESP_SUBC1_PULSE_32 * DIGITAL_SIGNAL_UNIT_S);
|
(uint32_t)(NFCV_RESP_SUBC1_PULSE_32 * DIGITAL_SIGNAL_UNIT_S);
|
||||||
|
data->emulation.nfcv_resp_pulse_32->edge_timings[1] =
|
||||||
|
(uint32_t)(NFCV_RESP_SUBC1_PULSE_32 * DIGITAL_SIGNAL_UNIT_S);
|
||||||
data->emulation.nfcv_resp_pulse_32->edge_cnt = 2;
|
data->emulation.nfcv_resp_pulse_32->edge_cnt = 2;
|
||||||
}
|
}
|
||||||
if(!data->emulation.nfcv_resp_one) {
|
if(!data->emulation.nfcv_resp_one) {
|
||||||
@@ -214,14 +226,16 @@ void nfcv_emu_alloc(NfcVData* data) {
|
|||||||
data->emulation.nfcv_resp_one = digital_signal_alloc(24);
|
data->emulation.nfcv_resp_one = digital_signal_alloc(24);
|
||||||
digital_signal_append(data->emulation.nfcv_resp_one, data->emulation.nfcv_resp_unmod_256);
|
digital_signal_append(data->emulation.nfcv_resp_one, data->emulation.nfcv_resp_unmod_256);
|
||||||
for(size_t i = 0; i < 8; i++) {
|
for(size_t i = 0; i < 8; i++) {
|
||||||
digital_signal_append(data->emulation.nfcv_resp_one, data->emulation.nfcv_resp_pulse_32);
|
digital_signal_append(
|
||||||
|
data->emulation.nfcv_resp_one, data->emulation.nfcv_resp_pulse_32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!data->emulation.nfcv_resp_zero) {
|
if(!data->emulation.nfcv_resp_zero) {
|
||||||
/* logical zero: 8 pulses fc/32 then 256/fc unmodulated */
|
/* logical zero: 8 pulses fc/32 then 256/fc unmodulated */
|
||||||
data->emulation.nfcv_resp_zero = digital_signal_alloc(24);
|
data->emulation.nfcv_resp_zero = digital_signal_alloc(24);
|
||||||
for(size_t i = 0; i < 8; i++) {
|
for(size_t i = 0; i < 8; i++) {
|
||||||
digital_signal_append(data->emulation.nfcv_resp_zero, data->emulation.nfcv_resp_pulse_32);
|
digital_signal_append(
|
||||||
|
data->emulation.nfcv_resp_zero, data->emulation.nfcv_resp_pulse_32);
|
||||||
}
|
}
|
||||||
digital_signal_append(data->emulation.nfcv_resp_zero, data->emulation.nfcv_resp_unmod_256);
|
digital_signal_append(data->emulation.nfcv_resp_zero, data->emulation.nfcv_resp_unmod_256);
|
||||||
}
|
}
|
||||||
@@ -232,7 +246,8 @@ void nfcv_emu_alloc(NfcVData* data) {
|
|||||||
digital_signal_append(data->emulation.nfcv_resp_sof, data->emulation.nfcv_resp_unmod_256);
|
digital_signal_append(data->emulation.nfcv_resp_sof, data->emulation.nfcv_resp_unmod_256);
|
||||||
digital_signal_append(data->emulation.nfcv_resp_sof, data->emulation.nfcv_resp_unmod_256);
|
digital_signal_append(data->emulation.nfcv_resp_sof, data->emulation.nfcv_resp_unmod_256);
|
||||||
for(size_t i = 0; i < 24; i++) {
|
for(size_t i = 0; i < 24; i++) {
|
||||||
digital_signal_append(data->emulation.nfcv_resp_sof, data->emulation.nfcv_resp_pulse_32);
|
digital_signal_append(
|
||||||
|
data->emulation.nfcv_resp_sof, data->emulation.nfcv_resp_pulse_32);
|
||||||
}
|
}
|
||||||
digital_signal_append(data->emulation.nfcv_resp_sof, data->emulation.nfcv_resp_one);
|
digital_signal_append(data->emulation.nfcv_resp_sof, data->emulation.nfcv_resp_one);
|
||||||
}
|
}
|
||||||
@@ -241,7 +256,8 @@ void nfcv_emu_alloc(NfcVData* data) {
|
|||||||
data->emulation.nfcv_resp_eof = digital_signal_alloc(128);
|
data->emulation.nfcv_resp_eof = digital_signal_alloc(128);
|
||||||
digital_signal_append(data->emulation.nfcv_resp_eof, data->emulation.nfcv_resp_zero);
|
digital_signal_append(data->emulation.nfcv_resp_eof, data->emulation.nfcv_resp_zero);
|
||||||
for(size_t i = 0; i < 24; i++) {
|
for(size_t i = 0; i < 24; i++) {
|
||||||
digital_signal_append(data->emulation.nfcv_resp_eof, data->emulation.nfcv_resp_pulse_32);
|
digital_signal_append(
|
||||||
|
data->emulation.nfcv_resp_eof, data->emulation.nfcv_resp_pulse_32);
|
||||||
}
|
}
|
||||||
digital_signal_append(data->emulation.nfcv_resp_eof, data->emulation.nfcv_resp_unmod_256);
|
digital_signal_append(data->emulation.nfcv_resp_eof, data->emulation.nfcv_resp_unmod_256);
|
||||||
digital_signal_append(data->emulation.nfcv_resp_eof, data->emulation.nfcv_resp_unmod_256);
|
digital_signal_append(data->emulation.nfcv_resp_eof, data->emulation.nfcv_resp_unmod_256);
|
||||||
@@ -250,13 +266,16 @@ void nfcv_emu_alloc(NfcVData* data) {
|
|||||||
digital_signal_append(data->emulation.nfcv_resp_eof, data->emulation.nfcv_resp_unmod_256);
|
digital_signal_append(data->emulation.nfcv_resp_eof, data->emulation.nfcv_resp_unmod_256);
|
||||||
}
|
}
|
||||||
|
|
||||||
digital_sequence_set_signal(data->emulation.nfcv_signal, NFCV_SIG_SOF, data->emulation.nfcv_resp_sof);
|
digital_sequence_set_signal(
|
||||||
digital_sequence_set_signal(data->emulation.nfcv_signal, NFCV_SIG_BIT0, data->emulation.nfcv_resp_zero);
|
data->emulation.nfcv_signal, NFCV_SIG_SOF, data->emulation.nfcv_resp_sof);
|
||||||
digital_sequence_set_signal(data->emulation.nfcv_signal, NFCV_SIG_BIT1, data->emulation.nfcv_resp_one);
|
digital_sequence_set_signal(
|
||||||
digital_sequence_set_signal(data->emulation.nfcv_signal, NFCV_SIG_EOF, data->emulation.nfcv_resp_eof);
|
data->emulation.nfcv_signal, NFCV_SIG_BIT0, data->emulation.nfcv_resp_zero);
|
||||||
|
digital_sequence_set_signal(
|
||||||
|
data->emulation.nfcv_signal, NFCV_SIG_BIT1, data->emulation.nfcv_resp_one);
|
||||||
|
digital_sequence_set_signal(
|
||||||
|
data->emulation.nfcv_signal, NFCV_SIG_EOF, data->emulation.nfcv_resp_eof);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void nfcv_emu_send_raw(NfcVData* nfcv, uint8_t* data, uint8_t length) {
|
static void nfcv_emu_send_raw(NfcVData* nfcv, uint8_t* data, uint8_t length) {
|
||||||
digital_sequence_clear(nfcv->emulation.nfcv_signal);
|
digital_sequence_clear(nfcv->emulation.nfcv_signal);
|
||||||
digital_sequence_add(nfcv->emulation.nfcv_signal, NFCV_SIG_SOF);
|
digital_sequence_add(nfcv->emulation.nfcv_signal, NFCV_SIG_SOF);
|
||||||
@@ -266,7 +285,9 @@ static void nfcv_emu_send_raw(NfcVData* nfcv, uint8_t* data, uint8_t length) {
|
|||||||
uint32_t bit_pos = bit_total % 8;
|
uint32_t bit_pos = bit_total % 8;
|
||||||
uint8_t bit_val = 0x01 << bit_pos;
|
uint8_t bit_val = 0x01 << bit_pos;
|
||||||
|
|
||||||
digital_sequence_add(nfcv->emulation.nfcv_signal, (data[byte_pos] & bit_val) ? NFCV_SIG_BIT1 : NFCV_SIG_BIT0);
|
digital_sequence_add(
|
||||||
|
nfcv->emulation.nfcv_signal,
|
||||||
|
(data[byte_pos] & bit_val) ? NFCV_SIG_BIT1 : NFCV_SIG_BIT0);
|
||||||
}
|
}
|
||||||
|
|
||||||
digital_sequence_add(nfcv->emulation.nfcv_signal, NFCV_SIG_EOF);
|
digital_sequence_add(nfcv->emulation.nfcv_signal, NFCV_SIG_EOF);
|
||||||
@@ -277,8 +298,8 @@ static void nfcv_emu_send_raw(NfcVData* nfcv, uint8_t* data, uint8_t length) {
|
|||||||
furi_hal_gpio_write(&gpio_spi_r_mosi, false);
|
furi_hal_gpio_write(&gpio_spi_r_mosi, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nfcv_emu_send(FuriHalNfcTxRxContext* tx_rx, NfcVData* nfcv, uint8_t* data, uint8_t length) {
|
static void
|
||||||
|
nfcv_emu_send(FuriHalNfcTxRxContext* tx_rx, NfcVData* nfcv, uint8_t* data, uint8_t length) {
|
||||||
nfcv_crc(data, length);
|
nfcv_crc(data, length);
|
||||||
nfcv_emu_send_raw(nfcv, data, length + 2);
|
nfcv_emu_send_raw(nfcv, data, length + 2);
|
||||||
if(tx_rx->sniff_tx) {
|
if(tx_rx->sniff_tx) {
|
||||||
@@ -312,15 +333,20 @@ static uint32_t nfcv_read_be(uint8_t *data, uint32_t length) {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nfcv_emu_handle_packet(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, uint8_t* payload, uint32_t payload_length) {
|
void nfcv_emu_handle_packet(
|
||||||
|
FuriHalNfcTxRxContext* tx_rx,
|
||||||
|
FuriHalNfcDevData* nfc_data,
|
||||||
|
NfcVData* nfcv_data,
|
||||||
|
uint8_t* payload,
|
||||||
|
uint32_t payload_length) {
|
||||||
if(!payload_length) {
|
if(!payload_length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t flags = payload[0];
|
uint8_t flags = payload[0];
|
||||||
uint8_t command = payload[1];
|
uint8_t command = payload[1];
|
||||||
bool addressed = !(flags & RFAL_NFCV_REQ_FLAG_INVENTORY) && (flags & RFAL_NFCV_REQ_FLAG_ADDRESS);
|
bool addressed = !(flags & RFAL_NFCV_REQ_FLAG_INVENTORY) &&
|
||||||
|
(flags & RFAL_NFCV_REQ_FLAG_ADDRESS);
|
||||||
bool advanced = (command >= 0xA0);
|
bool advanced = (command >= 0xA0);
|
||||||
uint8_t address_offset = 2 + (advanced ? 1 : 0);
|
uint8_t address_offset = 2 + (advanced ? 1 : 0);
|
||||||
uint8_t payload_offset = address_offset + (addressed ? 8 : 0);
|
uint8_t payload_offset = address_offset + (addressed ? 8 : 0);
|
||||||
@@ -329,18 +355,40 @@ void nfcv_emu_handle_packet(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc
|
|||||||
|
|
||||||
if(addressed && nfcv_uidcmp(address, nfc_data->uid)) {
|
if(addressed && nfcv_uidcmp(address, nfc_data->uid)) {
|
||||||
FURI_LOG_D(TAG, "addressed command 0x%02X, but not for us:", command);
|
FURI_LOG_D(TAG, "addressed command 0x%02X, but not for us:", command);
|
||||||
FURI_LOG_D(TAG, " dest: %02X%02X%02X%02X%02X%02X%02X%02X", address[7], address[6], address[5], address[4], address[3], address[2], address[1], address[0]);
|
FURI_LOG_D(
|
||||||
FURI_LOG_D(TAG, " our UID: %02X%02X%02X%02X%02X%02X%02X%02X", nfc_data->uid[0], nfc_data->uid[1], nfc_data->uid[2], nfc_data->uid[3], nfc_data->uid[4], nfc_data->uid[5], nfc_data->uid[6], nfc_data->uid[7]);
|
TAG,
|
||||||
|
" dest: %02X%02X%02X%02X%02X%02X%02X%02X",
|
||||||
|
address[7],
|
||||||
|
address[6],
|
||||||
|
address[5],
|
||||||
|
address[4],
|
||||||
|
address[3],
|
||||||
|
address[2],
|
||||||
|
address[1],
|
||||||
|
address[0]);
|
||||||
|
FURI_LOG_D(
|
||||||
|
TAG,
|
||||||
|
" our UID: %02X%02X%02X%02X%02X%02X%02X%02X",
|
||||||
|
nfc_data->uid[0],
|
||||||
|
nfc_data->uid[1],
|
||||||
|
nfc_data->uid[2],
|
||||||
|
nfc_data->uid[3],
|
||||||
|
nfc_data->uid[4],
|
||||||
|
nfc_data->uid[5],
|
||||||
|
nfc_data->uid[6],
|
||||||
|
nfc_data->uid[7]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
switch(nfcv_data->type) {
|
switch(nfcv_data->type) {
|
||||||
case NfcVTypeSlixL:
|
case NfcVTypeSlixL:
|
||||||
if(nfcv_data->sub_data.slix_l.privacy &&
|
if(nfcv_data->sub_data.slix_l.privacy && command != ISO15693_CMD_NXP_GET_RANDOM_NUMBER &&
|
||||||
command != ISO15693_CMD_NXP_GET_RANDOM_NUMBER &&
|
|
||||||
command != ISO15693_CMD_NXP_SET_PASSWORD) {
|
command != ISO15693_CMD_NXP_SET_PASSWORD) {
|
||||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "command 0x%02X ignored, privacy mode", command);
|
snprintf(
|
||||||
|
nfcv_data->last_command,
|
||||||
|
sizeof(nfcv_data->last_command),
|
||||||
|
"command 0x%02X ignored, privacy mode",
|
||||||
|
command);
|
||||||
FURI_LOG_D(TAG, "%s", nfcv_data->last_command);
|
FURI_LOG_D(TAG, "%s", nfcv_data->last_command);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -354,8 +402,7 @@ void nfcv_emu_handle_packet(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc
|
|||||||
furi_delay_us(270);
|
furi_delay_us(270);
|
||||||
|
|
||||||
switch(command) {
|
switch(command) {
|
||||||
case ISO15693_INVENTORY:
|
case ISO15693_INVENTORY: {
|
||||||
{
|
|
||||||
response_buffer[0] = ISO15693_NOERROR;
|
response_buffer[0] = ISO15693_NOERROR;
|
||||||
response_buffer[1] = nfcv_data->dsfid;
|
response_buffer[1] = nfcv_data->dsfid;
|
||||||
nfcv_uidcpy(&response_buffer[2], nfc_data->uid);
|
nfcv_uidcpy(&response_buffer[2], nfc_data->uid);
|
||||||
@@ -365,40 +412,34 @@ void nfcv_emu_handle_packet(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ISO15693_STAYQUIET:
|
case ISO15693_STAYQUIET: {
|
||||||
{
|
|
||||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "STAYQUIET");
|
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "STAYQUIET");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ISO15693_LOCKBLOCK:
|
case ISO15693_LOCKBLOCK: {
|
||||||
{
|
|
||||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "LOCKBLOCK");
|
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "LOCKBLOCK");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ISO15693_READ_MULTI_BLOCK:
|
case ISO15693_READ_MULTI_BLOCK: {
|
||||||
{
|
|
||||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "READ_MULTI_BLOCK");
|
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "READ_MULTI_BLOCK");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ISO15693_WRITE_MULTI_BLOCK:
|
case ISO15693_WRITE_MULTI_BLOCK: {
|
||||||
{
|
|
||||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "WRITE_MULTI_BLOCK");
|
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "WRITE_MULTI_BLOCK");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ISO15693_SELECT:
|
case ISO15693_SELECT: {
|
||||||
{
|
|
||||||
response_buffer[0] = ISO15693_NOERROR;
|
response_buffer[0] = ISO15693_NOERROR;
|
||||||
nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1);
|
nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1);
|
||||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "SELECT");
|
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "SELECT");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ISO15693_READBLOCK:
|
case ISO15693_READBLOCK: {
|
||||||
{
|
|
||||||
uint8_t block = payload[payload_offset];
|
uint8_t block = payload[payload_offset];
|
||||||
|
|
||||||
if(block >= nfcv_data->block_num) {
|
if(block >= nfcv_data->block_num) {
|
||||||
@@ -406,15 +447,17 @@ void nfcv_emu_handle_packet(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc
|
|||||||
nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1);
|
nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1);
|
||||||
} else {
|
} else {
|
||||||
response_buffer[0] = ISO15693_NOERROR;
|
response_buffer[0] = ISO15693_NOERROR;
|
||||||
memcpy(&response_buffer[1], &nfcv_data->data[nfcv_data->block_size * block], nfcv_data->block_size);
|
memcpy(
|
||||||
|
&response_buffer[1],
|
||||||
|
&nfcv_data->data[nfcv_data->block_size * block],
|
||||||
|
nfcv_data->block_size);
|
||||||
nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1 + nfcv_data->block_size);
|
nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1 + nfcv_data->block_size);
|
||||||
}
|
}
|
||||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "READ BLOCK %d", block);
|
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "READ BLOCK %d", block);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ISO15693_WRITEBLOCK:
|
case ISO15693_WRITEBLOCK: {
|
||||||
{
|
|
||||||
uint8_t block = payload[payload_offset];
|
uint8_t block = payload[payload_offset];
|
||||||
uint8_t* data = &payload[payload_offset + 1];
|
uint8_t* data = &payload[payload_offset + 1];
|
||||||
|
|
||||||
@@ -422,15 +465,25 @@ void nfcv_emu_handle_packet(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc
|
|||||||
response_buffer[0] = ISO15693_ERROR_BLOCK_WRITE;
|
response_buffer[0] = ISO15693_ERROR_BLOCK_WRITE;
|
||||||
} else {
|
} else {
|
||||||
response_buffer[0] = ISO15693_NOERROR;
|
response_buffer[0] = ISO15693_NOERROR;
|
||||||
memcpy(&nfcv_data->data[nfcv_data->block_size * block], &response_buffer[1], nfcv_data->block_size);
|
memcpy(
|
||||||
|
&nfcv_data->data[nfcv_data->block_size * block],
|
||||||
|
&response_buffer[1],
|
||||||
|
nfcv_data->block_size);
|
||||||
}
|
}
|
||||||
nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1);
|
nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1);
|
||||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "WRITE BLOCK %d <- %02X %02X %02X %02X", block, data[0], data[1], data[2], data[3]);
|
snprintf(
|
||||||
|
nfcv_data->last_command,
|
||||||
|
sizeof(nfcv_data->last_command),
|
||||||
|
"WRITE BLOCK %d <- %02X %02X %02X %02X",
|
||||||
|
block,
|
||||||
|
data[0],
|
||||||
|
data[1],
|
||||||
|
data[2],
|
||||||
|
data[3]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ISO15693_GET_SYSTEM_INFO:
|
case ISO15693_GET_SYSTEM_INFO: {
|
||||||
{
|
|
||||||
response_buffer[0] = ISO15693_NOERROR;
|
response_buffer[0] = ISO15693_NOERROR;
|
||||||
response_buffer[1] = 0x0F;
|
response_buffer[1] = 0x0F;
|
||||||
nfcv_uidcpy(&response_buffer[2], nfc_data->uid);
|
nfcv_uidcpy(&response_buffer[2], nfc_data->uid);
|
||||||
@@ -446,8 +499,7 @@ void nfcv_emu_handle_packet(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ISO15693_CMD_NXP_GET_RANDOM_NUMBER:
|
case ISO15693_CMD_NXP_GET_RANDOM_NUMBER: {
|
||||||
{
|
|
||||||
nfcv_data->sub_data.slix_l.rand[0] = furi_hal_random_get();
|
nfcv_data->sub_data.slix_l.rand[0] = furi_hal_random_get();
|
||||||
nfcv_data->sub_data.slix_l.rand[1] = furi_hal_random_get();
|
nfcv_data->sub_data.slix_l.rand[1] = furi_hal_random_get();
|
||||||
|
|
||||||
@@ -456,15 +508,16 @@ void nfcv_emu_handle_packet(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc
|
|||||||
response_buffer[2] = nfcv_data->sub_data.slix_l.rand[0];
|
response_buffer[2] = nfcv_data->sub_data.slix_l.rand[0];
|
||||||
|
|
||||||
nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 3);
|
nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 3);
|
||||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command),
|
snprintf(
|
||||||
|
nfcv_data->last_command,
|
||||||
|
sizeof(nfcv_data->last_command),
|
||||||
"GET_RANDOM_NUMBER -> 0x%02X%02X",
|
"GET_RANDOM_NUMBER -> 0x%02X%02X",
|
||||||
nfcv_data->sub_data.slix_l.rand[0],
|
nfcv_data->sub_data.slix_l.rand[0],
|
||||||
nfcv_data->sub_data.slix_l.rand[1]);
|
nfcv_data->sub_data.slix_l.rand[1]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ISO15693_CMD_NXP_SET_PASSWORD:
|
case ISO15693_CMD_NXP_SET_PASSWORD: {
|
||||||
{
|
|
||||||
uint8_t password_id = payload[payload_offset];
|
uint8_t password_id = payload[payload_offset];
|
||||||
uint8_t* password_xored = &payload[payload_offset + 1];
|
uint8_t* password_xored = &payload[payload_offset + 1];
|
||||||
uint8_t* rand = nfcv_data->sub_data.slix_l.rand;
|
uint8_t* rand = nfcv_data->sub_data.slix_l.rand;
|
||||||
@@ -496,26 +549,40 @@ void nfcv_emu_handle_packet(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc
|
|||||||
nfcv_data->sub_data.slix_l.privacy = false;
|
nfcv_data->sub_data.slix_l.privacy = false;
|
||||||
response_buffer[0] = ISO15693_NOERROR;
|
response_buffer[0] = ISO15693_NOERROR;
|
||||||
nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1);
|
nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1);
|
||||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "SET_PASSWORD #%02X 0x%08lX OK", password_id, pass_received);
|
snprintf(
|
||||||
|
nfcv_data->last_command,
|
||||||
|
sizeof(nfcv_data->last_command),
|
||||||
|
"SET_PASSWORD #%02X 0x%08lX OK",
|
||||||
|
password_id,
|
||||||
|
pass_received);
|
||||||
} else {
|
} else {
|
||||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "SET_PASSWORD #%02X 0x%08lX/%08lX FAIL", password_id, pass_received, pass_expect);
|
snprintf(
|
||||||
|
nfcv_data->last_command,
|
||||||
|
sizeof(nfcv_data->last_command),
|
||||||
|
"SET_PASSWORD #%02X 0x%08lX/%08lX FAIL",
|
||||||
|
password_id,
|
||||||
|
pass_received,
|
||||||
|
pass_expect);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ISO15693_CMD_NXP_ENABLE_PRIVACY:
|
case ISO15693_CMD_NXP_ENABLE_PRIVACY: {
|
||||||
{
|
|
||||||
response_buffer[0] = ISO15693_NOERROR;
|
response_buffer[0] = ISO15693_NOERROR;
|
||||||
|
|
||||||
nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1);
|
nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1);
|
||||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "ISO15693_CMD_NXP_ENABLE_PRIVACY");
|
snprintf(
|
||||||
|
nfcv_data->last_command,
|
||||||
|
sizeof(nfcv_data->last_command),
|
||||||
|
"ISO15693_CMD_NXP_ENABLE_PRIVACY");
|
||||||
|
|
||||||
nfcv_data->sub_data.slix_l.privacy = true;
|
nfcv_data->sub_data.slix_l.privacy = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "unsupported: %02X", command);
|
snprintf(
|
||||||
|
nfcv_data->last_command, sizeof(nfcv_data->last_command), "unsupported: %02X", command);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -536,16 +603,31 @@ void nfcv_emu_init(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data) {
|
|||||||
furi_hal_spi_bus_handle_deinit(&furi_hal_spi_bus_handle_nfc);
|
furi_hal_spi_bus_handle_deinit(&furi_hal_spi_bus_handle_nfc);
|
||||||
|
|
||||||
FURI_LOG_D(TAG, "Starting NfcV emulation");
|
FURI_LOG_D(TAG, "Starting NfcV emulation");
|
||||||
FURI_LOG_D(TAG, " UID: %02X %02X %02X %02X %02X %02X %02X %02X",
|
FURI_LOG_D(
|
||||||
nfc_data->uid[0], nfc_data->uid[1], nfc_data->uid[2], nfc_data->uid[3],
|
TAG,
|
||||||
nfc_data->uid[4], nfc_data->uid[5], nfc_data->uid[6], nfc_data->uid[7]);
|
" UID: %02X %02X %02X %02X %02X %02X %02X %02X",
|
||||||
|
nfc_data->uid[0],
|
||||||
|
nfc_data->uid[1],
|
||||||
|
nfc_data->uid[2],
|
||||||
|
nfc_data->uid[3],
|
||||||
|
nfc_data->uid[4],
|
||||||
|
nfc_data->uid[5],
|
||||||
|
nfc_data->uid[6],
|
||||||
|
nfc_data->uid[7]);
|
||||||
|
|
||||||
switch(nfcv_data->type) {
|
switch(nfcv_data->type) {
|
||||||
case NfcVTypeSlixL:
|
case NfcVTypeSlixL:
|
||||||
FURI_LOG_D(TAG, " Card type: SLIX-L");
|
FURI_LOG_D(TAG, " Card type: SLIX-L");
|
||||||
FURI_LOG_D(TAG, " Privacy pass: 0x%08lX", nfcv_read_be(nfcv_data->sub_data.slix_l.key_privacy, 4));
|
FURI_LOG_D(
|
||||||
FURI_LOG_D(TAG, " Destroy pass: 0x%08lX", nfcv_read_be(nfcv_data->sub_data.slix_l.key_destroy, 4));
|
TAG,
|
||||||
FURI_LOG_D(TAG, " EAS pass: 0x%08lX", nfcv_read_be(nfcv_data->sub_data.slix_l.key_eas, 4));
|
" Privacy pass: 0x%08lX",
|
||||||
|
nfcv_read_be(nfcv_data->sub_data.slix_l.key_privacy, 4));
|
||||||
|
FURI_LOG_D(
|
||||||
|
TAG,
|
||||||
|
" Destroy pass: 0x%08lX",
|
||||||
|
nfcv_read_be(nfcv_data->sub_data.slix_l.key_destroy, 4));
|
||||||
|
FURI_LOG_D(
|
||||||
|
TAG, " EAS pass: 0x%08lX", nfcv_read_be(nfcv_data->sub_data.slix_l.key_eas, 4));
|
||||||
FURI_LOG_D(TAG, " Privacy mode: %s", nfcv_data->sub_data.slix_l.privacy ? "ON" : "OFF");
|
FURI_LOG_D(TAG, " Privacy mode: %s", nfcv_data->sub_data.slix_l.privacy ? "ON" : "OFF");
|
||||||
break;
|
break;
|
||||||
case NfcVTypeSlixS:
|
case NfcVTypeSlixS:
|
||||||
@@ -579,8 +661,11 @@ void nfcv_emu_deinit(NfcVData* nfcv_data) {
|
|||||||
pulse_reader_free(nfcv_data->emulation.reader_signal);
|
pulse_reader_free(nfcv_data->emulation.reader_signal);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nfcv_emu_loop(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, uint32_t timeout_ms) {
|
bool nfcv_emu_loop(
|
||||||
|
FuriHalNfcTxRxContext* tx_rx,
|
||||||
|
FuriHalNfcDevData* nfc_data,
|
||||||
|
NfcVData* nfcv_data,
|
||||||
|
uint32_t timeout_ms) {
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
uint32_t frame_state = NFCV_FRAME_STATE_SOF1;
|
uint32_t frame_state = NFCV_FRAME_STATE_SOF1;
|
||||||
uint32_t periods_previous = 0;
|
uint32_t periods_previous = 0;
|
||||||
@@ -592,8 +677,8 @@ bool nfcv_emu_loop(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, Nf
|
|||||||
bool wait_for_pulse = false;
|
bool wait_for_pulse = false;
|
||||||
|
|
||||||
while(true) {
|
while(true) {
|
||||||
|
uint32_t periods =
|
||||||
uint32_t periods = pulse_reader_receive(nfcv_data->emulation.reader_signal, timeout_ms * 1000);
|
pulse_reader_receive(nfcv_data->emulation.reader_signal, timeout_ms * 1000);
|
||||||
|
|
||||||
if(periods == PULSE_READER_NO_EDGE) {
|
if(periods == PULSE_READER_NO_EDGE) {
|
||||||
break;
|
break;
|
||||||
@@ -602,7 +687,12 @@ bool nfcv_emu_loop(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, Nf
|
|||||||
if(wait_for_pulse) {
|
if(wait_for_pulse) {
|
||||||
wait_for_pulse = false;
|
wait_for_pulse = false;
|
||||||
if(periods != 1) {
|
if(periods != 1) {
|
||||||
snprintf(reset_reason, sizeof(reset_reason), "SOF: Expected a single low pulse in state %lu, but got %lu", frame_state, periods);
|
snprintf(
|
||||||
|
reset_reason,
|
||||||
|
sizeof(reset_reason),
|
||||||
|
"SOF: Expected a single low pulse in state %lu, but got %lu",
|
||||||
|
frame_state,
|
||||||
|
periods);
|
||||||
frame_state = NFCV_FRAME_STATE_RESET;
|
frame_state = NFCV_FRAME_STATE_RESET;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@@ -629,14 +719,23 @@ bool nfcv_emu_loop(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, Nf
|
|||||||
periods_previous = 2;
|
periods_previous = 2;
|
||||||
wait_for_pulse = true;
|
wait_for_pulse = true;
|
||||||
} else {
|
} else {
|
||||||
snprintf(reset_reason, sizeof(reset_reason), "SOF: Expected 4/6 periods, got %lu", periods);
|
snprintf(
|
||||||
|
reset_reason,
|
||||||
|
sizeof(reset_reason),
|
||||||
|
"SOF: Expected 4/6 periods, got %lu",
|
||||||
|
periods);
|
||||||
frame_state = NFCV_FRAME_STATE_SOF1;
|
frame_state = NFCV_FRAME_STATE_SOF1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NFCV_FRAME_STATE_CODING_256:
|
case NFCV_FRAME_STATE_CODING_256:
|
||||||
if(periods_previous > periods) {
|
if(periods_previous > periods) {
|
||||||
snprintf(reset_reason, sizeof(reset_reason), "1oo256: Missing %lu periods from previous symbol, got %lu", periods_previous, periods);
|
snprintf(
|
||||||
|
reset_reason,
|
||||||
|
sizeof(reset_reason),
|
||||||
|
"1oo256: Missing %lu periods from previous symbol, got %lu",
|
||||||
|
periods_previous,
|
||||||
|
periods);
|
||||||
frame_state = NFCV_FRAME_STATE_RESET;
|
frame_state = NFCV_FRAME_STATE_RESET;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -644,7 +743,8 @@ bool nfcv_emu_loop(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, Nf
|
|||||||
periods -= periods_previous;
|
periods -= periods_previous;
|
||||||
|
|
||||||
if(periods > 512) {
|
if(periods > 512) {
|
||||||
snprintf(reset_reason, sizeof(reset_reason), "1oo256: %lu periods is too much", periods);
|
snprintf(
|
||||||
|
reset_reason, sizeof(reset_reason), "1oo256: %lu periods is too much", periods);
|
||||||
frame_state = NFCV_FRAME_STATE_RESET;
|
frame_state = NFCV_FRAME_STATE_RESET;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -664,7 +764,12 @@ bool nfcv_emu_loop(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, Nf
|
|||||||
|
|
||||||
case NFCV_FRAME_STATE_CODING_4:
|
case NFCV_FRAME_STATE_CODING_4:
|
||||||
if(periods_previous > periods) {
|
if(periods_previous > periods) {
|
||||||
snprintf(reset_reason, sizeof(reset_reason), "1oo4: Missing %lu periods from previous symbol, got %lu", periods_previous, periods);
|
snprintf(
|
||||||
|
reset_reason,
|
||||||
|
sizeof(reset_reason),
|
||||||
|
"1oo4: Missing %lu periods from previous symbol, got %lu",
|
||||||
|
periods_previous,
|
||||||
|
periods);
|
||||||
frame_state = NFCV_FRAME_STATE_RESET;
|
frame_state = NFCV_FRAME_STATE_RESET;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -692,7 +797,11 @@ bool nfcv_emu_loop(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, Nf
|
|||||||
frame_state = NFCV_FRAME_STATE_EOF;
|
frame_state = NFCV_FRAME_STATE_EOF;
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
snprintf(reset_reason, sizeof(reset_reason), "1oo4: Expected 1/3/5/7 low pulses, but got %lu", periods);
|
snprintf(
|
||||||
|
reset_reason,
|
||||||
|
sizeof(reset_reason),
|
||||||
|
"1oo4: Expected 1/3/5/7 low pulses, but got %lu",
|
||||||
|
periods);
|
||||||
frame_state = NFCV_FRAME_STATE_RESET;
|
frame_state = NFCV_FRAME_STATE_RESET;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,9 +8,6 @@
|
|||||||
#include "nfc_util.h"
|
#include "nfc_util.h"
|
||||||
#include <furi_hal_nfc.h>
|
#include <furi_hal_nfc.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define NFCV_FC (13560000.0f) /* MHz */
|
#define NFCV_FC (13560000.0f) /* MHz */
|
||||||
#define NFCV_RESP_SUBC1_PULSE_32 (1.0f / (NFCV_FC / 32) / 2.0f) /* 1.1799 µs */
|
#define NFCV_RESP_SUBC1_PULSE_32 (1.0f / (NFCV_FC / 32) / 2.0f) /* 1.1799 µs */
|
||||||
#define NFCV_RESP_SUBC1_UNMOD_256 (256.0f / NFCV_FC) /* 18.8791 µs */
|
#define NFCV_RESP_SUBC1_UNMOD_256 (256.0f / NFCV_FC) /* 18.8791 µs */
|
||||||
@@ -24,7 +21,6 @@
|
|||||||
#define NFCV_BLOCK_SIZE 4
|
#define NFCV_BLOCK_SIZE 4
|
||||||
#define NFCV_MAX_DUMP_SIZE (NFCV_BLOCK_SIZE * NFCV_TOTAL_BLOCKS_MAX)
|
#define NFCV_MAX_DUMP_SIZE (NFCV_BLOCK_SIZE * NFCV_TOTAL_BLOCKS_MAX)
|
||||||
|
|
||||||
|
|
||||||
#define NFCV_FRAME_STATE_SOF1 0
|
#define NFCV_FRAME_STATE_SOF1 0
|
||||||
#define NFCV_FRAME_STATE_SOF2 1
|
#define NFCV_FRAME_STATE_SOF2 1
|
||||||
#define NFCV_FRAME_STATE_CODING_4 2
|
#define NFCV_FRAME_STATE_CODING_4 2
|
||||||
@@ -32,7 +28,6 @@
|
|||||||
#define NFCV_FRAME_STATE_EOF 4
|
#define NFCV_FRAME_STATE_EOF 4
|
||||||
#define NFCV_FRAME_STATE_RESET 5
|
#define NFCV_FRAME_STATE_RESET 5
|
||||||
|
|
||||||
|
|
||||||
#define NFCV_SIG_SOF 0
|
#define NFCV_SIG_SOF 0
|
||||||
#define NFCV_SIG_BIT0 1
|
#define NFCV_SIG_BIT0 1
|
||||||
#define NFCV_SIG_BIT1 2
|
#define NFCV_SIG_BIT1 2
|
||||||
@@ -85,7 +80,6 @@
|
|||||||
#define ISO15693_ERROR_BLOCK_WRITE 0x13 // Writing was unsuccessful
|
#define ISO15693_ERROR_BLOCK_WRITE 0x13 // Writing was unsuccessful
|
||||||
#define ISO15693_ERROR_BLOCL_WRITELOCK 0x14 // Locking was unsuccessful
|
#define ISO15693_ERROR_BLOCL_WRITELOCK 0x14 // Locking was unsuccessful
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
NfcVAuthMethodManual,
|
NfcVAuthMethodManual,
|
||||||
NfcVAuthMethodTonieBox,
|
NfcVAuthMethodTonieBox,
|
||||||
@@ -139,7 +133,6 @@ typedef union {
|
|||||||
NfcVSlixLData slix_l;
|
NfcVSlixLData slix_l;
|
||||||
} NfcVSubtypeData;
|
} NfcVSubtypeData;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PulseReader* reader_signal;
|
PulseReader* reader_signal;
|
||||||
DigitalSignal* nfcv_resp_pulse_32;
|
DigitalSignal* nfcv_resp_pulse_32;
|
||||||
@@ -186,4 +179,8 @@ bool nfcv_read_card(NfcVReader* reader, FuriHalNfcDevData* nfc_data, NfcVData* d
|
|||||||
|
|
||||||
void nfcv_emu_init(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data);
|
void nfcv_emu_init(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data);
|
||||||
void nfcv_emu_deinit(NfcVData* nfcv_data);
|
void nfcv_emu_deinit(NfcVData* nfcv_data);
|
||||||
bool nfcv_emu_loop(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, uint32_t timeout_ms);
|
bool nfcv_emu_loop(
|
||||||
|
FuriHalNfcTxRxContext* tx_rx,
|
||||||
|
FuriHalNfcDevData* nfc_data,
|
||||||
|
NfcVData* nfcv_data,
|
||||||
|
uint32_t timeout_ms);
|
||||||
|
|||||||
@@ -6,46 +6,36 @@
|
|||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include "furi_hal_nfc.h"
|
#include "furi_hal_nfc.h"
|
||||||
|
|
||||||
|
|
||||||
bool slix_check_card_type(FuriHalNfcDevData* nfc_data) {
|
bool slix_check_card_type(FuriHalNfcDevData* nfc_data) {
|
||||||
if((nfc_data->uid[0] == 0xE0)
|
if((nfc_data->uid[0] == 0xE0) && (nfc_data->uid[1] == 0x04) && (nfc_data->uid[2] == 0x01) &&
|
||||||
&& (nfc_data->uid[1] == 0x04)
|
(((nfc_data->uid[3] >> 4) & 3) == 2)) {
|
||||||
&& (nfc_data->uid[2] == 0x01)
|
|
||||||
&& (((nfc_data->uid[3] >> 4) & 3) == 2)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool slix2_check_card_type(FuriHalNfcDevData* nfc_data) {
|
bool slix2_check_card_type(FuriHalNfcDevData* nfc_data) {
|
||||||
if((nfc_data->uid[0] == 0xE0)
|
if((nfc_data->uid[0] == 0xE0) && (nfc_data->uid[1] == 0x04) && (nfc_data->uid[2] == 0x01) &&
|
||||||
&& (nfc_data->uid[1] == 0x04)
|
(((nfc_data->uid[3] >> 4) & 3) == 1)) {
|
||||||
&& (nfc_data->uid[2] == 0x01)
|
|
||||||
&& (((nfc_data->uid[3] >> 4) & 3) == 1)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool slix_s_check_card_type(FuriHalNfcDevData* nfc_data) {
|
bool slix_s_check_card_type(FuriHalNfcDevData* nfc_data) {
|
||||||
if((nfc_data->uid[0] == 0xE0)
|
if((nfc_data->uid[0] == 0xE0) && (nfc_data->uid[1] == 0x04) && (nfc_data->uid[2] == 0x02)) {
|
||||||
&& (nfc_data->uid[1] == 0x04)
|
|
||||||
&& (nfc_data->uid[2] == 0x02)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool slix_l_check_card_type(FuriHalNfcDevData* nfc_data) {
|
bool slix_l_check_card_type(FuriHalNfcDevData* nfc_data) {
|
||||||
if((nfc_data->uid[0] == 0xE0)
|
if((nfc_data->uid[0] == 0xE0) && (nfc_data->uid[1] == 0x04) && (nfc_data->uid[2] == 0x03)) {
|
||||||
&& (nfc_data->uid[1] == 0x04)
|
|
||||||
&& (nfc_data->uid[2] == 0x03)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ReturnCode slix_l_get_random(NfcVData* data) {
|
ReturnCode slix_l_get_random(NfcVData* data) {
|
||||||
uint16_t received = 0;
|
uint16_t received = 0;
|
||||||
uint8_t rxBuf[32];
|
uint8_t rxBuf[32];
|
||||||
@@ -84,8 +74,7 @@ ReturnCode slix_l_unlock(NfcVData* data, uint32_t password_id) {
|
|||||||
data->sub_data.slix_l.rand[1],
|
data->sub_data.slix_l.rand[1],
|
||||||
data->sub_data.slix_l.rand[0],
|
data->sub_data.slix_l.rand[0],
|
||||||
data->sub_data.slix_l.rand[1],
|
data->sub_data.slix_l.rand[1],
|
||||||
data->sub_data.slix_l.rand[0]
|
data->sub_data.slix_l.rand[0]};
|
||||||
};
|
|
||||||
uint8_t* password = NULL;
|
uint8_t* password = NULL;
|
||||||
|
|
||||||
switch(password_id) {
|
switch(password_id) {
|
||||||
|
|||||||
@@ -9,11 +9,9 @@
|
|||||||
#define ISO15693_CMD_NXP_SET_PASSWORD 0xB3
|
#define ISO15693_CMD_NXP_SET_PASSWORD 0xB3
|
||||||
#define ISO15693_MANUFACTURER_NXP 0x04
|
#define ISO15693_MANUFACTURER_NXP 0x04
|
||||||
|
|
||||||
|
|
||||||
bool slix_check_card_type(FuriHalNfcDevData* nfc_data);
|
bool slix_check_card_type(FuriHalNfcDevData* nfc_data);
|
||||||
bool slix2_check_card_type(FuriHalNfcDevData* nfc_data);
|
bool slix2_check_card_type(FuriHalNfcDevData* nfc_data);
|
||||||
bool slix_s_check_card_type(FuriHalNfcDevData* nfc_data);
|
bool slix_s_check_card_type(FuriHalNfcDevData* nfc_data);
|
||||||
bool slix_l_check_card_type(FuriHalNfcDevData* nfc_data);
|
bool slix_l_check_card_type(FuriHalNfcDevData* nfc_data);
|
||||||
ReturnCode slix_l_get_random(NfcVData* data);
|
ReturnCode slix_l_get_random(NfcVData* data);
|
||||||
ReturnCode slix_l_unlock(NfcVData* data, uint32_t password_id);
|
ReturnCode slix_l_unlock(NfcVData* data, uint32_t password_id);
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
#include "pulse_reader.h"
|
#include "pulse_reader.h"
|
||||||
|
|
||||||
|
|
||||||
#define GPIO_PIN_MAP(pin, prefix) \
|
#define GPIO_PIN_MAP(pin, prefix) \
|
||||||
(((pin) == (LL_GPIO_PIN_0)) ? prefix##0 : \
|
(((pin) == (LL_GPIO_PIN_0)) ? prefix##0 : \
|
||||||
((pin) == (LL_GPIO_PIN_1)) ? prefix##1 : \
|
((pin) == (LL_GPIO_PIN_1)) ? prefix##1 : \
|
||||||
@@ -26,10 +25,7 @@
|
|||||||
|
|
||||||
#define GET_DMAMUX_EXTI_LINE(pin) GPIO_PIN_MAP(pin, LL_DMAMUX_REQ_GEN_EXTI_LINE)
|
#define GET_DMAMUX_EXTI_LINE(pin) GPIO_PIN_MAP(pin, LL_DMAMUX_REQ_GEN_EXTI_LINE)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PulseReader* pulse_reader_alloc(const GpioPin* gpio, uint32_t size) {
|
PulseReader* pulse_reader_alloc(const GpioPin* gpio, uint32_t size) {
|
||||||
|
|
||||||
PulseReader* signal = malloc(sizeof(PulseReader));
|
PulseReader* signal = malloc(sizeof(PulseReader));
|
||||||
signal->timer_buffer = malloc(size * sizeof(uint32_t));
|
signal->timer_buffer = malloc(size * sizeof(uint32_t));
|
||||||
signal->gpio_buffer = malloc(size * sizeof(uint32_t));
|
signal->gpio_buffer = malloc(size * sizeof(uint32_t));
|
||||||
@@ -50,7 +46,8 @@ PulseReader* pulse_reader_alloc(const GpioPin* gpio, uint32_t size) {
|
|||||||
signal->dma_config_timer.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
|
signal->dma_config_timer.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
|
||||||
signal->dma_config_timer.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD;
|
signal->dma_config_timer.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD;
|
||||||
signal->dma_config_timer.Mode = LL_DMA_MODE_CIRCULAR;
|
signal->dma_config_timer.Mode = LL_DMA_MODE_CIRCULAR;
|
||||||
signal->dma_config_timer.PeriphRequest = LL_DMAMUX_REQ_GENERATOR0; /* executes LL_DMA_SetPeriphRequest */
|
signal->dma_config_timer.PeriphRequest =
|
||||||
|
LL_DMAMUX_REQ_GENERATOR0; /* executes LL_DMA_SetPeriphRequest */
|
||||||
signal->dma_config_timer.Priority = LL_DMA_PRIORITY_VERYHIGH;
|
signal->dma_config_timer.Priority = LL_DMA_PRIORITY_VERYHIGH;
|
||||||
|
|
||||||
signal->dma_config_gpio.Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY;
|
signal->dma_config_gpio.Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY;
|
||||||
@@ -59,7 +56,8 @@ PulseReader* pulse_reader_alloc(const GpioPin* gpio, uint32_t size) {
|
|||||||
signal->dma_config_gpio.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
|
signal->dma_config_gpio.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
|
||||||
signal->dma_config_gpio.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD;
|
signal->dma_config_gpio.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD;
|
||||||
signal->dma_config_gpio.Mode = LL_DMA_MODE_CIRCULAR;
|
signal->dma_config_gpio.Mode = LL_DMA_MODE_CIRCULAR;
|
||||||
signal->dma_config_gpio.PeriphRequest = LL_DMAMUX_REQ_GENERATOR0; /* executes LL_DMA_SetPeriphRequest */
|
signal->dma_config_gpio.PeriphRequest =
|
||||||
|
LL_DMAMUX_REQ_GENERATOR0; /* executes LL_DMA_SetPeriphRequest */
|
||||||
signal->dma_config_gpio.Priority = LL_DMA_PRIORITY_VERYHIGH;
|
signal->dma_config_gpio.Priority = LL_DMA_PRIORITY_VERYHIGH;
|
||||||
|
|
||||||
return signal;
|
return signal;
|
||||||
@@ -126,14 +124,16 @@ void pulse_reader_start(PulseReader* signal) {
|
|||||||
LL_TIM_EnableCounter(TIM2);
|
LL_TIM_EnableCounter(TIM2);
|
||||||
|
|
||||||
/* generator 0 gets fed by EXTI_LINEn */
|
/* generator 0 gets fed by EXTI_LINEn */
|
||||||
LL_DMAMUX_SetRequestSignalID(NULL, LL_DMAMUX_REQ_GEN_0, GET_DMAMUX_EXTI_LINE(signal->gpio->pin));
|
LL_DMAMUX_SetRequestSignalID(
|
||||||
|
NULL, LL_DMAMUX_REQ_GEN_0, GET_DMAMUX_EXTI_LINE(signal->gpio->pin));
|
||||||
/* trigger on rising edge of the interrupt */
|
/* trigger on rising edge of the interrupt */
|
||||||
LL_DMAMUX_SetRequestGenPolarity(NULL, LL_DMAMUX_REQ_GEN_0, LL_DMAMUX_REQ_GEN_POL_RISING);
|
LL_DMAMUX_SetRequestGenPolarity(NULL, LL_DMAMUX_REQ_GEN_0, LL_DMAMUX_REQ_GEN_POL_RISING);
|
||||||
/* now enable request generation again */
|
/* now enable request generation again */
|
||||||
LL_DMAMUX_EnableRequestGen(NULL, LL_DMAMUX_REQ_GEN_0);
|
LL_DMAMUX_EnableRequestGen(NULL, LL_DMAMUX_REQ_GEN_0);
|
||||||
|
|
||||||
/* we need the EXTI to be configured as interrupt generating line, but no ISR registered */
|
/* we need the EXTI to be configured as interrupt generating line, but no ISR registered */
|
||||||
furi_hal_gpio_init_ex(signal->gpio, GpioModeInterruptRiseFall, GpioPullNo, GpioSpeedVeryHigh, GpioAltFnUnused);
|
furi_hal_gpio_init_ex(
|
||||||
|
signal->gpio, GpioModeInterruptRiseFall, GpioPullNo, GpioSpeedVeryHigh, GpioAltFnUnused);
|
||||||
|
|
||||||
/* capture current timer */
|
/* capture current timer */
|
||||||
signal->pos = 0;
|
signal->pos = 0;
|
||||||
@@ -149,17 +149,16 @@ void pulse_reader_start(PulseReader* signal) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t pulse_reader_receive(PulseReader* signal, int timeout_us) {
|
uint32_t pulse_reader_receive(PulseReader* signal, int timeout_us) {
|
||||||
|
|
||||||
uint32_t start_time = DWT->CYCCNT;
|
uint32_t start_time = DWT->CYCCNT;
|
||||||
uint32_t timeout_ticks = timeout_us * (F_TIM2 / 1000000);
|
uint32_t timeout_ticks = timeout_us * (F_TIM2 / 1000000);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
/* get the DMA's next write position by reading "remaining length" register */
|
/* get the DMA's next write position by reading "remaining length" register */
|
||||||
uint32_t dma_pos = signal->size - (uint32_t)LL_DMA_GetDataLength(DMA1, signal->dma_channel);
|
uint32_t dma_pos =
|
||||||
|
signal->size - (uint32_t)LL_DMA_GetDataLength(DMA1, signal->dma_channel);
|
||||||
|
|
||||||
/* the DMA has advanced in the ringbuffer */
|
/* the DMA has advanced in the ringbuffer */
|
||||||
if(dma_pos != signal->pos) {
|
if(dma_pos != signal->pos) {
|
||||||
|
|
||||||
uint32_t delta = signal->timer_buffer[signal->pos] - signal->timer_value;
|
uint32_t delta = signal->timer_buffer[signal->pos] - signal->timer_value;
|
||||||
uint32_t last_gpio_value = signal->gpio_value;
|
uint32_t last_gpio_value = signal->gpio_value;
|
||||||
|
|
||||||
@@ -179,7 +178,8 @@ uint32_t pulse_reader_receive(PulseReader* signal, int timeout_us) {
|
|||||||
|
|
||||||
/* probably larger values, so choose a wider data type */
|
/* probably larger values, so choose a wider data type */
|
||||||
if(signal->unit_divider > 1) {
|
if(signal->unit_divider > 1) {
|
||||||
delta_unit = (uint32_t)((uint64_t)delta * (uint64_t)signal->unit_multiplier / signal->unit_divider);
|
delta_unit =
|
||||||
|
(uint32_t)((uint64_t)delta * (uint64_t)signal->unit_multiplier / signal->unit_divider);
|
||||||
} else {
|
} else {
|
||||||
delta_unit = delta * signal->unit_multiplier;
|
delta_unit = delta * signal->unit_multiplier;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ typedef enum {
|
|||||||
PulseReaderUnitMicrosecond,
|
PulseReaderUnitMicrosecond,
|
||||||
} PulseReaderUnit;
|
} PulseReaderUnit;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool start_level;
|
bool start_level;
|
||||||
uint32_t* timer_buffer;
|
uint32_t* timer_buffer;
|
||||||
@@ -47,7 +46,6 @@ typedef struct {
|
|||||||
LL_DMA_InitTypeDef dma_config_gpio;
|
LL_DMA_InitTypeDef dma_config_gpio;
|
||||||
} PulseReader;
|
} PulseReader;
|
||||||
|
|
||||||
|
|
||||||
/** Allocate a PulseReader object
|
/** Allocate a PulseReader object
|
||||||
*
|
*
|
||||||
* Allocates memory for a ringbuffer and initalizes the object
|
* Allocates memory for a ringbuffer and initalizes the object
|
||||||
@@ -57,7 +55,6 @@ typedef struct {
|
|||||||
*/
|
*/
|
||||||
PulseReader* pulse_reader_alloc(const GpioPin* gpio, uint32_t size);
|
PulseReader* pulse_reader_alloc(const GpioPin* gpio, uint32_t size);
|
||||||
|
|
||||||
|
|
||||||
/** Free a PulseReader object
|
/** Free a PulseReader object
|
||||||
*
|
*
|
||||||
* Frees all memory of the given object
|
* Frees all memory of the given object
|
||||||
@@ -66,7 +63,6 @@ PulseReader* pulse_reader_alloc(const GpioPin* gpio, uint32_t size);
|
|||||||
*/
|
*/
|
||||||
void pulse_reader_free(PulseReader* signal);
|
void pulse_reader_free(PulseReader* signal);
|
||||||
|
|
||||||
|
|
||||||
/** Start signal capturing
|
/** Start signal capturing
|
||||||
*
|
*
|
||||||
* Initializes DMA1, TIM2 and DMAMUX_REQ_GEN_0 to automatically capture timer values
|
* Initializes DMA1, TIM2 and DMAMUX_REQ_GEN_0 to automatically capture timer values
|
||||||
@@ -83,7 +79,6 @@ void pulse_reader_start(PulseReader* signal);
|
|||||||
*/
|
*/
|
||||||
void pulse_reader_stop(PulseReader* signal);
|
void pulse_reader_stop(PulseReader* signal);
|
||||||
|
|
||||||
|
|
||||||
/** Recevie a sample from ringbuffer
|
/** Recevie a sample from ringbuffer
|
||||||
*
|
*
|
||||||
* Waits for the specified time until a new edge gets detected.
|
* Waits for the specified time until a new edge gets detected.
|
||||||
@@ -98,7 +93,6 @@ void pulse_reader_stop(PulseReader* signal);
|
|||||||
*/
|
*/
|
||||||
uint32_t pulse_reader_receive(PulseReader* signal, int timeout_us);
|
uint32_t pulse_reader_receive(PulseReader* signal, int timeout_us);
|
||||||
|
|
||||||
|
|
||||||
/** Get available samples
|
/** Get available samples
|
||||||
*
|
*
|
||||||
* Get the number of available samples in the ringbuffer
|
* Get the number of available samples in the ringbuffer
|
||||||
@@ -109,7 +103,6 @@ uint32_t pulse_reader_receive(PulseReader* signal, int timeout_us);
|
|||||||
*/
|
*/
|
||||||
uint32_t pulse_reader_samples(PulseReader* signal);
|
uint32_t pulse_reader_samples(PulseReader* signal);
|
||||||
|
|
||||||
|
|
||||||
/** Set timebase
|
/** Set timebase
|
||||||
*
|
*
|
||||||
* Set the timebase to be used when returning pulse duration.
|
* Set the timebase to be used when returning pulse duration.
|
||||||
@@ -119,8 +112,6 @@ uint32_t pulse_reader_samples(PulseReader* signal);
|
|||||||
*/
|
*/
|
||||||
void pulse_reader_set_timebase(PulseReader* signal, PulseReaderUnit unit);
|
void pulse_reader_set_timebase(PulseReader* signal, PulseReaderUnit unit);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Set bit time
|
/** Set bit time
|
||||||
*
|
*
|
||||||
* Set the number of timebase units per bit.
|
* Set the number of timebase units per bit.
|
||||||
@@ -134,7 +125,6 @@ void pulse_reader_set_timebase(PulseReader* signal, PulseReaderUnit unit);
|
|||||||
*/
|
*/
|
||||||
void pulse_reader_set_bittime(PulseReader* signal, uint32_t bit_time);
|
void pulse_reader_set_bittime(PulseReader* signal, uint32_t bit_time);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user