Merge remote-tracking branch 'origin/dev' into release-candidate
This commit is contained in:
commit
96d97af4e6
17
.github/workflows/build.yml
vendored
17
.github/workflows/build.yml
vendored
@ -123,18 +123,11 @@ jobs:
|
||||
- name: 'Upload artifacts to update server'
|
||||
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||
run: |
|
||||
mkdir -p ~/.ssh
|
||||
ssh-keyscan -p ${{ secrets.RSYNC_DEPLOY_PORT }} -H ${{ secrets.RSYNC_DEPLOY_HOST }} > ~/.ssh/known_hosts
|
||||
echo "${{ secrets.RSYNC_DEPLOY_KEY }}" > deploy_key;
|
||||
chmod 600 ./deploy_key;
|
||||
rsync -avzP --delete --mkpath \
|
||||
-e 'ssh -p ${{ secrets.RSYNC_DEPLOY_PORT }} -i ./deploy_key' \
|
||||
artifacts/ ${{ secrets.RSYNC_DEPLOY_USER }}@${{ secrets.RSYNC_DEPLOY_HOST }}:"${{ secrets.RSYNC_DEPLOY_BASE_PATH }}${BRANCH_NAME}/";
|
||||
rm ./deploy_key;
|
||||
|
||||
- name: 'Trigger update server reindex'
|
||||
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||
run: curl -X POST -F 'key=${{ secrets.REINDEX_KEY }}' ${{ secrets.REINDEX_URL }}
|
||||
FILES=$(for CUR in $(ls artifacts/); do echo "-F files=@artifacts/$CUR"; done)
|
||||
curl --fail -L -H "Token: ${{ secrets.INDEXER_TOKEN }}" \
|
||||
-F "branch=${BRANCH_NAME}" \
|
||||
${FILES[@]} \
|
||||
"${{ secrets.INDEXER_URL }}"/firmware/uploadfiles
|
||||
|
||||
- name: 'Find Previous Comment'
|
||||
if: ${{ !github.event.pull_request.head.repo.fork && github.event.pull_request }}
|
||||
|
||||
3
.github/workflows/reindex.yml
vendored
3
.github/workflows/reindex.yml
vendored
@ -11,4 +11,5 @@ jobs:
|
||||
steps:
|
||||
- name: Trigger reindex
|
||||
run: |
|
||||
curl -X POST -F 'key=${{ secrets.REINDEX_KEY }}' ${{ secrets.REINDEX_URL }}
|
||||
curl --fail -L -H "Token: ${{ secrets.INDEXER_TOKEN }}" \
|
||||
"${{ secrets.INDEXER_URL }}"/firmware/reindex
|
||||
|
||||
22
.gitignore
vendored
22
.gitignore
vendored
@ -30,27 +30,25 @@ bindings/
|
||||
.mxproject
|
||||
Brewfile.lock.json
|
||||
|
||||
# Visual Studio Code
|
||||
/.vscode/
|
||||
|
||||
# Kate
|
||||
.kateproject
|
||||
.kateconfig
|
||||
|
||||
# legendary cmake's
|
||||
build
|
||||
CMakeLists.txt
|
||||
|
||||
# bundle output
|
||||
dist
|
||||
|
||||
# kde
|
||||
.directory
|
||||
|
||||
# SCons
|
||||
.sconsign.dblite
|
||||
|
||||
|
||||
# Visual Studio Code
|
||||
/.vscode
|
||||
|
||||
# bundle output
|
||||
/dist
|
||||
|
||||
# SCons build dir
|
||||
build/
|
||||
/build
|
||||
|
||||
# Toolchain
|
||||
/toolchain
|
||||
@ -64,3 +62,5 @@ PVS-Studio.log
|
||||
*.PVS-Studio.*
|
||||
|
||||
.gdbinit
|
||||
|
||||
/fbt_options_local.py
|
||||
@ -14,9 +14,7 @@ void lfrfid_debug_scene_tune_on_enter(void* context) {
|
||||
furi_hal_rfid_comp_set_callback(comparator_trigger_callback, app);
|
||||
furi_hal_rfid_comp_start();
|
||||
|
||||
furi_hal_rfid_pins_read();
|
||||
furi_hal_rfid_tim_read(125000, 0.5);
|
||||
furi_hal_rfid_tim_read_start();
|
||||
furi_hal_rfid_tim_read_start(125000, 0.5);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidDebugViewTune);
|
||||
}
|
||||
@ -43,6 +41,5 @@ void lfrfid_debug_scene_tune_on_exit(void* context) {
|
||||
|
||||
furi_hal_gpio_init_simple(&gpio_ext_pa7, GpioModeAnalog);
|
||||
furi_hal_rfid_tim_read_stop();
|
||||
furi_hal_rfid_tim_reset();
|
||||
furi_hal_rfid_pins_reset();
|
||||
}
|
||||
|
||||
175
applications/external/nfc_magic/lib/magic/classic_gen1.c
vendored
Normal file
175
applications/external/nfc_magic/lib/magic/classic_gen1.c
vendored
Normal file
@ -0,0 +1,175 @@
|
||||
#include "classic_gen1.h"
|
||||
|
||||
#include <furi_hal_nfc.h>
|
||||
|
||||
#define TAG "Magic"
|
||||
|
||||
#define MAGIC_CMD_WUPA (0x40)
|
||||
#define MAGIC_CMD_WIPE (0x41)
|
||||
#define MAGIC_CMD_ACCESS (0x43)
|
||||
|
||||
#define MAGIC_MIFARE_READ_CMD (0x30)
|
||||
#define MAGIC_MIFARE_WRITE_CMD (0xA0)
|
||||
|
||||
#define MAGIC_ACK (0x0A)
|
||||
|
||||
#define MAGIC_BUFFER_SIZE (32)
|
||||
|
||||
bool magic_gen1_wupa() {
|
||||
bool magic_activated = false;
|
||||
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint16_t rx_len = 0;
|
||||
FuriHalNfcReturn ret = 0;
|
||||
|
||||
do {
|
||||
// Start communication
|
||||
tx_data[0] = MAGIC_CMD_WUPA;
|
||||
ret = furi_hal_nfc_ll_txrx_bits(
|
||||
tx_data,
|
||||
7,
|
||||
rx_data,
|
||||
sizeof(rx_data),
|
||||
&rx_len,
|
||||
FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL | FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON |
|
||||
FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP,
|
||||
furi_hal_nfc_ll_ms2fc(20));
|
||||
if(ret != FuriHalNfcReturnIncompleteByte) break;
|
||||
if(rx_len != 4) break;
|
||||
if(rx_data[0] != MAGIC_ACK) break;
|
||||
magic_activated = true;
|
||||
} while(false);
|
||||
|
||||
return magic_activated;
|
||||
}
|
||||
|
||||
bool magic_gen1_data_access_cmd() {
|
||||
bool write_cmd_success = false;
|
||||
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint16_t rx_len = 0;
|
||||
FuriHalNfcReturn ret = 0;
|
||||
|
||||
do {
|
||||
tx_data[0] = MAGIC_CMD_ACCESS;
|
||||
ret = furi_hal_nfc_ll_txrx_bits(
|
||||
tx_data,
|
||||
8,
|
||||
rx_data,
|
||||
sizeof(rx_data),
|
||||
&rx_len,
|
||||
FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL | FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON |
|
||||
FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP,
|
||||
furi_hal_nfc_ll_ms2fc(20));
|
||||
if(ret != FuriHalNfcReturnIncompleteByte) break;
|
||||
if(rx_len != 4) break;
|
||||
if(rx_data[0] != MAGIC_ACK) break;
|
||||
|
||||
write_cmd_success = true;
|
||||
} while(false);
|
||||
|
||||
return write_cmd_success;
|
||||
}
|
||||
|
||||
bool magic_gen1_read_block(uint8_t block_num, MfClassicBlock* data) {
|
||||
furi_assert(data);
|
||||
|
||||
bool read_success = false;
|
||||
|
||||
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint16_t rx_len = 0;
|
||||
FuriHalNfcReturn ret = 0;
|
||||
|
||||
do {
|
||||
tx_data[0] = MAGIC_MIFARE_READ_CMD;
|
||||
tx_data[1] = block_num;
|
||||
ret = furi_hal_nfc_ll_txrx_bits(
|
||||
tx_data,
|
||||
2 * 8,
|
||||
rx_data,
|
||||
sizeof(rx_data),
|
||||
&rx_len,
|
||||
FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON,
|
||||
furi_hal_nfc_ll_ms2fc(20));
|
||||
|
||||
if(ret != FuriHalNfcReturnOk) break;
|
||||
if(rx_len != 16 * 8) break;
|
||||
memcpy(data->value, rx_data, sizeof(data->value));
|
||||
read_success = true;
|
||||
} while(false);
|
||||
|
||||
return read_success;
|
||||
}
|
||||
|
||||
bool magic_gen1_write_blk(uint8_t block_num, MfClassicBlock* data) {
|
||||
furi_assert(data);
|
||||
|
||||
bool write_success = false;
|
||||
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint16_t rx_len = 0;
|
||||
FuriHalNfcReturn ret = 0;
|
||||
|
||||
do {
|
||||
tx_data[0] = MAGIC_MIFARE_WRITE_CMD;
|
||||
tx_data[1] = block_num;
|
||||
ret = furi_hal_nfc_ll_txrx_bits(
|
||||
tx_data,
|
||||
2 * 8,
|
||||
rx_data,
|
||||
sizeof(rx_data),
|
||||
&rx_len,
|
||||
FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP,
|
||||
furi_hal_nfc_ll_ms2fc(20));
|
||||
if(ret != FuriHalNfcReturnIncompleteByte) break;
|
||||
if(rx_len != 4) break;
|
||||
if(rx_data[0] != MAGIC_ACK) break;
|
||||
|
||||
memcpy(tx_data, data->value, sizeof(data->value));
|
||||
ret = furi_hal_nfc_ll_txrx_bits(
|
||||
tx_data,
|
||||
16 * 8,
|
||||
rx_data,
|
||||
sizeof(rx_data),
|
||||
&rx_len,
|
||||
FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP,
|
||||
furi_hal_nfc_ll_ms2fc(20));
|
||||
if(ret != FuriHalNfcReturnIncompleteByte) break;
|
||||
if(rx_len != 4) break;
|
||||
if(rx_data[0] != MAGIC_ACK) break;
|
||||
|
||||
write_success = true;
|
||||
} while(false);
|
||||
|
||||
return write_success;
|
||||
}
|
||||
|
||||
bool magic_gen1_wipe() {
|
||||
bool wipe_success = false;
|
||||
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint16_t rx_len = 0;
|
||||
FuriHalNfcReturn ret = 0;
|
||||
|
||||
do {
|
||||
tx_data[0] = MAGIC_CMD_WIPE;
|
||||
ret = furi_hal_nfc_ll_txrx_bits(
|
||||
tx_data,
|
||||
8,
|
||||
rx_data,
|
||||
sizeof(rx_data),
|
||||
&rx_len,
|
||||
FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL | FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON |
|
||||
FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP,
|
||||
furi_hal_nfc_ll_ms2fc(2000));
|
||||
|
||||
if(ret != FuriHalNfcReturnIncompleteByte) break;
|
||||
if(rx_len != 4) break;
|
||||
if(rx_data[0] != MAGIC_ACK) break;
|
||||
|
||||
wipe_success = true;
|
||||
} while(false);
|
||||
|
||||
return wipe_success;
|
||||
}
|
||||
13
applications/external/nfc_magic/lib/magic/classic_gen1.h
vendored
Normal file
13
applications/external/nfc_magic/lib/magic/classic_gen1.h
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <lib/nfc/protocols/mifare_classic.h>
|
||||
|
||||
bool magic_gen1_wupa();
|
||||
|
||||
bool magic_gen1_read_block(uint8_t block_num, MfClassicBlock* data);
|
||||
|
||||
bool magic_gen1_data_access_cmd();
|
||||
|
||||
bool magic_gen1_write_blk(uint8_t block_num, MfClassicBlock* data);
|
||||
|
||||
bool magic_gen1_wipe();
|
||||
33
applications/external/nfc_magic/lib/magic/common.c
vendored
Normal file
33
applications/external/nfc_magic/lib/magic/common.c
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
#include "common.h"
|
||||
|
||||
#include <furi_hal_nfc.h>
|
||||
|
||||
#define REQA (0x26)
|
||||
#define CL1_PREFIX (0x93)
|
||||
#define SELECT (0x70)
|
||||
|
||||
#define MAGIC_BUFFER_SIZE (32)
|
||||
|
||||
bool magic_activate() {
|
||||
FuriHalNfcReturn ret = 0;
|
||||
|
||||
// Setup nfc poller
|
||||
furi_hal_nfc_exit_sleep();
|
||||
furi_hal_nfc_ll_txrx_on();
|
||||
furi_hal_nfc_ll_poll();
|
||||
ret = furi_hal_nfc_ll_set_mode(
|
||||
FuriHalNfcModePollNfca, FuriHalNfcBitrate106, FuriHalNfcBitrate106);
|
||||
if(ret != FuriHalNfcReturnOk) return false;
|
||||
|
||||
furi_hal_nfc_ll_set_fdt_listen(FURI_HAL_NFC_LL_FDT_LISTEN_NFCA_POLLER);
|
||||
furi_hal_nfc_ll_set_fdt_poll(FURI_HAL_NFC_LL_FDT_POLL_NFCA_POLLER);
|
||||
furi_hal_nfc_ll_set_error_handling(FuriHalNfcErrorHandlingNfc);
|
||||
furi_hal_nfc_ll_set_guard_time(FURI_HAL_NFC_LL_GT_NFCA);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void magic_deactivate() {
|
||||
furi_hal_nfc_ll_txrx_off();
|
||||
furi_hal_nfc_sleep();
|
||||
}
|
||||
19
applications/external/nfc_magic/lib/magic/common.h
vendored
Normal file
19
applications/external/nfc_magic/lib/magic/common.h
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef enum {
|
||||
MagicTypeClassicGen1,
|
||||
MagicTypeClassicDirectWrite,
|
||||
MagicTypeClassicAPDU,
|
||||
MagicTypeUltralightGen1,
|
||||
MagicTypeUltralightDirectWrite,
|
||||
MagicTypeUltralightC_Gen1,
|
||||
MagicTypeUltralightC_DirectWrite,
|
||||
MagicTypeGen4,
|
||||
} MagicType;
|
||||
|
||||
bool magic_activate();
|
||||
|
||||
void magic_deactivate();
|
||||
199
applications/external/nfc_magic/lib/magic/gen4.c
vendored
Normal file
199
applications/external/nfc_magic/lib/magic/gen4.c
vendored
Normal file
@ -0,0 +1,199 @@
|
||||
#include "gen4.h"
|
||||
|
||||
#include <furi_hal_nfc.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define TAG "Magic"
|
||||
|
||||
#define MAGIC_CMD_PREFIX (0xCF)
|
||||
|
||||
#define MAGIC_CMD_GET_CFG (0xC6)
|
||||
#define MAGIC_CMD_WRITE (0xCD)
|
||||
#define MAGIC_CMD_READ (0xCE)
|
||||
#define MAGIC_CMD_SET_CFG (0xF0)
|
||||
#define MAGIC_CMD_FUSE_CFG (0xF1)
|
||||
#define MAGIC_CMD_SET_PWD (0xFE)
|
||||
|
||||
#define MAGIC_BUFFER_SIZE (40)
|
||||
|
||||
const uint8_t MAGIC_DEFAULT_CONFIG[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x09, 0x78, 0x00, 0x91, 0x02, 0xDA, 0xBC, 0x19, 0x10, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x04, 0x00, 0x08, 0x00
|
||||
};
|
||||
|
||||
const uint8_t MAGIC_DEFAULT_BLOCK0[] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
const uint8_t MAGIC_EMPTY_BLOCK[16] = { 0 };
|
||||
|
||||
const uint8_t MAGIC_DEFAULT_SECTOR_TRAILER[] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
||||
};
|
||||
|
||||
static bool magic_gen4_is_block_num_trailer(uint8_t n) {
|
||||
n++;
|
||||
if (n < 32 * 4) {
|
||||
return (n % 4 == 0);
|
||||
}
|
||||
|
||||
return (n % 16 == 0);
|
||||
}
|
||||
|
||||
bool magic_gen4_get_cfg(uint32_t pwd, uint8_t* config) {
|
||||
bool is_valid_config_len = false;
|
||||
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint16_t rx_len = 0;
|
||||
FuriHalNfcReturn ret = 0;
|
||||
|
||||
do {
|
||||
// Start communication
|
||||
tx_data[0] = MAGIC_CMD_PREFIX;
|
||||
tx_data[1] = (uint8_t)(pwd >> 24);
|
||||
tx_data[2] = (uint8_t)(pwd >> 16);
|
||||
tx_data[3] = (uint8_t)(pwd >> 8);
|
||||
tx_data[4] = (uint8_t)pwd;
|
||||
tx_data[5] = MAGIC_CMD_GET_CFG;
|
||||
ret = furi_hal_nfc_ll_txrx(
|
||||
tx_data,
|
||||
6,
|
||||
rx_data,
|
||||
sizeof(rx_data),
|
||||
&rx_len,
|
||||
FURI_HAL_NFC_TXRX_DEFAULT,
|
||||
furi_hal_nfc_ll_ms2fc(20));
|
||||
if(ret != FuriHalNfcReturnOk) break;
|
||||
if(rx_len != 30 && rx_len != 32) break;
|
||||
memcpy(config, rx_data, rx_len);
|
||||
is_valid_config_len = true;
|
||||
} while(false);
|
||||
|
||||
return is_valid_config_len;
|
||||
}
|
||||
|
||||
bool magic_gen4_set_cfg(uint32_t pwd, const uint8_t* config, uint8_t config_length, bool fuse) {
|
||||
bool write_success = false;
|
||||
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint16_t rx_len = 0;
|
||||
FuriHalNfcReturn ret = 0;
|
||||
|
||||
do {
|
||||
// Start communication
|
||||
tx_data[0] = MAGIC_CMD_PREFIX;
|
||||
tx_data[1] = (uint8_t)(pwd >> 24);
|
||||
tx_data[2] = (uint8_t)(pwd >> 16);
|
||||
tx_data[3] = (uint8_t)(pwd >> 8);
|
||||
tx_data[4] = (uint8_t)pwd;
|
||||
tx_data[5] = fuse ? MAGIC_CMD_FUSE_CFG : MAGIC_CMD_SET_CFG;
|
||||
memcpy(tx_data + 6, config, config_length);
|
||||
ret = furi_hal_nfc_ll_txrx(
|
||||
tx_data,
|
||||
6 + config_length,
|
||||
rx_data,
|
||||
sizeof(rx_data),
|
||||
&rx_len,
|
||||
FURI_HAL_NFC_TXRX_DEFAULT,
|
||||
furi_hal_nfc_ll_ms2fc(20));
|
||||
if(ret != FuriHalNfcReturnOk) break;
|
||||
if(rx_len != 2) break;
|
||||
write_success = true;
|
||||
} while(false);
|
||||
|
||||
return write_success;
|
||||
}
|
||||
|
||||
bool magic_gen4_set_pwd(uint32_t old_pwd, uint32_t new_pwd) {
|
||||
bool change_success = false;
|
||||
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint16_t rx_len = 0;
|
||||
FuriHalNfcReturn ret = 0;
|
||||
|
||||
do {
|
||||
// Start communication
|
||||
tx_data[0] = MAGIC_CMD_PREFIX;
|
||||
tx_data[1] = (uint8_t)(old_pwd >> 24);
|
||||
tx_data[2] = (uint8_t)(old_pwd >> 16);
|
||||
tx_data[3] = (uint8_t)(old_pwd >> 8);
|
||||
tx_data[4] = (uint8_t)old_pwd;
|
||||
tx_data[5] = MAGIC_CMD_SET_PWD;
|
||||
tx_data[6] = (uint8_t)(new_pwd >> 24);
|
||||
tx_data[7] = (uint8_t)(new_pwd >> 16);
|
||||
tx_data[8] = (uint8_t)(new_pwd >> 8);
|
||||
tx_data[9] = (uint8_t)new_pwd;
|
||||
ret = furi_hal_nfc_ll_txrx(
|
||||
tx_data,
|
||||
10,
|
||||
rx_data,
|
||||
sizeof(rx_data),
|
||||
&rx_len,
|
||||
FURI_HAL_NFC_TXRX_DEFAULT,
|
||||
furi_hal_nfc_ll_ms2fc(20));
|
||||
FURI_LOG_I(TAG, "ret %d, len %d", ret, rx_len);
|
||||
if(ret != FuriHalNfcReturnOk) break;
|
||||
if(rx_len != 2) break;
|
||||
change_success = true;
|
||||
} while(false);
|
||||
|
||||
return change_success;
|
||||
}
|
||||
|
||||
bool magic_gen4_write_blk(uint32_t pwd, uint8_t block_num, const uint8_t* data) {
|
||||
bool write_success = false;
|
||||
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint16_t rx_len = 0;
|
||||
FuriHalNfcReturn ret = 0;
|
||||
|
||||
do {
|
||||
// Start communication
|
||||
tx_data[0] = MAGIC_CMD_PREFIX;
|
||||
tx_data[1] = (uint8_t)(pwd >> 24);
|
||||
tx_data[2] = (uint8_t)(pwd >> 16);
|
||||
tx_data[3] = (uint8_t)(pwd >> 8);
|
||||
tx_data[4] = (uint8_t)pwd;
|
||||
tx_data[5] = MAGIC_CMD_WRITE;
|
||||
tx_data[6] = block_num;
|
||||
memcpy(tx_data + 7, data, 16);
|
||||
ret = furi_hal_nfc_ll_txrx(
|
||||
tx_data,
|
||||
23,
|
||||
rx_data,
|
||||
sizeof(rx_data),
|
||||
&rx_len,
|
||||
FURI_HAL_NFC_TXRX_DEFAULT,
|
||||
furi_hal_nfc_ll_ms2fc(200));
|
||||
if(ret != FuriHalNfcReturnOk) break;
|
||||
if(rx_len != 2) break;
|
||||
write_success = true;
|
||||
} while(false);
|
||||
|
||||
return write_success;
|
||||
}
|
||||
|
||||
bool magic_gen4_wipe(uint32_t pwd) {
|
||||
if(!magic_gen4_set_cfg(pwd, MAGIC_DEFAULT_CONFIG, sizeof(MAGIC_DEFAULT_CONFIG), false)) {
|
||||
FURI_LOG_E(TAG, "Set config failed");
|
||||
return false;
|
||||
}
|
||||
if(!magic_gen4_write_blk(pwd, 0, MAGIC_DEFAULT_BLOCK0)) {
|
||||
FURI_LOG_E(TAG, "Block 0 write failed");
|
||||
return false;
|
||||
}
|
||||
for(size_t i = 1; i < 64; i++) {
|
||||
const uint8_t* block = magic_gen4_is_block_num_trailer(i) ? MAGIC_DEFAULT_SECTOR_TRAILER : MAGIC_EMPTY_BLOCK;
|
||||
if(!magic_gen4_write_blk(pwd, i, block)) {
|
||||
FURI_LOG_E(TAG, "Block %d write failed", i);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for(size_t i = 65; i < 256; i++) {
|
||||
if(!magic_gen4_write_blk(pwd, i, MAGIC_EMPTY_BLOCK)) {
|
||||
FURI_LOG_E(TAG, "Block %d write failed", i);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
48
applications/external/nfc_magic/lib/magic/gen4.h
vendored
Normal file
48
applications/external/nfc_magic/lib/magic/gen4.h
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include <lib/nfc/protocols/mifare_classic.h>
|
||||
|
||||
#define MAGIC_GEN4_DEFAULT_PWD 0x00000000
|
||||
#define MAGIC_GEN4_CONFIG_LEN 32
|
||||
|
||||
#define NFCID1_SINGLE_SIZE 4
|
||||
#define NFCID1_DOUBLE_SIZE 7
|
||||
#define NFCID1_TRIPLE_SIZE 10
|
||||
|
||||
typedef enum {
|
||||
MagicGen4UIDLengthSingle = 0x00,
|
||||
MagicGen4UIDLengthDouble = 0x01,
|
||||
MagicGen4UIDLengthTriple = 0x02
|
||||
} MagicGen4UIDLength;
|
||||
|
||||
typedef enum {
|
||||
MagicGen4UltralightModeUL_EV1 = 0x00,
|
||||
MagicGen4UltralightModeNTAG = 0x01,
|
||||
MagicGen4UltralightModeUL_C = 0x02,
|
||||
MagicGen4UltralightModeUL = 0x03
|
||||
} MagicGen4UltralightMode;
|
||||
|
||||
typedef enum {
|
||||
// for writing original (shadow) data
|
||||
MagicGen4ShadowModePreWrite = 0x00,
|
||||
// written data can be read once before restored to original
|
||||
MagicGen4ShadowModeRestore = 0x01,
|
||||
// written data is discarded
|
||||
MagicGen4ShadowModeIgnore = 0x02,
|
||||
// apparently for UL?
|
||||
MagicGen4ShadowModeHighSpeedIgnore = 0x03
|
||||
} MagicGen4ShadowMode;
|
||||
|
||||
bool magic_gen4_get_cfg(uint32_t pwd, uint8_t* config);
|
||||
|
||||
bool magic_gen4_set_cfg(uint32_t pwd, const uint8_t* config, uint8_t config_length, bool fuse);
|
||||
|
||||
bool magic_gen4_set_pwd(uint32_t old_pwd, uint32_t new_pwd);
|
||||
|
||||
bool magic_gen4_read_blk(uint32_t pwd, uint8_t block_num, uint8_t* data);
|
||||
|
||||
bool magic_gen4_write_blk(uint32_t pwd, uint8_t block_num, const uint8_t* data);
|
||||
|
||||
bool magic_gen4_wipe(uint32_t pwd);
|
||||
|
||||
void magic_gen4_deactivate();
|
||||
@ -1,4 +1,4 @@
|
||||
#include "magic.h"
|
||||
#include "classic_gen1.h"
|
||||
|
||||
#include <furi_hal_nfc.h>
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
|
||||
#define MAGIC_BUFFER_SIZE (32)
|
||||
|
||||
bool magic_wupa() {
|
||||
bool magic_gen1_wupa() {
|
||||
bool magic_activated = false;
|
||||
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
@ -23,19 +23,6 @@ bool magic_wupa() {
|
||||
FuriHalNfcReturn ret = 0;
|
||||
|
||||
do {
|
||||
// Setup nfc poller
|
||||
furi_hal_nfc_exit_sleep();
|
||||
furi_hal_nfc_ll_txrx_on();
|
||||
furi_hal_nfc_ll_poll();
|
||||
ret = furi_hal_nfc_ll_set_mode(
|
||||
FuriHalNfcModePollNfca, FuriHalNfcBitrate106, FuriHalNfcBitrate106);
|
||||
if(ret != FuriHalNfcReturnOk) break;
|
||||
|
||||
furi_hal_nfc_ll_set_fdt_listen(FURI_HAL_NFC_LL_FDT_LISTEN_NFCA_POLLER);
|
||||
furi_hal_nfc_ll_set_fdt_poll(FURI_HAL_NFC_LL_FDT_POLL_NFCA_POLLER);
|
||||
furi_hal_nfc_ll_set_error_handling(FuriHalNfcErrorHandlingNfc);
|
||||
furi_hal_nfc_ll_set_guard_time(FURI_HAL_NFC_LL_GT_NFCA);
|
||||
|
||||
// Start communication
|
||||
tx_data[0] = MAGIC_CMD_WUPA;
|
||||
ret = furi_hal_nfc_ll_txrx_bits(
|
||||
@ -53,15 +40,10 @@ bool magic_wupa() {
|
||||
magic_activated = true;
|
||||
} while(false);
|
||||
|
||||
if(!magic_activated) {
|
||||
furi_hal_nfc_ll_txrx_off();
|
||||
furi_hal_nfc_start_sleep();
|
||||
}
|
||||
|
||||
return magic_activated;
|
||||
}
|
||||
|
||||
bool magic_data_access_cmd() {
|
||||
bool magic_gen1_data_access_cmd() {
|
||||
bool write_cmd_success = false;
|
||||
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
@ -86,15 +68,10 @@ bool magic_data_access_cmd() {
|
||||
write_cmd_success = true;
|
||||
} while(false);
|
||||
|
||||
if(!write_cmd_success) {
|
||||
furi_hal_nfc_ll_txrx_off();
|
||||
furi_hal_nfc_start_sleep();
|
||||
}
|
||||
|
||||
return write_cmd_success;
|
||||
}
|
||||
|
||||
bool magic_read_block(uint8_t block_num, MfClassicBlock* data) {
|
||||
bool magic_gen1_read_block(uint8_t block_num, MfClassicBlock* data) {
|
||||
furi_assert(data);
|
||||
|
||||
bool read_success = false;
|
||||
@ -122,15 +99,10 @@ bool magic_read_block(uint8_t block_num, MfClassicBlock* data) {
|
||||
read_success = true;
|
||||
} while(false);
|
||||
|
||||
if(!read_success) {
|
||||
furi_hal_nfc_ll_txrx_off();
|
||||
furi_hal_nfc_start_sleep();
|
||||
}
|
||||
|
||||
return read_success;
|
||||
}
|
||||
|
||||
bool magic_write_blk(uint8_t block_num, MfClassicBlock* data) {
|
||||
bool magic_gen1_write_blk(uint8_t block_num, MfClassicBlock* data) {
|
||||
furi_assert(data);
|
||||
|
||||
bool write_success = false;
|
||||
@ -170,15 +142,10 @@ bool magic_write_blk(uint8_t block_num, MfClassicBlock* data) {
|
||||
write_success = true;
|
||||
} while(false);
|
||||
|
||||
if(!write_success) {
|
||||
furi_hal_nfc_ll_txrx_off();
|
||||
furi_hal_nfc_start_sleep();
|
||||
}
|
||||
|
||||
return write_success;
|
||||
}
|
||||
|
||||
bool magic_wipe() {
|
||||
bool magic_gen1_wipe() {
|
||||
bool wipe_success = false;
|
||||
uint8_t tx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
uint8_t rx_data[MAGIC_BUFFER_SIZE] = {};
|
||||
@ -206,8 +173,3 @@ bool magic_wipe() {
|
||||
|
||||
return wipe_success;
|
||||
}
|
||||
|
||||
void magic_deactivate() {
|
||||
furi_hal_nfc_ll_txrx_off();
|
||||
furi_hal_nfc_sleep();
|
||||
}
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <lib/nfc/protocols/mifare_classic.h>
|
||||
|
||||
bool magic_wupa();
|
||||
|
||||
bool magic_read_block(uint8_t block_num, MfClassicBlock* data);
|
||||
|
||||
bool magic_data_access_cmd();
|
||||
|
||||
bool magic_write_blk(uint8_t block_num, MfClassicBlock* data);
|
||||
|
||||
bool magic_wipe();
|
||||
|
||||
void magic_deactivate();
|
||||
23
applications/external/nfc_magic/lib/magic/types.c
vendored
Normal file
23
applications/external/nfc_magic/lib/magic/types.c
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
#include "types.h"
|
||||
|
||||
const char* nfc_magic_type(MagicType type) {
|
||||
if(type == MagicTypeClassicGen1) {
|
||||
return "Classic Gen 1A/B";
|
||||
} else if(type == MagicTypeClassicDirectWrite) {
|
||||
return "Classic DirectWrite";
|
||||
} else if(type == MagicTypeClassicAPDU) {
|
||||
return "Classic APDU";
|
||||
} else if(type == MagicTypeUltralightGen1) {
|
||||
return "Ultralight Gen 1";
|
||||
} else if(type == MagicTypeUltralightDirectWrite) {
|
||||
return "Ultralight DirectWrite";
|
||||
} else if(type == MagicTypeUltralightC_Gen1) {
|
||||
return "Ultralight-C Gen 1";
|
||||
} else if(type == MagicTypeUltralightC_DirectWrite) {
|
||||
return "Ultralight-C DirectWrite";
|
||||
} else if(type == MagicTypeGen4) {
|
||||
return "Gen 4 GTU";
|
||||
} else {
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
5
applications/external/nfc_magic/lib/magic/types.h
vendored
Normal file
5
applications/external/nfc_magic/lib/magic/types.h
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
|
||||
const char* nfc_magic_type(MagicType type);
|
||||
22
applications/external/nfc_magic/nfc_magic.c
vendored
22
applications/external/nfc_magic/nfc_magic.c
vendored
@ -48,8 +48,9 @@ NfcMagic* nfc_magic_alloc() {
|
||||
nfc_magic->view_dispatcher, nfc_magic_tick_event_callback, 100);
|
||||
|
||||
// Nfc device
|
||||
nfc_magic->nfc_dev = nfc_device_alloc();
|
||||
furi_string_set(nfc_magic->nfc_dev->folder, NFC_APP_FOLDER);
|
||||
nfc_magic->dev = malloc(sizeof(NfcMagicDevice));
|
||||
nfc_magic->source_dev = nfc_device_alloc();
|
||||
furi_string_set(nfc_magic->source_dev->folder, NFC_APP_FOLDER);
|
||||
|
||||
// Open GUI record
|
||||
nfc_magic->gui = furi_record_open(RECORD_GUI);
|
||||
@ -81,6 +82,13 @@ NfcMagic* nfc_magic_alloc() {
|
||||
NfcMagicViewTextInput,
|
||||
text_input_get_view(nfc_magic->text_input));
|
||||
|
||||
// Byte Input
|
||||
nfc_magic->byte_input = byte_input_alloc();
|
||||
view_dispatcher_add_view(
|
||||
nfc_magic->view_dispatcher,
|
||||
NfcMagicViewByteInput,
|
||||
byte_input_get_view(nfc_magic->byte_input));
|
||||
|
||||
// Custom Widget
|
||||
nfc_magic->widget = widget_alloc();
|
||||
view_dispatcher_add_view(
|
||||
@ -93,7 +101,8 @@ void nfc_magic_free(NfcMagic* nfc_magic) {
|
||||
furi_assert(nfc_magic);
|
||||
|
||||
// Nfc device
|
||||
nfc_device_free(nfc_magic->nfc_dev);
|
||||
free(nfc_magic->dev);
|
||||
nfc_device_free(nfc_magic->source_dev);
|
||||
|
||||
// Submenu
|
||||
view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewMenu);
|
||||
@ -107,10 +116,14 @@ void nfc_magic_free(NfcMagic* nfc_magic) {
|
||||
view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewLoading);
|
||||
loading_free(nfc_magic->loading);
|
||||
|
||||
// TextInput
|
||||
// Text Input
|
||||
view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewTextInput);
|
||||
text_input_free(nfc_magic->text_input);
|
||||
|
||||
// Byte Input
|
||||
view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewByteInput);
|
||||
byte_input_free(nfc_magic->byte_input);
|
||||
|
||||
// Custom Widget
|
||||
view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewWidget);
|
||||
widget_free(nfc_magic->widget);
|
||||
@ -164,6 +177,7 @@ int32_t nfc_magic_app(void* p) {
|
||||
|
||||
view_dispatcher_run(nfc_magic->view_dispatcher);
|
||||
|
||||
magic_deactivate();
|
||||
nfc_magic_free(nfc_magic);
|
||||
|
||||
return 0;
|
||||
|
||||
2
applications/external/nfc_magic/nfc_magic.h
vendored
2
applications/external/nfc_magic/nfc_magic.h
vendored
@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
typedef struct NfcMagicDevice NfcMagicDevice;
|
||||
|
||||
typedef struct NfcMagic NfcMagic;
|
||||
|
||||
20
applications/external/nfc_magic/nfc_magic_i.h
vendored
20
applications/external/nfc_magic/nfc_magic_i.h
vendored
@ -3,7 +3,10 @@
|
||||
#include "nfc_magic.h"
|
||||
#include "nfc_magic_worker.h"
|
||||
|
||||
#include "lib/magic/magic.h"
|
||||
#include "lib/magic/common.h"
|
||||
#include "lib/magic/types.h"
|
||||
#include "lib/magic/classic_gen1.h"
|
||||
#include "lib/magic/gen4.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include <gui/gui.h>
|
||||
@ -15,6 +18,7 @@
|
||||
#include <gui/modules/popup.h>
|
||||
#include <gui/modules/loading.h>
|
||||
#include <gui/modules/text_input.h>
|
||||
#include <gui/modules/byte_input.h>
|
||||
#include <gui/modules/widget.h>
|
||||
|
||||
#include <input/input.h>
|
||||
@ -39,14 +43,22 @@ enum NfcMagicCustomEvent {
|
||||
NfcMagicCustomEventTextInputDone,
|
||||
};
|
||||
|
||||
struct NfcMagicDevice {
|
||||
MagicType type;
|
||||
uint32_t cuid;
|
||||
uint32_t password;
|
||||
};
|
||||
|
||||
struct NfcMagic {
|
||||
NfcMagicWorker* worker;
|
||||
ViewDispatcher* view_dispatcher;
|
||||
Gui* gui;
|
||||
NotificationApp* notifications;
|
||||
SceneManager* scene_manager;
|
||||
// NfcMagicDevice* dev;
|
||||
NfcDevice* nfc_dev;
|
||||
struct NfcMagicDevice* dev;
|
||||
NfcDevice* source_dev;
|
||||
|
||||
uint32_t new_password;
|
||||
|
||||
FuriString* text_box_store;
|
||||
|
||||
@ -55,6 +67,7 @@ struct NfcMagic {
|
||||
Popup* popup;
|
||||
Loading* loading;
|
||||
TextInput* text_input;
|
||||
ByteInput* byte_input;
|
||||
Widget* widget;
|
||||
};
|
||||
|
||||
@ -63,6 +76,7 @@ typedef enum {
|
||||
NfcMagicViewPopup,
|
||||
NfcMagicViewLoading,
|
||||
NfcMagicViewTextInput,
|
||||
NfcMagicViewByteInput,
|
||||
NfcMagicViewWidget,
|
||||
} NfcMagicView;
|
||||
|
||||
|
||||
372
applications/external/nfc_magic/nfc_magic_worker.c
vendored
372
applications/external/nfc_magic/nfc_magic_worker.c
vendored
@ -1,6 +1,9 @@
|
||||
#include "nfc_magic_worker_i.h"
|
||||
|
||||
#include "lib/magic/magic.h"
|
||||
#include "nfc_magic_i.h"
|
||||
#include "lib/magic/common.h"
|
||||
#include "lib/magic/classic_gen1.h"
|
||||
#include "lib/magic/gen4.h"
|
||||
|
||||
#define TAG "NfcMagicWorker"
|
||||
|
||||
@ -43,15 +46,20 @@ void nfc_magic_worker_stop(NfcMagicWorker* nfc_magic_worker) {
|
||||
void nfc_magic_worker_start(
|
||||
NfcMagicWorker* nfc_magic_worker,
|
||||
NfcMagicWorkerState state,
|
||||
NfcMagicDevice* magic_dev,
|
||||
NfcDeviceData* dev_data,
|
||||
uint32_t new_password,
|
||||
NfcMagicWorkerCallback callback,
|
||||
void* context) {
|
||||
furi_assert(nfc_magic_worker);
|
||||
furi_assert(magic_dev);
|
||||
furi_assert(dev_data);
|
||||
|
||||
nfc_magic_worker->callback = callback;
|
||||
nfc_magic_worker->context = context;
|
||||
nfc_magic_worker->magic_dev = magic_dev;
|
||||
nfc_magic_worker->dev_data = dev_data;
|
||||
nfc_magic_worker->new_password = new_password;
|
||||
nfc_magic_worker_change_state(nfc_magic_worker, state);
|
||||
furi_thread_start(nfc_magic_worker->thread);
|
||||
}
|
||||
@ -63,6 +71,8 @@ int32_t nfc_magic_worker_task(void* context) {
|
||||
nfc_magic_worker_check(nfc_magic_worker);
|
||||
} else if(nfc_magic_worker->state == NfcMagicWorkerStateWrite) {
|
||||
nfc_magic_worker_write(nfc_magic_worker);
|
||||
} else if(nfc_magic_worker->state == NfcMagicWorkerStateRekey) {
|
||||
nfc_magic_worker_rekey(nfc_magic_worker);
|
||||
} else if(nfc_magic_worker->state == NfcMagicWorkerStateWipe) {
|
||||
nfc_magic_worker_wipe(nfc_magic_worker);
|
||||
}
|
||||
@ -74,59 +84,245 @@ int32_t nfc_magic_worker_task(void* context) {
|
||||
|
||||
void nfc_magic_worker_write(NfcMagicWorker* nfc_magic_worker) {
|
||||
bool card_found_notified = false;
|
||||
bool done = false;
|
||||
FuriHalNfcDevData nfc_data = {};
|
||||
MfClassicData* src_data = &nfc_magic_worker->dev_data->mf_classic_data;
|
||||
NfcMagicDevice* magic_dev = nfc_magic_worker->magic_dev;
|
||||
NfcDeviceData* dev_data = nfc_magic_worker->dev_data;
|
||||
NfcProtocol dev_protocol = dev_data->protocol;
|
||||
|
||||
while(nfc_magic_worker->state == NfcMagicWorkerStateWrite) {
|
||||
if(furi_hal_nfc_detect(&nfc_data, 200)) {
|
||||
if(!card_found_notified) {
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventCardDetected, nfc_magic_worker->context);
|
||||
card_found_notified = true;
|
||||
}
|
||||
furi_hal_nfc_sleep();
|
||||
if(!magic_wupa()) {
|
||||
FURI_LOG_E(TAG, "No card response to WUPA (not a magic card)");
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventWrongCard, nfc_magic_worker->context);
|
||||
break;
|
||||
}
|
||||
furi_hal_nfc_sleep();
|
||||
}
|
||||
if(magic_wupa()) {
|
||||
if(!magic_data_access_cmd()) {
|
||||
FURI_LOG_E(TAG, "No card response to data access command (not a magic card)");
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventWrongCard, nfc_magic_worker->context);
|
||||
break;
|
||||
}
|
||||
for(size_t i = 0; i < 64; i++) {
|
||||
FURI_LOG_D(TAG, "Writing block %d", i);
|
||||
if(!magic_write_blk(i, &src_data->block[i])) {
|
||||
FURI_LOG_E(TAG, "Failed to write %d block", i);
|
||||
nfc_magic_worker->callback(NfcMagicWorkerEventFail, nfc_magic_worker->context);
|
||||
do {
|
||||
if(furi_hal_nfc_detect(&nfc_data, 200)) {
|
||||
if(nfc_data.cuid != magic_dev->cuid) break;
|
||||
if(!card_found_notified) {
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventCardDetected, nfc_magic_worker->context);
|
||||
card_found_notified = true;
|
||||
}
|
||||
furi_hal_nfc_sleep();
|
||||
|
||||
magic_activate();
|
||||
if(magic_dev->type == MagicTypeClassicGen1) {
|
||||
if(dev_protocol != NfcDeviceProtocolMifareClassic) break;
|
||||
MfClassicData* mfc_data = &dev_data->mf_classic_data;
|
||||
|
||||
if(mfc_data->type != MfClassicType1k) break;
|
||||
if(!magic_gen1_wupa()) {
|
||||
FURI_LOG_E(TAG, "Not Magic card");
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventWrongCard, nfc_magic_worker->context);
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
if(!magic_gen1_data_access_cmd()) {
|
||||
FURI_LOG_E(TAG, "Not Magic card");
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventWrongCard, nfc_magic_worker->context);
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
for(size_t i = 0; i < 64; i++) {
|
||||
FURI_LOG_D(TAG, "Writing block %d", i);
|
||||
if(!magic_gen1_write_blk(i, &mfc_data->block[i])) {
|
||||
FURI_LOG_E(TAG, "Failed to write %d block", i);
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventFail, nfc_magic_worker->context);
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
|
||||
done = true;
|
||||
break;
|
||||
} else if(magic_dev->type == MagicTypeGen4) {
|
||||
uint8_t gen4_config[28];
|
||||
uint32_t password = magic_dev->password;
|
||||
|
||||
uint32_t cuid;
|
||||
if(dev_protocol == NfcDeviceProtocolMifareClassic) {
|
||||
gen4_config[0] = 0x00;
|
||||
gen4_config[27] = 0x00;
|
||||
} else if(dev_protocol == NfcDeviceProtocolMifareUl) {
|
||||
MfUltralightData* mf_ul_data = &dev_data->mf_ul_data;
|
||||
gen4_config[0] = 0x01;
|
||||
switch(mf_ul_data->type) {
|
||||
case MfUltralightTypeUL11:
|
||||
case MfUltralightTypeUL21:
|
||||
// UL-C?
|
||||
// UL?
|
||||
default:
|
||||
gen4_config[27] = MagicGen4UltralightModeUL_EV1;
|
||||
break;
|
||||
case MfUltralightTypeNTAG203:
|
||||
case MfUltralightTypeNTAG213:
|
||||
case MfUltralightTypeNTAG215:
|
||||
case MfUltralightTypeNTAG216:
|
||||
case MfUltralightTypeNTAGI2C1K:
|
||||
case MfUltralightTypeNTAGI2C2K:
|
||||
case MfUltralightTypeNTAGI2CPlus1K:
|
||||
case MfUltralightTypeNTAGI2CPlus2K:
|
||||
gen4_config[27] = MagicGen4UltralightModeNTAG;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(dev_data->nfc_data.uid_len == 4) {
|
||||
gen4_config[1] = MagicGen4UIDLengthSingle;
|
||||
} else if(dev_data->nfc_data.uid_len == 7) {
|
||||
gen4_config[1] = MagicGen4UIDLengthDouble;
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Unexpected UID length %d", dev_data->nfc_data.uid_len);
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventFail, nfc_magic_worker->context);
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
|
||||
gen4_config[2] = (uint8_t)(password >> 24);
|
||||
gen4_config[3] = (uint8_t)(password >> 16);
|
||||
gen4_config[4] = (uint8_t)(password >> 8);
|
||||
gen4_config[5] = (uint8_t)password;
|
||||
|
||||
if(dev_protocol == NfcDeviceProtocolMifareUl) {
|
||||
gen4_config[6] = MagicGen4ShadowModeHighSpeedIgnore;
|
||||
} else {
|
||||
gen4_config[6] = MagicGen4ShadowModeIgnore;
|
||||
}
|
||||
gen4_config[7] = 0x00;
|
||||
memset(gen4_config + 8, 0, 16);
|
||||
gen4_config[24] = dev_data->nfc_data.atqa[0];
|
||||
gen4_config[25] = dev_data->nfc_data.atqa[1];
|
||||
gen4_config[26] = dev_data->nfc_data.sak;
|
||||
|
||||
furi_hal_nfc_activate_nfca(200, &cuid);
|
||||
if(!magic_gen4_set_cfg(password, gen4_config, sizeof(gen4_config), false)) {
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventFail, nfc_magic_worker->context);
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
if(dev_protocol == NfcDeviceProtocolMifareClassic) {
|
||||
MfClassicData* mfc_data = &dev_data->mf_classic_data;
|
||||
size_t block_count = 64;
|
||||
if(mfc_data->type == MfClassicType4k) block_count = 256;
|
||||
for(size_t i = 0; i < block_count; i++) {
|
||||
FURI_LOG_D(TAG, "Writing block %d", i);
|
||||
if(!magic_gen4_write_blk(password, i, mfc_data->block[i].value)) {
|
||||
FURI_LOG_E(TAG, "Failed to write %d block", i);
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventFail, nfc_magic_worker->context);
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if(dev_protocol == NfcDeviceProtocolMifareUl) {
|
||||
MfUltralightData* mf_ul_data = &dev_data->mf_ul_data;
|
||||
for(size_t i = 0; (i * 4) < mf_ul_data->data_read; i++) {
|
||||
size_t data_offset = i * 4;
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
"Writing page %zu (%zu/%u)",
|
||||
i,
|
||||
data_offset,
|
||||
mf_ul_data->data_read);
|
||||
uint8_t* block = mf_ul_data->data + data_offset;
|
||||
if(!magic_gen4_write_blk(password, i, block)) {
|
||||
FURI_LOG_E(TAG, "Failed to write %zu page", i);
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventFail, nfc_magic_worker->context);
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t buffer[16] = {0};
|
||||
|
||||
for(size_t i = 0; i < 8; i++) {
|
||||
memcpy(buffer, &mf_ul_data->signature[i * 4], 4); //-V1086
|
||||
if(!magic_gen4_write_blk(password, 0xF2 + i, buffer)) {
|
||||
FURI_LOG_E(TAG, "Failed to write signature block %d", i);
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventFail, nfc_magic_worker->context);
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
buffer[0] = mf_ul_data->version.header;
|
||||
buffer[1] = mf_ul_data->version.vendor_id;
|
||||
buffer[2] = mf_ul_data->version.prod_type;
|
||||
buffer[3] = mf_ul_data->version.prod_subtype;
|
||||
if(!magic_gen4_write_blk(password, 0xFA, buffer)) {
|
||||
FURI_LOG_E(TAG, "Failed to write version block 0");
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventFail, nfc_magic_worker->context);
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
|
||||
buffer[0] = mf_ul_data->version.prod_ver_major;
|
||||
buffer[1] = mf_ul_data->version.prod_ver_minor;
|
||||
buffer[2] = mf_ul_data->version.storage_size;
|
||||
buffer[3] = mf_ul_data->version.protocol_type;
|
||||
if(!magic_gen4_write_blk(password, 0xFB, buffer)) {
|
||||
FURI_LOG_E(TAG, "Failed to write version block 1");
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventFail, nfc_magic_worker->context);
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
|
||||
break;
|
||||
} else {
|
||||
if(card_found_notified) {
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context);
|
||||
card_found_notified = false;
|
||||
}
|
||||
} while(false);
|
||||
|
||||
if(done) break;
|
||||
|
||||
if(card_found_notified) {
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context);
|
||||
card_found_notified = false;
|
||||
}
|
||||
|
||||
furi_delay_ms(300);
|
||||
}
|
||||
magic_deactivate();
|
||||
}
|
||||
|
||||
void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker) {
|
||||
NfcMagicDevice* magic_dev = nfc_magic_worker->magic_dev;
|
||||
bool card_found_notified = false;
|
||||
uint8_t gen4_config[MAGIC_GEN4_CONFIG_LEN];
|
||||
|
||||
while(nfc_magic_worker->state == NfcMagicWorkerStateCheck) {
|
||||
if(magic_wupa()) {
|
||||
magic_activate();
|
||||
if(magic_gen1_wupa()) {
|
||||
magic_dev->type = MagicTypeClassicGen1;
|
||||
if(!card_found_notified) {
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventCardDetected, nfc_magic_worker->context);
|
||||
card_found_notified = true;
|
||||
}
|
||||
|
||||
furi_hal_nfc_activate_nfca(200, &magic_dev->cuid);
|
||||
nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
|
||||
break;
|
||||
}
|
||||
|
||||
magic_deactivate();
|
||||
furi_delay_ms(300);
|
||||
magic_activate();
|
||||
|
||||
furi_hal_nfc_activate_nfca(200, &magic_dev->cuid);
|
||||
if(magic_gen4_get_cfg(magic_dev->password, gen4_config)) {
|
||||
magic_dev->type = MagicTypeGen4;
|
||||
if(!card_found_notified) {
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventCardDetected, nfc_magic_worker->context);
|
||||
@ -135,12 +331,56 @@ void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker) {
|
||||
|
||||
nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
|
||||
break;
|
||||
} else {
|
||||
}
|
||||
|
||||
if(card_found_notified) {
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context);
|
||||
card_found_notified = false;
|
||||
}
|
||||
|
||||
magic_deactivate();
|
||||
furi_delay_ms(300);
|
||||
}
|
||||
|
||||
magic_deactivate();
|
||||
}
|
||||
|
||||
void nfc_magic_worker_rekey(NfcMagicWorker* nfc_magic_worker) {
|
||||
NfcMagicDevice* magic_dev = nfc_magic_worker->magic_dev;
|
||||
bool card_found_notified = false;
|
||||
|
||||
if(magic_dev->type != MagicTypeGen4) {
|
||||
nfc_magic_worker->callback(NfcMagicWorkerEventCardDetected, nfc_magic_worker->context);
|
||||
return;
|
||||
}
|
||||
|
||||
while(nfc_magic_worker->state == NfcMagicWorkerStateRekey) {
|
||||
magic_activate();
|
||||
uint32_t cuid;
|
||||
furi_hal_nfc_activate_nfca(200, &cuid);
|
||||
if(cuid != magic_dev->cuid) {
|
||||
if(card_found_notified) {
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context);
|
||||
card_found_notified = false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
nfc_magic_worker->callback(NfcMagicWorkerEventCardDetected, nfc_magic_worker->context);
|
||||
card_found_notified = true;
|
||||
|
||||
if(magic_gen4_set_pwd(magic_dev->password, nfc_magic_worker->new_password)) {
|
||||
magic_dev->password = nfc_magic_worker->new_password;
|
||||
nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
|
||||
break;
|
||||
}
|
||||
|
||||
if(card_found_notified) { //-V547
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context);
|
||||
card_found_notified = false;
|
||||
}
|
||||
furi_delay_ms(300);
|
||||
}
|
||||
@ -148,6 +388,10 @@ void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker) {
|
||||
}
|
||||
|
||||
void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker) {
|
||||
NfcMagicDevice* magic_dev = nfc_magic_worker->magic_dev;
|
||||
bool card_found_notified = false;
|
||||
bool card_wiped = false;
|
||||
|
||||
MfClassicBlock block;
|
||||
memset(&block, 0, sizeof(MfClassicBlock));
|
||||
block.value[0] = 0x01;
|
||||
@ -159,14 +403,48 @@ void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker) {
|
||||
block.value[6] = 0x04;
|
||||
|
||||
while(nfc_magic_worker->state == NfcMagicWorkerStateWipe) {
|
||||
magic_deactivate();
|
||||
furi_delay_ms(300);
|
||||
if(!magic_wupa()) continue;
|
||||
if(!magic_wipe()) continue;
|
||||
if(!magic_data_access_cmd()) continue;
|
||||
if(!magic_write_blk(0, &block)) continue;
|
||||
nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
|
||||
break;
|
||||
do {
|
||||
magic_deactivate();
|
||||
furi_delay_ms(300);
|
||||
if(!magic_activate()) break;
|
||||
if(magic_dev->type == MagicTypeClassicGen1) {
|
||||
if(!magic_gen1_wupa()) break;
|
||||
if(!card_found_notified) {
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventCardDetected, nfc_magic_worker->context);
|
||||
card_found_notified = true;
|
||||
}
|
||||
|
||||
if(!magic_gen1_wipe()) break;
|
||||
if(!magic_gen1_data_access_cmd()) break;
|
||||
if(!magic_gen1_write_blk(0, &block)) break;
|
||||
|
||||
card_wiped = true;
|
||||
nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
|
||||
} else if(magic_dev->type == MagicTypeGen4) {
|
||||
uint32_t cuid;
|
||||
if(!furi_hal_nfc_activate_nfca(200, &cuid)) break;
|
||||
if(cuid != magic_dev->cuid) break;
|
||||
if(!card_found_notified) {
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventCardDetected, nfc_magic_worker->context);
|
||||
card_found_notified = true;
|
||||
}
|
||||
|
||||
if(!magic_gen4_wipe(magic_dev->password)) break;
|
||||
|
||||
card_wiped = true;
|
||||
nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
|
||||
}
|
||||
} while(false);
|
||||
|
||||
if(card_wiped) break;
|
||||
|
||||
if(card_found_notified) {
|
||||
nfc_magic_worker->callback(
|
||||
NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context);
|
||||
card_found_notified = false;
|
||||
}
|
||||
}
|
||||
magic_deactivate();
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <lib/nfc/nfc_device.h>
|
||||
#include "nfc_magic.h"
|
||||
|
||||
typedef struct NfcMagicWorker NfcMagicWorker;
|
||||
|
||||
@ -9,6 +10,7 @@ typedef enum {
|
||||
|
||||
NfcMagicWorkerStateCheck,
|
||||
NfcMagicWorkerStateWrite,
|
||||
NfcMagicWorkerStateRekey,
|
||||
NfcMagicWorkerStateWipe,
|
||||
|
||||
NfcMagicWorkerStateStop,
|
||||
@ -33,6 +35,8 @@ void nfc_magic_worker_stop(NfcMagicWorker* nfc_magic_worker);
|
||||
void nfc_magic_worker_start(
|
||||
NfcMagicWorker* nfc_magic_worker,
|
||||
NfcMagicWorkerState state,
|
||||
NfcMagicDevice* magic_dev,
|
||||
NfcDeviceData* dev_data,
|
||||
uint32_t new_password,
|
||||
NfcMagicWorkerCallback callback,
|
||||
void* context);
|
||||
|
||||
@ -3,11 +3,14 @@
|
||||
#include <furi.h>
|
||||
|
||||
#include "nfc_magic_worker.h"
|
||||
#include "lib/magic/common.h"
|
||||
|
||||
struct NfcMagicWorker {
|
||||
FuriThread* thread;
|
||||
|
||||
NfcMagicDevice* magic_dev;
|
||||
NfcDeviceData* dev_data;
|
||||
uint32_t new_password;
|
||||
|
||||
NfcMagicWorkerCallback callback;
|
||||
void* context;
|
||||
@ -21,4 +24,6 @@ void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker);
|
||||
|
||||
void nfc_magic_worker_write(NfcMagicWorker* nfc_magic_worker);
|
||||
|
||||
void nfc_magic_worker_rekey(NfcMagicWorker* nfc_magic_worker);
|
||||
|
||||
void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker);
|
||||
|
||||
50
applications/external/nfc_magic/scenes/nfc_magic_scene_actions.c
vendored
Normal file
50
applications/external/nfc_magic/scenes/nfc_magic_scene_actions.c
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
#include "../nfc_magic_i.h"
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexWrite,
|
||||
SubmenuIndexWipe,
|
||||
};
|
||||
|
||||
void nfc_magic_scene_actions_submenu_callback(void* context, uint32_t index) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, index);
|
||||
}
|
||||
|
||||
void nfc_magic_scene_actions_on_enter(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
|
||||
Submenu* submenu = nfc_magic->submenu;
|
||||
submenu_add_item(
|
||||
submenu, "Write", SubmenuIndexWrite, nfc_magic_scene_actions_submenu_callback, nfc_magic);
|
||||
submenu_add_item(
|
||||
submenu, "Wipe", SubmenuIndexWipe, nfc_magic_scene_actions_submenu_callback, nfc_magic);
|
||||
|
||||
submenu_set_selected_item(
|
||||
submenu, scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneActions));
|
||||
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewMenu);
|
||||
}
|
||||
|
||||
bool nfc_magic_scene_actions_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubmenuIndexWrite) {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneFileSelect);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexWipe) {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWipe);
|
||||
consumed = true;
|
||||
}
|
||||
scene_manager_set_scene_state(nfc_magic->scene_manager, NfcMagicSceneActions, event.event);
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc_magic->scene_manager, NfcMagicSceneStart);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_magic_scene_actions_on_exit(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
submenu_reset(nfc_magic->submenu);
|
||||
}
|
||||
@ -42,7 +42,9 @@ void nfc_magic_scene_check_on_enter(void* context) {
|
||||
nfc_magic_worker_start(
|
||||
nfc_magic->worker,
|
||||
NfcMagicWorkerStateCheck,
|
||||
&nfc_magic->nfc_dev->dev_data,
|
||||
nfc_magic->dev,
|
||||
&nfc_magic->source_dev->dev_data,
|
||||
nfc_magic->new_password,
|
||||
nfc_magic_check_worker_callback,
|
||||
nfc_magic);
|
||||
nfc_magic_blink_start(nfc_magic);
|
||||
|
||||
@ -1,4 +1,8 @@
|
||||
ADD_SCENE(nfc_magic, start, Start)
|
||||
ADD_SCENE(nfc_magic, key_input, KeyInput)
|
||||
ADD_SCENE(nfc_magic, actions, Actions)
|
||||
ADD_SCENE(nfc_magic, gen4_actions, Gen4Actions)
|
||||
ADD_SCENE(nfc_magic, new_key_input, NewKeyInput)
|
||||
ADD_SCENE(nfc_magic, file_select, FileSelect)
|
||||
ADD_SCENE(nfc_magic, write_confirm, WriteConfirm)
|
||||
ADD_SCENE(nfc_magic, wrong_card, WrongCard)
|
||||
@ -8,5 +12,7 @@ ADD_SCENE(nfc_magic, success, Success)
|
||||
ADD_SCENE(nfc_magic, check, Check)
|
||||
ADD_SCENE(nfc_magic, not_magic, NotMagic)
|
||||
ADD_SCENE(nfc_magic, magic_info, MagicInfo)
|
||||
ADD_SCENE(nfc_magic, rekey, Rekey)
|
||||
ADD_SCENE(nfc_magic, rekey_fail, RekeyFail)
|
||||
ADD_SCENE(nfc_magic, wipe, Wipe)
|
||||
ADD_SCENE(nfc_magic, wipe_fail, WipeFail)
|
||||
|
||||
@ -1,22 +1,60 @@
|
||||
#include "../nfc_magic_i.h"
|
||||
|
||||
static bool nfc_magic_scene_file_select_is_file_suitable(NfcDevice* nfc_dev) {
|
||||
return (nfc_dev->format == NfcDeviceSaveFormatMifareClassic) &&
|
||||
(nfc_dev->dev_data.mf_classic_data.type == MfClassicType1k) &&
|
||||
(nfc_dev->dev_data.nfc_data.uid_len == 4);
|
||||
static bool nfc_magic_scene_file_select_is_file_suitable(NfcMagic* nfc_magic) {
|
||||
NfcDevice* nfc_dev = nfc_magic->source_dev;
|
||||
if(nfc_dev->format == NfcDeviceSaveFormatMifareClassic) {
|
||||
switch(nfc_magic->dev->type) {
|
||||
case MagicTypeClassicGen1:
|
||||
case MagicTypeClassicDirectWrite:
|
||||
case MagicTypeClassicAPDU:
|
||||
if((nfc_dev->dev_data.mf_classic_data.type != MfClassicType1k) ||
|
||||
(nfc_dev->dev_data.nfc_data.uid_len != 4)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
case MagicTypeGen4:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} else if(
|
||||
(nfc_dev->format == NfcDeviceSaveFormatMifareUl) &&
|
||||
(nfc_dev->dev_data.nfc_data.uid_len == 7)) {
|
||||
switch(nfc_magic->dev->type) {
|
||||
case MagicTypeUltralightGen1:
|
||||
case MagicTypeUltralightDirectWrite:
|
||||
case MagicTypeUltralightC_Gen1:
|
||||
case MagicTypeUltralightC_DirectWrite:
|
||||
case MagicTypeGen4:
|
||||
switch(nfc_dev->dev_data.mf_ul_data.type) {
|
||||
case MfUltralightTypeNTAGI2C1K:
|
||||
case MfUltralightTypeNTAGI2C2K:
|
||||
case MfUltralightTypeNTAGI2CPlus1K:
|
||||
case MfUltralightTypeNTAGI2CPlus2K:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void nfc_magic_scene_file_select_on_enter(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
// Process file_select return
|
||||
nfc_device_set_loading_callback(nfc_magic->nfc_dev, nfc_magic_show_loading_popup, nfc_magic);
|
||||
nfc_device_set_loading_callback(
|
||||
nfc_magic->source_dev, nfc_magic_show_loading_popup, nfc_magic);
|
||||
|
||||
if(!furi_string_size(nfc_magic->nfc_dev->load_path)) {
|
||||
furi_string_set_str(nfc_magic->nfc_dev->load_path, NFC_APP_FOLDER);
|
||||
if(!furi_string_size(nfc_magic->source_dev->load_path)) {
|
||||
furi_string_set_str(nfc_magic->source_dev->load_path, NFC_APP_FOLDER);
|
||||
}
|
||||
|
||||
if(nfc_file_select(nfc_magic->nfc_dev)) {
|
||||
if(nfc_magic_scene_file_select_is_file_suitable(nfc_magic->nfc_dev)) {
|
||||
if(nfc_file_select(nfc_magic->source_dev)) {
|
||||
if(nfc_magic_scene_file_select_is_file_suitable(nfc_magic)) {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWriteConfirm);
|
||||
} else {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWrongCard);
|
||||
@ -34,5 +72,5 @@ bool nfc_magic_scene_file_select_on_event(void* context, SceneManagerEvent event
|
||||
|
||||
void nfc_magic_scene_file_select_on_exit(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
nfc_device_set_loading_callback(nfc_magic->nfc_dev, NULL, nfc_magic);
|
||||
nfc_device_set_loading_callback(nfc_magic->source_dev, NULL, nfc_magic);
|
||||
}
|
||||
|
||||
70
applications/external/nfc_magic/scenes/nfc_magic_scene_gen4_actions.c
vendored
Normal file
70
applications/external/nfc_magic/scenes/nfc_magic_scene_gen4_actions.c
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
#include "../nfc_magic_i.h"
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexWrite,
|
||||
SubmenuIndexChangePassword,
|
||||
SubmenuIndexWipe,
|
||||
};
|
||||
|
||||
void nfc_magic_scene_gen4_actions_submenu_callback(void* context, uint32_t index) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, index);
|
||||
}
|
||||
|
||||
void nfc_magic_scene_gen4_actions_on_enter(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
|
||||
Submenu* submenu = nfc_magic->submenu;
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Write",
|
||||
SubmenuIndexWrite,
|
||||
nfc_magic_scene_gen4_actions_submenu_callback,
|
||||
nfc_magic);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Change password",
|
||||
SubmenuIndexChangePassword,
|
||||
nfc_magic_scene_gen4_actions_submenu_callback,
|
||||
nfc_magic);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Wipe",
|
||||
SubmenuIndexWipe,
|
||||
nfc_magic_scene_gen4_actions_submenu_callback,
|
||||
nfc_magic);
|
||||
|
||||
submenu_set_selected_item(
|
||||
submenu,
|
||||
scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneGen4Actions));
|
||||
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewMenu);
|
||||
}
|
||||
|
||||
bool nfc_magic_scene_gen4_actions_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubmenuIndexWrite) {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneFileSelect);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexChangePassword) {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneNewKeyInput);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexWipe) {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWipe);
|
||||
consumed = true;
|
||||
}
|
||||
scene_manager_set_scene_state(
|
||||
nfc_magic->scene_manager, NfcMagicSceneGen4Actions, event.event);
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc_magic->scene_manager, NfcMagicSceneStart);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_magic_scene_gen4_actions_on_exit(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
submenu_reset(nfc_magic->submenu);
|
||||
}
|
||||
45
applications/external/nfc_magic/scenes/nfc_magic_scene_key_input.c
vendored
Normal file
45
applications/external/nfc_magic/scenes/nfc_magic_scene_key_input.c
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
#include "../nfc_magic_i.h"
|
||||
|
||||
void nfc_magic_scene_key_input_byte_input_callback(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
|
||||
view_dispatcher_send_custom_event(
|
||||
nfc_magic->view_dispatcher, NfcMagicCustomEventByteInputDone);
|
||||
}
|
||||
|
||||
void nfc_magic_scene_key_input_on_enter(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
|
||||
// Setup view
|
||||
ByteInput* byte_input = nfc_magic->byte_input;
|
||||
byte_input_set_header_text(byte_input, "Enter the password in hex");
|
||||
byte_input_set_result_callback(
|
||||
byte_input,
|
||||
nfc_magic_scene_key_input_byte_input_callback,
|
||||
NULL,
|
||||
nfc_magic,
|
||||
(uint8_t*)&nfc_magic->dev->password,
|
||||
4);
|
||||
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewByteInput);
|
||||
}
|
||||
|
||||
bool nfc_magic_scene_key_input_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == NfcMagicCustomEventByteInputDone) {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneCheck);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_magic_scene_key_input_on_exit(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
|
||||
// Clear view
|
||||
byte_input_set_result_callback(nfc_magic->byte_input, NULL, NULL, NULL, NULL, 0);
|
||||
byte_input_set_header_text(nfc_magic->byte_input, "");
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
#include "../nfc_magic_i.h"
|
||||
#include "../lib/magic/types.h"
|
||||
|
||||
void nfc_magic_scene_magic_info_widget_callback(
|
||||
GuiButtonType result,
|
||||
@ -13,14 +14,18 @@ void nfc_magic_scene_magic_info_widget_callback(
|
||||
void nfc_magic_scene_magic_info_on_enter(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
Widget* widget = nfc_magic->widget;
|
||||
const char* card_type = nfc_magic_type(nfc_magic->dev->type);
|
||||
|
||||
notification_message(nfc_magic->notifications, &sequence_success);
|
||||
|
||||
widget_add_icon_element(widget, 73, 17, &I_DolphinCommon_56x48);
|
||||
widget_add_string_element(
|
||||
widget, 3, 4, AlignLeft, AlignTop, FontPrimary, "Magic card detected");
|
||||
widget_add_string_element(widget, 3, 17, AlignLeft, AlignTop, FontSecondary, card_type);
|
||||
widget_add_button_element(
|
||||
widget, GuiButtonTypeLeft, "Retry", nfc_magic_scene_magic_info_widget_callback, nfc_magic);
|
||||
widget_add_button_element(
|
||||
widget, GuiButtonTypeRight, "More", nfc_magic_scene_magic_info_widget_callback, nfc_magic);
|
||||
|
||||
// Setup and start worker
|
||||
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget);
|
||||
@ -33,6 +38,15 @@ bool nfc_magic_scene_magic_info_on_event(void* context, SceneManagerEvent event)
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == GuiButtonTypeLeft) {
|
||||
consumed = scene_manager_previous_scene(nfc_magic->scene_manager);
|
||||
} else if(event.event == GuiButtonTypeRight) {
|
||||
MagicType type = nfc_magic->dev->type;
|
||||
if(type == MagicTypeGen4) {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneGen4Actions);
|
||||
consumed = true;
|
||||
} else {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneActions);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
|
||||
45
applications/external/nfc_magic/scenes/nfc_magic_scene_new_key_input.c
vendored
Normal file
45
applications/external/nfc_magic/scenes/nfc_magic_scene_new_key_input.c
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
#include "../nfc_magic_i.h"
|
||||
|
||||
void nfc_magic_scene_new_key_input_byte_input_callback(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
|
||||
view_dispatcher_send_custom_event(
|
||||
nfc_magic->view_dispatcher, NfcMagicCustomEventByteInputDone);
|
||||
}
|
||||
|
||||
void nfc_magic_scene_new_key_input_on_enter(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
|
||||
// Setup view
|
||||
ByteInput* byte_input = nfc_magic->byte_input;
|
||||
byte_input_set_header_text(byte_input, "Enter the password in hex");
|
||||
byte_input_set_result_callback(
|
||||
byte_input,
|
||||
nfc_magic_scene_new_key_input_byte_input_callback,
|
||||
NULL,
|
||||
nfc_magic,
|
||||
(uint8_t*)&nfc_magic->new_password,
|
||||
4);
|
||||
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewByteInput);
|
||||
}
|
||||
|
||||
bool nfc_magic_scene_new_key_input_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == NfcMagicCustomEventByteInputDone) {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneRekey);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_magic_scene_new_key_input_on_exit(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
|
||||
// Clear view
|
||||
byte_input_set_result_callback(nfc_magic->byte_input, NULL, NULL, NULL, NULL, 0);
|
||||
byte_input_set_header_text(nfc_magic->byte_input, "");
|
||||
}
|
||||
95
applications/external/nfc_magic/scenes/nfc_magic_scene_rekey.c
vendored
Normal file
95
applications/external/nfc_magic/scenes/nfc_magic_scene_rekey.c
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
#include "../nfc_magic_i.h"
|
||||
|
||||
enum {
|
||||
NfcMagicSceneRekeyStateCardSearch,
|
||||
NfcMagicSceneRekeyStateCardFound,
|
||||
};
|
||||
|
||||
bool nfc_magic_rekey_worker_callback(NfcMagicWorkerEvent event, void* context) {
|
||||
furi_assert(context);
|
||||
|
||||
NfcMagic* nfc_magic = context;
|
||||
view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, event);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void nfc_magic_scene_rekey_setup_view(NfcMagic* nfc_magic) {
|
||||
Popup* popup = nfc_magic->popup;
|
||||
popup_reset(popup);
|
||||
uint32_t state = scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneRekey);
|
||||
|
||||
if(state == NfcMagicSceneRekeyStateCardSearch) {
|
||||
popup_set_text(
|
||||
nfc_magic->popup,
|
||||
"Apply the\nsame card\nto the back",
|
||||
128,
|
||||
32,
|
||||
AlignRight,
|
||||
AlignCenter);
|
||||
popup_set_icon(nfc_magic->popup, 0, 8, &I_NFC_manual_60x50);
|
||||
} else {
|
||||
popup_set_icon(popup, 12, 23, &I_Loading_24);
|
||||
popup_set_header(popup, "Writing\nDon't move...", 52, 32, AlignLeft, AlignCenter);
|
||||
}
|
||||
|
||||
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewPopup);
|
||||
}
|
||||
|
||||
void nfc_magic_scene_rekey_on_enter(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
|
||||
scene_manager_set_scene_state(
|
||||
nfc_magic->scene_manager, NfcMagicSceneRekey, NfcMagicSceneRekeyStateCardSearch);
|
||||
nfc_magic_scene_rekey_setup_view(nfc_magic);
|
||||
|
||||
// Setup and start worker
|
||||
nfc_magic_worker_start(
|
||||
nfc_magic->worker,
|
||||
NfcMagicWorkerStateRekey,
|
||||
nfc_magic->dev,
|
||||
&nfc_magic->source_dev->dev_data,
|
||||
nfc_magic->new_password,
|
||||
nfc_magic_rekey_worker_callback,
|
||||
nfc_magic);
|
||||
nfc_magic_blink_start(nfc_magic);
|
||||
}
|
||||
|
||||
bool nfc_magic_scene_rekey_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == NfcMagicWorkerEventSuccess) {
|
||||
nfc_magic->dev->password = nfc_magic->new_password;
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneSuccess);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcMagicWorkerEventFail) {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneRekeyFail);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcMagicWorkerEventCardDetected) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc_magic->scene_manager, NfcMagicSceneRekey, NfcMagicSceneRekeyStateCardFound);
|
||||
nfc_magic_scene_rekey_setup_view(nfc_magic);
|
||||
consumed = true;
|
||||
} else if(event.event == NfcMagicWorkerEventNoCardDetected) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc_magic->scene_manager, NfcMagicSceneRekey, NfcMagicSceneRekeyStateCardSearch);
|
||||
nfc_magic_scene_rekey_setup_view(nfc_magic);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_magic_scene_rekey_on_exit(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
|
||||
nfc_magic_worker_stop(nfc_magic->worker);
|
||||
scene_manager_set_scene_state(
|
||||
nfc_magic->scene_manager, NfcMagicSceneRekey, NfcMagicSceneRekeyStateCardSearch);
|
||||
// Clear view
|
||||
popup_reset(nfc_magic->popup);
|
||||
|
||||
nfc_magic_blink_stop(nfc_magic);
|
||||
}
|
||||
50
applications/external/nfc_magic/scenes/nfc_magic_scene_rekey_fail.c
vendored
Normal file
50
applications/external/nfc_magic/scenes/nfc_magic_scene_rekey_fail.c
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
#include "../nfc_magic_i.h"
|
||||
|
||||
void nfc_magic_scene_rekey_fail_widget_callback(
|
||||
GuiButtonType result,
|
||||
InputType type,
|
||||
void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, result);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_magic_scene_rekey_fail_on_enter(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
Widget* widget = nfc_magic->widget;
|
||||
|
||||
notification_message(nfc_magic->notifications, &sequence_error);
|
||||
|
||||
widget_add_icon_element(widget, 72, 17, &I_DolphinCommon_56x48);
|
||||
widget_add_string_element(
|
||||
widget, 7, 4, AlignLeft, AlignTop, FontPrimary, "Can't change password!");
|
||||
|
||||
widget_add_button_element(
|
||||
widget, GuiButtonTypeLeft, "Finish", nfc_magic_scene_rekey_fail_widget_callback, nfc_magic);
|
||||
|
||||
// Setup and start worker
|
||||
view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget);
|
||||
}
|
||||
|
||||
bool nfc_magic_scene_rekey_fail_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == GuiButtonTypeLeft) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc_magic->scene_manager, NfcMagicSceneStart);
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc_magic->scene_manager, NfcMagicSceneStart);
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_magic_scene_rekey_fail_on_exit(void* context) {
|
||||
NfcMagic* nfc_magic = context;
|
||||
|
||||
widget_reset(nfc_magic->widget);
|
||||
}
|
||||
@ -1,8 +1,7 @@
|
||||
#include "../nfc_magic_i.h"
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexCheck,
|
||||
SubmenuIndexWriteGen1A,
|
||||
SubmenuIndexWipe,
|
||||
SubmenuIndexAuthenticateGen4,
|
||||
};
|
||||
|
||||
void nfc_magic_scene_start_submenu_callback(void* context, uint32_t index) {
|
||||
@ -22,12 +21,10 @@ void nfc_magic_scene_start_on_enter(void* context) {
|
||||
nfc_magic);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Write Gen1A",
|
||||
SubmenuIndexWriteGen1A,
|
||||
"Authenticate Gen4",
|
||||
SubmenuIndexAuthenticateGen4,
|
||||
nfc_magic_scene_start_submenu_callback,
|
||||
nfc_magic);
|
||||
submenu_add_item(
|
||||
submenu, "Wipe", SubmenuIndexWipe, nfc_magic_scene_start_submenu_callback, nfc_magic);
|
||||
|
||||
submenu_set_selected_item(
|
||||
submenu, scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneStart));
|
||||
@ -40,23 +37,13 @@ bool nfc_magic_scene_start_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubmenuIndexCheck) {
|
||||
nfc_magic->dev->password = MAGIC_GEN4_DEFAULT_PWD;
|
||||
scene_manager_set_scene_state(
|
||||
nfc_magic->scene_manager, NfcMagicSceneStart, SubmenuIndexCheck);
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneCheck);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexWriteGen1A) {
|
||||
// Explicitly save state in each branch so that the
|
||||
// correct option is reselected if the user cancels
|
||||
// loading a file.
|
||||
scene_manager_set_scene_state(
|
||||
nfc_magic->scene_manager, NfcMagicSceneStart, SubmenuIndexWriteGen1A);
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneFileSelect);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexWipe) {
|
||||
scene_manager_set_scene_state(
|
||||
nfc_magic->scene_manager, NfcMagicSceneStart, SubmenuIndexWipe);
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWipe);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexAuthenticateGen4) {
|
||||
scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneKeyInput);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -22,7 +22,12 @@ static void nfc_magic_scene_wipe_setup_view(NfcMagic* nfc_magic) {
|
||||
if(state == NfcMagicSceneWipeStateCardSearch) {
|
||||
popup_set_icon(nfc_magic->popup, 0, 8, &I_NFC_manual_60x50);
|
||||
popup_set_text(
|
||||
nfc_magic->popup, "Apply card to\nthe back", 128, 32, AlignRight, AlignCenter);
|
||||
nfc_magic->popup,
|
||||
"Apply the\nsame card\nto the back",
|
||||
128,
|
||||
32,
|
||||
AlignRight,
|
||||
AlignCenter);
|
||||
} else {
|
||||
popup_set_icon(popup, 12, 23, &I_Loading_24);
|
||||
popup_set_header(popup, "Wiping\nDon't move...", 52, 32, AlignLeft, AlignCenter);
|
||||
@ -42,7 +47,9 @@ void nfc_magic_scene_wipe_on_enter(void* context) {
|
||||
nfc_magic_worker_start(
|
||||
nfc_magic->worker,
|
||||
NfcMagicWorkerStateWipe,
|
||||
&nfc_magic->nfc_dev->dev_data,
|
||||
nfc_magic->dev,
|
||||
&nfc_magic->source_dev->dev_data,
|
||||
nfc_magic->new_password,
|
||||
nfc_magic_wipe_worker_callback,
|
||||
nfc_magic);
|
||||
nfc_magic_blink_start(nfc_magic);
|
||||
|
||||
@ -21,7 +21,12 @@ static void nfc_magic_scene_write_setup_view(NfcMagic* nfc_magic) {
|
||||
|
||||
if(state == NfcMagicSceneWriteStateCardSearch) {
|
||||
popup_set_text(
|
||||
nfc_magic->popup, "Apply card to\nthe back", 128, 32, AlignRight, AlignCenter);
|
||||
nfc_magic->popup,
|
||||
"Apply the\nsame card\nto the back",
|
||||
128,
|
||||
32,
|
||||
AlignRight,
|
||||
AlignCenter);
|
||||
popup_set_icon(nfc_magic->popup, 0, 8, &I_NFC_manual_60x50);
|
||||
} else {
|
||||
popup_set_icon(popup, 12, 23, &I_Loading_24);
|
||||
@ -42,7 +47,9 @@ void nfc_magic_scene_write_on_enter(void* context) {
|
||||
nfc_magic_worker_start(
|
||||
nfc_magic->worker,
|
||||
NfcMagicWorkerStateWrite,
|
||||
&nfc_magic->nfc_dev->dev_data,
|
||||
nfc_magic->dev,
|
||||
&nfc_magic->source_dev->dev_data,
|
||||
nfc_magic->new_password,
|
||||
nfc_magic_write_worker_callback,
|
||||
nfc_magic);
|
||||
nfc_magic_blink_start(nfc_magic);
|
||||
|
||||
@ -26,7 +26,7 @@ void nfc_magic_scene_wrong_card_on_enter(void* context) {
|
||||
AlignLeft,
|
||||
AlignTop,
|
||||
FontSecondary,
|
||||
"Writing is supported\nonly for 4 bytes UID\nMifare Classic 1k");
|
||||
"Writing this file is\nnot supported for\nthis magic card.");
|
||||
widget_add_button_element(
|
||||
widget, GuiButtonTypeLeft, "Retry", nfc_magic_scene_wrong_card_widget_callback, nfc_magic);
|
||||
|
||||
|
||||
@ -16,10 +16,11 @@
|
||||
(((uint8_t)x < 128) ? (script->layout[(uint8_t)x]) : HID_KEYBOARD_NONE)
|
||||
|
||||
typedef enum {
|
||||
WorkerEvtToggle = (1 << 0),
|
||||
WorkerEvtEnd = (1 << 1),
|
||||
WorkerEvtConnect = (1 << 2),
|
||||
WorkerEvtDisconnect = (1 << 3),
|
||||
WorkerEvtStartStop = (1 << 0),
|
||||
WorkerEvtPauseResume = (1 << 1),
|
||||
WorkerEvtEnd = (1 << 2),
|
||||
WorkerEvtConnect = (1 << 3),
|
||||
WorkerEvtDisconnect = (1 << 4),
|
||||
} WorkerEvtFlags;
|
||||
|
||||
static const char ducky_cmd_id[] = {"ID"};
|
||||
@ -372,6 +373,7 @@ static int32_t bad_usb_worker(void* context) {
|
||||
BadUsbScript* bad_usb = context;
|
||||
|
||||
BadUsbWorkerState worker_state = BadUsbStateInit;
|
||||
BadUsbWorkerState pause_state = BadUsbStateRunning;
|
||||
int32_t delay_val = 0;
|
||||
|
||||
FURI_LOG_I(WORKER_TAG, "Init");
|
||||
@ -406,24 +408,24 @@ static int32_t bad_usb_worker(void* context) {
|
||||
|
||||
} else if(worker_state == BadUsbStateNotConnected) { // State: USB not connected
|
||||
uint32_t flags = bad_usb_flags_get(
|
||||
WorkerEvtEnd | WorkerEvtConnect | WorkerEvtToggle, FuriWaitForever);
|
||||
WorkerEvtEnd | WorkerEvtConnect | WorkerEvtStartStop, FuriWaitForever);
|
||||
|
||||
if(flags & WorkerEvtEnd) {
|
||||
break;
|
||||
} else if(flags & WorkerEvtConnect) {
|
||||
worker_state = BadUsbStateIdle; // Ready to run
|
||||
} else if(flags & WorkerEvtToggle) {
|
||||
} else if(flags & WorkerEvtStartStop) {
|
||||
worker_state = BadUsbStateWillRun; // Will run when USB is connected
|
||||
}
|
||||
bad_usb->st.state = worker_state;
|
||||
|
||||
} else if(worker_state == BadUsbStateIdle) { // State: ready to start
|
||||
uint32_t flags = bad_usb_flags_get(
|
||||
WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect, FuriWaitForever);
|
||||
WorkerEvtEnd | WorkerEvtStartStop | WorkerEvtDisconnect, FuriWaitForever);
|
||||
|
||||
if(flags & WorkerEvtEnd) {
|
||||
break;
|
||||
} else if(flags & WorkerEvtToggle) { // Start executing script
|
||||
} else if(flags & WorkerEvtStartStop) { // Start executing script
|
||||
DOLPHIN_DEED(DolphinDeedBadUsbPlayScript);
|
||||
delay_val = 0;
|
||||
bad_usb->buf_len = 0;
|
||||
@ -442,7 +444,7 @@ static int32_t bad_usb_worker(void* context) {
|
||||
|
||||
} else if(worker_state == BadUsbStateWillRun) { // State: start on connection
|
||||
uint32_t flags = bad_usb_flags_get(
|
||||
WorkerEvtEnd | WorkerEvtConnect | WorkerEvtToggle, FuriWaitForever);
|
||||
WorkerEvtEnd | WorkerEvtConnect | WorkerEvtStartStop, FuriWaitForever);
|
||||
|
||||
if(flags & WorkerEvtEnd) {
|
||||
break;
|
||||
@ -458,17 +460,17 @@ static int32_t bad_usb_worker(void* context) {
|
||||
storage_file_seek(script_file, 0, true);
|
||||
// extra time for PC to recognize Flipper as keyboard
|
||||
flags = furi_thread_flags_wait(
|
||||
WorkerEvtEnd | WorkerEvtDisconnect | WorkerEvtToggle,
|
||||
WorkerEvtEnd | WorkerEvtDisconnect | WorkerEvtStartStop,
|
||||
FuriFlagWaitAny | FuriFlagNoClear,
|
||||
1500);
|
||||
if(flags == (unsigned)FuriFlagErrorTimeout) {
|
||||
// If nothing happened - start script execution
|
||||
worker_state = BadUsbStateRunning;
|
||||
} else if(flags & WorkerEvtToggle) {
|
||||
} else if(flags & WorkerEvtStartStop) {
|
||||
worker_state = BadUsbStateIdle;
|
||||
furi_thread_flags_clear(WorkerEvtToggle);
|
||||
furi_thread_flags_clear(WorkerEvtStartStop);
|
||||
}
|
||||
} else if(flags & WorkerEvtToggle) { // Cancel scheduled execution
|
||||
} else if(flags & WorkerEvtStartStop) { // Cancel scheduled execution
|
||||
worker_state = BadUsbStateNotConnected;
|
||||
}
|
||||
bad_usb->st.state = worker_state;
|
||||
@ -476,18 +478,23 @@ static int32_t bad_usb_worker(void* context) {
|
||||
} else if(worker_state == BadUsbStateRunning) { // State: running
|
||||
uint16_t delay_cur = (delay_val > 1000) ? (1000) : (delay_val);
|
||||
uint32_t flags = furi_thread_flags_wait(
|
||||
WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect, FuriFlagWaitAny, delay_cur);
|
||||
WorkerEvtEnd | WorkerEvtStartStop | WorkerEvtPauseResume | WorkerEvtDisconnect,
|
||||
FuriFlagWaitAny,
|
||||
delay_cur);
|
||||
|
||||
delay_val -= delay_cur;
|
||||
if(!(flags & FuriFlagError)) {
|
||||
if(flags & WorkerEvtEnd) {
|
||||
break;
|
||||
} else if(flags & WorkerEvtToggle) {
|
||||
} else if(flags & WorkerEvtStartStop) {
|
||||
worker_state = BadUsbStateIdle; // Stop executing script
|
||||
furi_hal_hid_kb_release_all();
|
||||
} else if(flags & WorkerEvtDisconnect) {
|
||||
worker_state = BadUsbStateNotConnected; // USB disconnected
|
||||
furi_hal_hid_kb_release_all();
|
||||
} else if(flags & WorkerEvtPauseResume) {
|
||||
pause_state = BadUsbStateRunning;
|
||||
worker_state = BadUsbStatePaused; // Pause
|
||||
}
|
||||
bad_usb->st.state = worker_state;
|
||||
continue;
|
||||
@ -526,13 +533,13 @@ static int32_t bad_usb_worker(void* context) {
|
||||
furi_check((flags & FuriFlagError) == 0);
|
||||
}
|
||||
} else if(worker_state == BadUsbStateWaitForBtn) { // State: Wait for button Press
|
||||
uint16_t delay_cur = (delay_val > 1000) ? (1000) : (delay_val);
|
||||
uint32_t flags = furi_thread_flags_wait(
|
||||
WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect, FuriFlagWaitAny, delay_cur);
|
||||
uint32_t flags = bad_usb_flags_get(
|
||||
WorkerEvtEnd | WorkerEvtStartStop | WorkerEvtPauseResume | WorkerEvtDisconnect,
|
||||
FuriWaitForever);
|
||||
if(!(flags & FuriFlagError)) {
|
||||
if(flags & WorkerEvtEnd) {
|
||||
break;
|
||||
} else if(flags & WorkerEvtToggle) {
|
||||
} else if(flags & WorkerEvtStartStop) {
|
||||
delay_val = 0;
|
||||
worker_state = BadUsbStateRunning;
|
||||
} else if(flags & WorkerEvtDisconnect) {
|
||||
@ -542,21 +549,55 @@ static int32_t bad_usb_worker(void* context) {
|
||||
bad_usb->st.state = worker_state;
|
||||
continue;
|
||||
}
|
||||
} else if(worker_state == BadUsbStatePaused) { // State: Paused
|
||||
uint32_t flags = bad_usb_flags_get(
|
||||
WorkerEvtEnd | WorkerEvtStartStop | WorkerEvtPauseResume | WorkerEvtDisconnect,
|
||||
FuriWaitForever);
|
||||
if(!(flags & FuriFlagError)) {
|
||||
if(flags & WorkerEvtEnd) {
|
||||
break;
|
||||
} else if(flags & WorkerEvtStartStop) {
|
||||
worker_state = BadUsbStateIdle; // Stop executing script
|
||||
bad_usb->st.state = worker_state;
|
||||
furi_hal_hid_kb_release_all();
|
||||
} else if(flags & WorkerEvtDisconnect) {
|
||||
worker_state = BadUsbStateNotConnected; // USB disconnected
|
||||
bad_usb->st.state = worker_state;
|
||||
furi_hal_hid_kb_release_all();
|
||||
} else if(flags & WorkerEvtPauseResume) {
|
||||
if(pause_state == BadUsbStateRunning) {
|
||||
if(delay_val > 0) {
|
||||
bad_usb->st.state = BadUsbStateDelay;
|
||||
bad_usb->st.delay_remain = delay_val / 1000;
|
||||
} else {
|
||||
bad_usb->st.state = BadUsbStateRunning;
|
||||
delay_val = 0;
|
||||
}
|
||||
worker_state = BadUsbStateRunning; // Resume
|
||||
} else if(pause_state == BadUsbStateStringDelay) {
|
||||
bad_usb->st.state = BadUsbStateRunning;
|
||||
worker_state = BadUsbStateStringDelay; // Resume
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
} else if(worker_state == BadUsbStateStringDelay) { // State: print string with delays
|
||||
uint32_t flags = furi_thread_flags_wait(
|
||||
WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect,
|
||||
FuriFlagWaitAny,
|
||||
uint32_t flags = bad_usb_flags_get(
|
||||
WorkerEvtEnd | WorkerEvtStartStop | WorkerEvtPauseResume | WorkerEvtDisconnect,
|
||||
bad_usb->stringdelay);
|
||||
|
||||
if(!(flags & FuriFlagError)) {
|
||||
if(flags & WorkerEvtEnd) {
|
||||
break;
|
||||
} else if(flags & WorkerEvtToggle) {
|
||||
} else if(flags & WorkerEvtStartStop) {
|
||||
worker_state = BadUsbStateIdle; // Stop executing script
|
||||
furi_hal_hid_kb_release_all();
|
||||
} else if(flags & WorkerEvtDisconnect) {
|
||||
worker_state = BadUsbStateNotConnected; // USB disconnected
|
||||
furi_hal_hid_kb_release_all();
|
||||
} else if(flags & WorkerEvtPauseResume) {
|
||||
pause_state = BadUsbStateStringDelay;
|
||||
worker_state = BadUsbStatePaused; // Pause
|
||||
}
|
||||
bad_usb->st.state = worker_state;
|
||||
continue;
|
||||
@ -651,9 +692,14 @@ void bad_usb_script_set_keyboard_layout(BadUsbScript* bad_usb, FuriString* layou
|
||||
storage_file_free(layout_file);
|
||||
}
|
||||
|
||||
void bad_usb_script_toggle(BadUsbScript* bad_usb) {
|
||||
void bad_usb_script_start_stop(BadUsbScript* bad_usb) {
|
||||
furi_assert(bad_usb);
|
||||
furi_thread_flags_set(furi_thread_get_id(bad_usb->thread), WorkerEvtToggle);
|
||||
furi_thread_flags_set(furi_thread_get_id(bad_usb->thread), WorkerEvtStartStop);
|
||||
}
|
||||
|
||||
void bad_usb_script_pause_resume(BadUsbScript* bad_usb) {
|
||||
furi_assert(bad_usb);
|
||||
furi_thread_flags_set(furi_thread_get_id(bad_usb->thread), WorkerEvtPauseResume);
|
||||
}
|
||||
|
||||
BadUsbState* bad_usb_script_get_state(BadUsbScript* bad_usb) {
|
||||
|
||||
@ -16,6 +16,7 @@ typedef enum {
|
||||
BadUsbStateDelay,
|
||||
BadUsbStateStringDelay,
|
||||
BadUsbStateWaitForBtn,
|
||||
BadUsbStatePaused,
|
||||
BadUsbStateDone,
|
||||
BadUsbStateScriptError,
|
||||
BadUsbStateFileError,
|
||||
@ -42,7 +43,9 @@ void bad_usb_script_start(BadUsbScript* bad_usb);
|
||||
|
||||
void bad_usb_script_stop(BadUsbScript* bad_usb);
|
||||
|
||||
void bad_usb_script_toggle(BadUsbScript* bad_usb);
|
||||
void bad_usb_script_start_stop(BadUsbScript* bad_usb);
|
||||
|
||||
void bad_usb_script_pause_resume(BadUsbScript* bad_usb);
|
||||
|
||||
BadUsbState* bad_usb_script_get_state(BadUsbScript* bad_usb);
|
||||
|
||||
|
||||
@ -21,7 +21,10 @@ bool bad_usb_scene_work_on_event(void* context, SceneManagerEvent event) {
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event.event == InputKeyOk) {
|
||||
bad_usb_script_toggle(app->bad_usb_script);
|
||||
bad_usb_script_start_stop(app->bad_usb_script);
|
||||
consumed = true;
|
||||
} else if(event.event == InputKeyRight) {
|
||||
bad_usb_script_pause_resume(app->bad_usb_script);
|
||||
consumed = true;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeTick) {
|
||||
|
||||
@ -16,6 +16,7 @@ typedef struct {
|
||||
char file_name[MAX_NAME_LEN];
|
||||
char layout[MAX_NAME_LEN];
|
||||
BadUsbState state;
|
||||
bool pause_wait;
|
||||
uint8_t anim_frame;
|
||||
} BadUsbModel;
|
||||
|
||||
@ -31,11 +32,7 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) {
|
||||
if(strlen(model->layout) == 0) {
|
||||
furi_string_set(disp_str, "(default)");
|
||||
} else {
|
||||
furi_string_reset(disp_str);
|
||||
furi_string_push_back(disp_str, '(');
|
||||
for(size_t i = 0; i < strlen(model->layout); i++)
|
||||
furi_string_push_back(disp_str, model->layout[i]);
|
||||
furi_string_push_back(disp_str, ')');
|
||||
furi_string_printf(disp_str, "(%s)", model->layout);
|
||||
}
|
||||
elements_string_fit_width(canvas, disp_str, 128 - 2);
|
||||
canvas_draw_str(
|
||||
@ -45,34 +42,42 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) {
|
||||
|
||||
canvas_draw_icon(canvas, 22, 24, &I_UsbTree_48x22);
|
||||
|
||||
if((model->state.state == BadUsbStateIdle) || (model->state.state == BadUsbStateDone) ||
|
||||
(model->state.state == BadUsbStateNotConnected)) {
|
||||
BadUsbWorkerState state = model->state.state;
|
||||
|
||||
if((state == BadUsbStateIdle) || (state == BadUsbStateDone) ||
|
||||
(state == BadUsbStateNotConnected)) {
|
||||
elements_button_center(canvas, "Run");
|
||||
elements_button_left(canvas, "Config");
|
||||
} else if((model->state.state == BadUsbStateRunning) || (model->state.state == BadUsbStateDelay)) {
|
||||
} else if((state == BadUsbStateRunning) || (state == BadUsbStateDelay)) {
|
||||
elements_button_center(canvas, "Stop");
|
||||
} else if(model->state.state == BadUsbStateWaitForBtn) {
|
||||
if(!model->pause_wait) {
|
||||
elements_button_right(canvas, "Pause");
|
||||
}
|
||||
} else if(state == BadUsbStatePaused) {
|
||||
elements_button_center(canvas, "End");
|
||||
elements_button_right(canvas, "Resume");
|
||||
} else if(state == BadUsbStateWaitForBtn) {
|
||||
elements_button_center(canvas, "Press to continue");
|
||||
} else if(model->state.state == BadUsbStateWillRun) {
|
||||
} else if(state == BadUsbStateWillRun) {
|
||||
elements_button_center(canvas, "Cancel");
|
||||
}
|
||||
|
||||
if(model->state.state == BadUsbStateNotConnected) {
|
||||
if(state == BadUsbStateNotConnected) {
|
||||
canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Connect");
|
||||
canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "to USB");
|
||||
} else if(model->state.state == BadUsbStateWillRun) {
|
||||
} else if(state == BadUsbStateWillRun) {
|
||||
canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Will run");
|
||||
canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "on connect");
|
||||
} else if(model->state.state == BadUsbStateFileError) {
|
||||
} else if(state == BadUsbStateFileError) {
|
||||
canvas_draw_icon(canvas, 4, 26, &I_Error_18x18);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "File");
|
||||
canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "ERROR");
|
||||
} else if(model->state.state == BadUsbStateScriptError) {
|
||||
} else if(state == BadUsbStateScriptError) {
|
||||
canvas_draw_icon(canvas, 4, 26, &I_Error_18x18);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 127, 33, AlignRight, AlignBottom, "ERROR:");
|
||||
@ -87,12 +92,12 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) {
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 127, 56, AlignRight, AlignBottom, furi_string_get_cstr(disp_str));
|
||||
furi_string_reset(disp_str);
|
||||
} else if(model->state.state == BadUsbStateIdle) {
|
||||
} else if(state == BadUsbStateIdle) {
|
||||
canvas_draw_icon(canvas, 4, 26, &I_Smile_18x18);
|
||||
canvas_set_font(canvas, FontBigNumbers);
|
||||
canvas_draw_str_aligned(canvas, 114, 40, AlignRight, AlignBottom, "0");
|
||||
canvas_draw_icon(canvas, 117, 26, &I_Percent_10x14);
|
||||
} else if(model->state.state == BadUsbStateRunning) {
|
||||
} else if(state == BadUsbStateRunning) {
|
||||
if(model->anim_frame == 0) {
|
||||
canvas_draw_icon(canvas, 4, 23, &I_EviSmile1_18x21);
|
||||
} else {
|
||||
@ -105,13 +110,13 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) {
|
||||
canvas, 114, 40, AlignRight, AlignBottom, furi_string_get_cstr(disp_str));
|
||||
furi_string_reset(disp_str);
|
||||
canvas_draw_icon(canvas, 117, 26, &I_Percent_10x14);
|
||||
} else if(model->state.state == BadUsbStateDone) {
|
||||
} else if(state == BadUsbStateDone) {
|
||||
canvas_draw_icon(canvas, 4, 23, &I_EviSmile1_18x21);
|
||||
canvas_set_font(canvas, FontBigNumbers);
|
||||
canvas_draw_str_aligned(canvas, 114, 40, AlignRight, AlignBottom, "100");
|
||||
furi_string_reset(disp_str);
|
||||
canvas_draw_icon(canvas, 117, 26, &I_Percent_10x14);
|
||||
} else if(model->state.state == BadUsbStateDelay) {
|
||||
} else if(state == BadUsbStateDelay) {
|
||||
if(model->anim_frame == 0) {
|
||||
canvas_draw_icon(canvas, 4, 23, &I_EviWaiting1_18x21);
|
||||
} else {
|
||||
@ -129,6 +134,22 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) {
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 127, 50, AlignRight, AlignBottom, furi_string_get_cstr(disp_str));
|
||||
furi_string_reset(disp_str);
|
||||
} else if((state == BadUsbStatePaused) || (state == BadUsbStateWaitForBtn)) {
|
||||
if(model->anim_frame == 0) {
|
||||
canvas_draw_icon(canvas, 4, 23, &I_EviWaiting1_18x21);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 4, 23, &I_EviWaiting2_18x21);
|
||||
}
|
||||
canvas_set_font(canvas, FontBigNumbers);
|
||||
furi_string_printf(
|
||||
disp_str, "%u", ((model->state.line_cur - 1) * 100) / model->state.line_nb);
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 114, 40, AlignRight, AlignBottom, furi_string_get_cstr(disp_str));
|
||||
furi_string_reset(disp_str);
|
||||
canvas_draw_icon(canvas, 117, 26, &I_Percent_10x14);
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str_aligned(canvas, 127, 50, AlignRight, AlignBottom, "Paused");
|
||||
furi_string_reset(disp_str);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18);
|
||||
}
|
||||
@ -142,7 +163,27 @@ static bool bad_usb_input_callback(InputEvent* event, void* context) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == InputTypeShort) {
|
||||
if((event->key == InputKeyLeft) || (event->key == InputKeyOk)) {
|
||||
if(event->key == InputKeyLeft) {
|
||||
consumed = true;
|
||||
furi_assert(bad_usb->callback);
|
||||
bad_usb->callback(event->key, bad_usb->context);
|
||||
} else if(event->key == InputKeyOk) {
|
||||
with_view_model(
|
||||
bad_usb->view, BadUsbModel * model, { model->pause_wait = false; }, true);
|
||||
consumed = true;
|
||||
furi_assert(bad_usb->callback);
|
||||
bad_usb->callback(event->key, bad_usb->context);
|
||||
} else if(event->key == InputKeyRight) {
|
||||
with_view_model(
|
||||
bad_usb->view,
|
||||
BadUsbModel * model,
|
||||
{
|
||||
if((model->state.state == BadUsbStateRunning) ||
|
||||
(model->state.state == BadUsbStateDelay)) {
|
||||
model->pause_wait = true;
|
||||
}
|
||||
},
|
||||
true);
|
||||
consumed = true;
|
||||
furi_assert(bad_usb->callback);
|
||||
bad_usb->callback(event->key, bad_usb->context);
|
||||
@ -215,6 +256,9 @@ void bad_usb_set_state(BadUsb* bad_usb, BadUsbState* st) {
|
||||
{
|
||||
memcpy(&(model->state), st, sizeof(BadUsbState));
|
||||
model->anim_frame ^= 1;
|
||||
if(model->state.state == BadUsbStatePaused) {
|
||||
model->pause_wait = false;
|
||||
}
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
@ -312,7 +312,8 @@ void infrared_tx_start_signal(Infrared* infrared, InfraredSignal* signal) {
|
||||
|
||||
if(infrared_signal_is_raw(signal)) {
|
||||
InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal);
|
||||
infrared_worker_set_raw_signal(infrared->worker, raw->timings, raw->timings_size);
|
||||
infrared_worker_set_raw_signal(
|
||||
infrared->worker, raw->timings, raw->timings_size, raw->frequency, raw->duty_cycle);
|
||||
} else {
|
||||
InfraredMessage* message = infrared_signal_get_message(signal);
|
||||
infrared_worker_set_decoded_signal(infrared->worker, message);
|
||||
|
||||
@ -52,6 +52,7 @@ void nfc_scene_device_info_on_enter(void* context) {
|
||||
}
|
||||
} else if(
|
||||
dev_data->protocol == NfcDeviceProtocolMifareClassic ||
|
||||
dev_data->protocol == NfcDeviceProtocolMifareDesfire ||
|
||||
dev_data->protocol == NfcDeviceProtocolMifareUl) {
|
||||
furi_string_set(temp_str, nfc->dev->dev_data.parsed_data);
|
||||
}
|
||||
|
||||
@ -20,35 +20,40 @@ void nfc_scene_mf_desfire_read_success_on_enter(void* context) {
|
||||
Widget* widget = nfc->widget;
|
||||
|
||||
// Prepare string for data display
|
||||
FuriString* temp_str = furi_string_alloc_printf("\e#MIFARE DESfire\n");
|
||||
furi_string_cat_printf(temp_str, "UID:");
|
||||
for(size_t i = 0; i < nfc_data->uid_len; i++) {
|
||||
furi_string_cat_printf(temp_str, " %02X", nfc_data->uid[i]);
|
||||
}
|
||||
|
||||
uint32_t bytes_total = 1UL << (data->version.sw_storage >> 1);
|
||||
uint32_t bytes_free = data->free_memory ? data->free_memory->bytes : 0;
|
||||
furi_string_cat_printf(temp_str, "\n%lu", bytes_total);
|
||||
if(data->version.sw_storage & 1) {
|
||||
furi_string_push_back(temp_str, '+');
|
||||
}
|
||||
furi_string_cat_printf(temp_str, " bytes, %lu bytes free\n", bytes_free);
|
||||
|
||||
uint16_t n_apps = 0;
|
||||
uint16_t n_files = 0;
|
||||
for(MifareDesfireApplication* app = data->app_head; app; app = app->next) {
|
||||
n_apps++;
|
||||
for(MifareDesfireFile* file = app->file_head; file; file = file->next) {
|
||||
n_files++;
|
||||
FuriString* temp_str = NULL;
|
||||
if(furi_string_size(nfc->dev->dev_data.parsed_data)) {
|
||||
temp_str = furi_string_alloc_set(nfc->dev->dev_data.parsed_data);
|
||||
} else {
|
||||
temp_str = furi_string_alloc_printf("\e#MIFARE DESFire\n");
|
||||
furi_string_cat_printf(temp_str, "UID:");
|
||||
for(size_t i = 0; i < nfc_data->uid_len; i++) {
|
||||
furi_string_cat_printf(temp_str, " %02X", nfc_data->uid[i]);
|
||||
}
|
||||
|
||||
uint32_t bytes_total = 1UL << (data->version.sw_storage >> 1);
|
||||
uint32_t bytes_free = data->free_memory ? data->free_memory->bytes : 0;
|
||||
furi_string_cat_printf(temp_str, "\n%lu", bytes_total);
|
||||
if(data->version.sw_storage & 1) {
|
||||
furi_string_push_back(temp_str, '+');
|
||||
}
|
||||
furi_string_cat_printf(temp_str, " bytes, %lu bytes free\n", bytes_free);
|
||||
|
||||
uint16_t n_apps = 0;
|
||||
uint16_t n_files = 0;
|
||||
for(MifareDesfireApplication* app = data->app_head; app; app = app->next) {
|
||||
n_apps++;
|
||||
for(MifareDesfireFile* file = app->file_head; file; file = file->next) {
|
||||
n_files++;
|
||||
}
|
||||
}
|
||||
furi_string_cat_printf(temp_str, "%d Application", n_apps);
|
||||
if(n_apps != 1) {
|
||||
furi_string_push_back(temp_str, 's');
|
||||
}
|
||||
furi_string_cat_printf(temp_str, ", %d file", n_files);
|
||||
if(n_files != 1) {
|
||||
furi_string_push_back(temp_str, 's');
|
||||
}
|
||||
}
|
||||
furi_string_cat_printf(temp_str, "%d Application", n_apps);
|
||||
if(n_apps != 1) {
|
||||
furi_string_push_back(temp_str, 's');
|
||||
}
|
||||
furi_string_cat_printf(temp_str, ", %d file", n_files);
|
||||
if(n_files != 1) {
|
||||
furi_string_push_back(temp_str, 's');
|
||||
}
|
||||
|
||||
notification_message_block(nfc->notifications, &sequence_set_green_255);
|
||||
|
||||
@ -19,7 +19,7 @@ void nfc_scene_mf_ultralight_menu_on_enter(void* context) {
|
||||
Submenu* submenu = nfc->submenu;
|
||||
MfUltralightData* data = &nfc->dev->dev_data.mf_ul_data;
|
||||
|
||||
if(!mf_ul_is_full_capture(data)) {
|
||||
if(!mf_ul_is_full_capture(data) && data->type != MfUltralightTypeULC) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Unlock",
|
||||
@ -29,12 +29,14 @@ void nfc_scene_mf_ultralight_menu_on_enter(void* context) {
|
||||
}
|
||||
submenu_add_item(
|
||||
submenu, "Save", SubmenuIndexSave, nfc_scene_mf_ultralight_menu_submenu_callback, nfc);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Emulate",
|
||||
SubmenuIndexEmulate,
|
||||
nfc_scene_mf_ultralight_menu_submenu_callback,
|
||||
nfc);
|
||||
if(mf_ul_emulation_supported(data)) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Emulate",
|
||||
SubmenuIndexEmulate,
|
||||
nfc_scene_mf_ultralight_menu_submenu_callback,
|
||||
nfc);
|
||||
}
|
||||
submenu_add_item(
|
||||
submenu, "Info", SubmenuIndexInfo, nfc_scene_mf_ultralight_menu_submenu_callback, nfc);
|
||||
|
||||
|
||||
@ -40,7 +40,7 @@ void nfc_scene_nfc_data_info_on_enter(void* context) {
|
||||
furi_string_cat_printf(
|
||||
temp_str, "\e#%s\n", nfc_mf_classic_type(dev_data->mf_classic_data.type));
|
||||
} 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 {
|
||||
furi_string_cat_printf(temp_str, "\e#Unknown ISO tag\n");
|
||||
}
|
||||
|
||||
@ -42,7 +42,8 @@ void nfc_scene_saved_menu_on_enter(void* context) {
|
||||
nfc);
|
||||
}
|
||||
} else if(
|
||||
nfc->dev->format == NfcDeviceSaveFormatMifareUl ||
|
||||
(nfc->dev->format == NfcDeviceSaveFormatMifareUl &&
|
||||
mf_ul_emulation_supported(&nfc->dev->dev_data.mf_ul_data)) ||
|
||||
nfc->dev->format == NfcDeviceSaveFormatMifareClassic) {
|
||||
submenu_add_item(
|
||||
submenu, "Emulate", SubmenuIndexEmulate, nfc_scene_saved_menu_submenu_callback, nfc);
|
||||
@ -72,6 +73,7 @@ void nfc_scene_saved_menu_on_enter(void* context) {
|
||||
submenu_add_item(
|
||||
submenu, "Info", SubmenuIndexInfo, nfc_scene_saved_menu_submenu_callback, nfc);
|
||||
if(nfc->dev->format == NfcDeviceSaveFormatMifareUl &&
|
||||
nfc->dev->dev_data.mf_ul_data.type != MfUltralightTypeULC &&
|
||||
!mf_ul_is_full_capture(&nfc->dev->dev_data.mf_ul_data)) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
@ -146,6 +148,7 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
application_info_present = true;
|
||||
} else if(
|
||||
dev_data->protocol == NfcDeviceProtocolMifareClassic ||
|
||||
dev_data->protocol == NfcDeviceProtocolMifareDesfire ||
|
||||
dev_data->protocol == NfcDeviceProtocolMifareUl) {
|
||||
application_info_present = nfc_supported_card_verify_and_parse(dev_data);
|
||||
}
|
||||
|
||||
@ -147,6 +147,9 @@ void desktop_lock(Desktop* desktop) {
|
||||
desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_FIRST_ENTER);
|
||||
scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked);
|
||||
notification_message(desktop->notification, &sequence_display_backlight_off_delay_1000);
|
||||
|
||||
DesktopStatus status = {.locked = true};
|
||||
furi_pubsub_publish(desktop->status_pubsub, &status);
|
||||
}
|
||||
|
||||
void desktop_unlock(Desktop* desktop) {
|
||||
@ -165,6 +168,9 @@ void desktop_unlock(Desktop* desktop) {
|
||||
cli_session_open(cli, &cli_vcp);
|
||||
furi_record_close(RECORD_CLI);
|
||||
}
|
||||
|
||||
DesktopStatus status = {.locked = false};
|
||||
furi_pubsub_publish(desktop->status_pubsub, &status);
|
||||
}
|
||||
|
||||
void desktop_set_dummy_mode_state(Desktop* desktop, bool enabled) {
|
||||
@ -308,63 +314,13 @@ Desktop* desktop_alloc() {
|
||||
desktop->auto_lock_timer =
|
||||
furi_timer_alloc(desktop_auto_lock_timer_callback, FuriTimerTypeOnce, desktop);
|
||||
|
||||
desktop->status_pubsub = furi_pubsub_alloc();
|
||||
|
||||
furi_record_create(RECORD_DESKTOP, desktop);
|
||||
|
||||
return desktop;
|
||||
}
|
||||
|
||||
void desktop_free(Desktop* desktop) {
|
||||
furi_assert(desktop);
|
||||
furi_check(furi_record_destroy(RECORD_DESKTOP));
|
||||
|
||||
furi_pubsub_unsubscribe(
|
||||
loader_get_pubsub(desktop->loader), desktop->app_start_stop_subscription);
|
||||
|
||||
if(desktop->input_events_subscription) {
|
||||
furi_pubsub_unsubscribe(desktop->input_events_pubsub, desktop->input_events_subscription);
|
||||
desktop->input_events_subscription = NULL;
|
||||
}
|
||||
|
||||
desktop->loader = NULL;
|
||||
desktop->input_events_pubsub = NULL;
|
||||
furi_record_close(RECORD_LOADER);
|
||||
furi_record_close(RECORD_NOTIFICATION);
|
||||
furi_record_close(RECORD_INPUT_EVENTS);
|
||||
|
||||
view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdMain);
|
||||
view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdLockMenu);
|
||||
view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdLocked);
|
||||
view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdDebug);
|
||||
view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdHwMismatch);
|
||||
view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdPinInput);
|
||||
view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdPinTimeout);
|
||||
|
||||
view_dispatcher_free(desktop->view_dispatcher);
|
||||
scene_manager_free(desktop->scene_manager);
|
||||
|
||||
animation_manager_free(desktop->animation_manager);
|
||||
view_stack_free(desktop->main_view_stack);
|
||||
desktop_main_free(desktop->main_view);
|
||||
view_stack_free(desktop->locked_view_stack);
|
||||
desktop_view_locked_free(desktop->locked_view);
|
||||
desktop_lock_menu_free(desktop->lock_menu);
|
||||
desktop_view_locked_free(desktop->locked_view);
|
||||
desktop_debug_free(desktop->debug_view);
|
||||
popup_free(desktop->hw_mismatch_popup);
|
||||
desktop_view_pin_timeout_free(desktop->pin_timeout_view);
|
||||
|
||||
furi_record_close(RECORD_GUI);
|
||||
desktop->gui = NULL;
|
||||
|
||||
furi_thread_free(desktop->scene_thread);
|
||||
|
||||
furi_record_close("menu");
|
||||
|
||||
furi_timer_free(desktop->auto_lock_timer);
|
||||
|
||||
free(desktop);
|
||||
}
|
||||
|
||||
static bool desktop_check_file_flag(const char* flag_path) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
bool exists = storage_common_stat(storage, flag_path, NULL) == FSE_OK;
|
||||
@ -383,6 +339,11 @@ void desktop_api_unlock(Desktop* instance) {
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, DesktopLockedEventUnlocked);
|
||||
}
|
||||
|
||||
FuriPubSub* desktop_api_get_status_pubsub(Desktop* instance) {
|
||||
furi_assert(instance);
|
||||
return instance->status_pubsub;
|
||||
}
|
||||
|
||||
int32_t desktop_srv(void* p) {
|
||||
UNUSED(p);
|
||||
|
||||
@ -427,7 +388,8 @@ int32_t desktop_srv(void* p) {
|
||||
}
|
||||
|
||||
view_dispatcher_run(desktop->view_dispatcher);
|
||||
desktop_free(desktop);
|
||||
|
||||
furi_crash("That was unexpected");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
typedef struct Desktop Desktop;
|
||||
|
||||
#define RECORD_DESKTOP "desktop"
|
||||
@ -7,3 +9,9 @@ typedef struct Desktop Desktop;
|
||||
bool desktop_api_is_locked(Desktop* instance);
|
||||
|
||||
void desktop_api_unlock(Desktop* instance);
|
||||
|
||||
typedef struct {
|
||||
bool locked;
|
||||
} DesktopStatus;
|
||||
|
||||
FuriPubSub* desktop_api_get_status_pubsub(Desktop* instance);
|
||||
|
||||
@ -71,6 +71,8 @@ struct Desktop {
|
||||
FuriPubSubSubscription* input_events_subscription;
|
||||
FuriTimer* auto_lock_timer;
|
||||
|
||||
FuriPubSub* status_pubsub;
|
||||
|
||||
bool in_transition;
|
||||
};
|
||||
|
||||
|
||||
@ -36,8 +36,6 @@
|
||||
#define MIN_PIN_SIZE 4
|
||||
#define MAX_APP_LENGTH 128
|
||||
|
||||
#define FAP_LOADER_APP_NAME "Applications"
|
||||
|
||||
typedef struct {
|
||||
InputKey data[MAX_PIN_SIZE];
|
||||
uint8_t length;
|
||||
|
||||
@ -16,6 +16,8 @@
|
||||
#define SNAKE_GAME_APP EXT_PATH("/apps/Games/snake_game.fap")
|
||||
#define CLOCK_APP EXT_PATH("/apps/Tools/clock.fap")
|
||||
|
||||
#define FAP_LOADER_APP_NAME "Applications"
|
||||
|
||||
static void desktop_scene_main_new_idle_animation_callback(void* context) {
|
||||
furi_assert(context);
|
||||
Desktop* desktop = context;
|
||||
@ -77,6 +79,21 @@ static void desktop_scene_main_open_app_or_profile(Desktop* desktop, const char*
|
||||
} while(false);
|
||||
}
|
||||
|
||||
static void desktop_scene_main_start_favorite(Desktop* desktop, FavoriteApp* application) {
|
||||
LoaderStatus status = LoaderStatusErrorInternal;
|
||||
if(application->is_external) {
|
||||
status = loader_start(desktop->loader, FAP_LOADER_APP_NAME, application->name_or_path);
|
||||
} else if(strlen(application->name_or_path) > 0) {
|
||||
status = loader_start(desktop->loader, application->name_or_path, NULL);
|
||||
} else {
|
||||
status = loader_start(desktop->loader, FAP_LOADER_APP_NAME, NULL);
|
||||
}
|
||||
|
||||
if(status != LoaderStatusOk) {
|
||||
FURI_LOG_E(TAG, "loader_start failed: %d", status);
|
||||
}
|
||||
}
|
||||
|
||||
void desktop_scene_main_callback(DesktopEvent event, void* context) {
|
||||
Desktop* desktop = (Desktop*)context;
|
||||
if(desktop->in_transition) return;
|
||||
@ -141,40 +158,12 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
case DesktopMainEventOpenFavoritePrimary:
|
||||
DESKTOP_SETTINGS_LOAD(&desktop->settings);
|
||||
if(desktop->settings.favorite_primary.is_external) {
|
||||
LoaderStatus status = loader_start(
|
||||
desktop->loader,
|
||||
FAP_LOADER_APP_NAME,
|
||||
desktop->settings.favorite_primary.name_or_path);
|
||||
if(status != LoaderStatusOk) {
|
||||
FURI_LOG_E(TAG, "loader_start failed: %d", status);
|
||||
}
|
||||
} else {
|
||||
LoaderStatus status = loader_start(
|
||||
desktop->loader, desktop->settings.favorite_primary.name_or_path, NULL);
|
||||
if(status != LoaderStatusOk) {
|
||||
FURI_LOG_E(TAG, "loader_start failed: %d", status);
|
||||
}
|
||||
}
|
||||
desktop_scene_main_start_favorite(desktop, &desktop->settings.favorite_primary);
|
||||
consumed = true;
|
||||
break;
|
||||
case DesktopMainEventOpenFavoriteSecondary:
|
||||
DESKTOP_SETTINGS_LOAD(&desktop->settings);
|
||||
if(desktop->settings.favorite_secondary.is_external) {
|
||||
LoaderStatus status = loader_start(
|
||||
desktop->loader,
|
||||
FAP_LOADER_APP_NAME,
|
||||
desktop->settings.favorite_secondary.name_or_path);
|
||||
if(status != LoaderStatusOk) {
|
||||
FURI_LOG_E(TAG, "loader_start failed: %d", status);
|
||||
}
|
||||
} else {
|
||||
LoaderStatus status = loader_start(
|
||||
desktop->loader, desktop->settings.favorite_secondary.name_or_path, NULL);
|
||||
if(status != LoaderStatusOk) {
|
||||
FURI_LOG_E(TAG, "loader_start failed: %d", status);
|
||||
}
|
||||
}
|
||||
desktop_scene_main_start_favorite(desktop, &desktop->settings.favorite_secondary);
|
||||
consumed = true;
|
||||
break;
|
||||
case DesktopAnimationEventCheckAnimation:
|
||||
|
||||
@ -89,15 +89,6 @@ Dolphin* dolphin_alloc() {
|
||||
return dolphin;
|
||||
}
|
||||
|
||||
void dolphin_free(Dolphin* dolphin) {
|
||||
furi_assert(dolphin);
|
||||
|
||||
dolphin_state_free(dolphin->state);
|
||||
furi_message_queue_free(dolphin->event_queue);
|
||||
|
||||
free(dolphin);
|
||||
}
|
||||
|
||||
void dolphin_event_send_async(Dolphin* dolphin, DolphinEvent* event) {
|
||||
furi_assert(dolphin);
|
||||
furi_assert(event);
|
||||
@ -204,7 +195,7 @@ int32_t dolphin_srv(void* p) {
|
||||
}
|
||||
}
|
||||
|
||||
dolphin_free(dolphin);
|
||||
furi_crash("That was unexpected");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -37,8 +37,6 @@ struct Dolphin {
|
||||
|
||||
Dolphin* dolphin_alloc();
|
||||
|
||||
void dolphin_free(Dolphin* dolphin);
|
||||
|
||||
void dolphin_event_send_async(Dolphin* dolphin, DolphinEvent* event);
|
||||
|
||||
void dolphin_event_send_wait(Dolphin* dolphin, DolphinEvent* event);
|
||||
|
||||
@ -85,30 +85,6 @@ Power* power_alloc() {
|
||||
return power;
|
||||
}
|
||||
|
||||
void power_free(Power* power) {
|
||||
furi_assert(power);
|
||||
|
||||
// Gui
|
||||
view_dispatcher_remove_view(power->view_dispatcher, PowerViewOff);
|
||||
power_off_free(power->power_off);
|
||||
view_dispatcher_remove_view(power->view_dispatcher, PowerViewUnplugUsb);
|
||||
power_unplug_usb_free(power->power_unplug_usb);
|
||||
|
||||
view_port_free(power->battery_view_port);
|
||||
|
||||
// State
|
||||
furi_mutex_free(power->api_mtx);
|
||||
|
||||
// FuriPubSub
|
||||
furi_pubsub_free(power->event_pubsub);
|
||||
|
||||
// Records
|
||||
furi_record_close(RECORD_NOTIFICATION);
|
||||
furi_record_close(RECORD_GUI);
|
||||
|
||||
free(power);
|
||||
}
|
||||
|
||||
static void power_check_charging_state(Power* power) {
|
||||
if(furi_hal_power_is_charging()) {
|
||||
if((power->info.charge == 100) || (furi_hal_power_is_charging_done())) {
|
||||
@ -252,7 +228,7 @@ int32_t power_srv(void* p) {
|
||||
furi_delay_ms(1000);
|
||||
}
|
||||
|
||||
power_free(power);
|
||||
furi_crash("That was unexpected");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -8,6 +8,8 @@
|
||||
typedef struct {
|
||||
RpcSession* session;
|
||||
Desktop* desktop;
|
||||
FuriPubSub* status_pubsub;
|
||||
FuriPubSubSubscription* status_subscription;
|
||||
} RpcDesktop;
|
||||
|
||||
static void rpc_desktop_on_is_locked_request(const PB_Main* request, void* context) {
|
||||
@ -39,11 +41,63 @@ static void rpc_desktop_on_unlock_request(const PB_Main* request, void* context)
|
||||
rpc_send_and_release_empty(session, request->command_id, PB_CommandStatus_OK);
|
||||
}
|
||||
|
||||
static void rpc_desktop_on_desktop_pubsub(const void* message, void* context) {
|
||||
RpcDesktop* rpc_desktop = context;
|
||||
RpcSession* session = rpc_desktop->session;
|
||||
const DesktopStatus* status = message;
|
||||
|
||||
PB_Main rpc_message = {
|
||||
.command_id = 0,
|
||||
.command_status = PB_CommandStatus_OK,
|
||||
.has_next = false,
|
||||
.which_content = PB_Main_desktop_status_tag,
|
||||
.content.desktop_status.locked = status->locked,
|
||||
};
|
||||
rpc_send_and_release(session, &rpc_message);
|
||||
}
|
||||
|
||||
static void rpc_desktop_on_status_subscribe_request(const PB_Main* request, void* context) {
|
||||
furi_assert(request);
|
||||
furi_assert(context);
|
||||
furi_assert(request->which_content == PB_Main_desktop_status_subscribe_request_tag);
|
||||
|
||||
FURI_LOG_D(TAG, "StatusSubscribeRequest");
|
||||
RpcDesktop* rpc_desktop = context;
|
||||
RpcSession* session = rpc_desktop->session;
|
||||
|
||||
if(rpc_desktop->status_subscription) {
|
||||
rpc_send_and_release_empty(session, request->command_id, PB_CommandStatus_ERROR);
|
||||
} else {
|
||||
rpc_desktop->status_subscription = furi_pubsub_subscribe(
|
||||
rpc_desktop->status_pubsub, rpc_desktop_on_desktop_pubsub, rpc_desktop);
|
||||
rpc_send_and_release_empty(session, request->command_id, PB_CommandStatus_OK);
|
||||
}
|
||||
}
|
||||
|
||||
static void rpc_desktop_on_status_unsubscribe_request(const PB_Main* request, void* context) {
|
||||
furi_assert(request);
|
||||
furi_assert(context);
|
||||
furi_assert(request->which_content == PB_Main_desktop_status_unsubscribe_request_tag);
|
||||
|
||||
FURI_LOG_D(TAG, "StatusUnsubscribeRequest");
|
||||
RpcDesktop* rpc_desktop = context;
|
||||
RpcSession* session = rpc_desktop->session;
|
||||
|
||||
if(rpc_desktop->status_subscription) {
|
||||
furi_pubsub_unsubscribe(rpc_desktop->status_pubsub, rpc_desktop->status_subscription);
|
||||
rpc_desktop->status_subscription = NULL;
|
||||
rpc_send_and_release_empty(session, request->command_id, PB_CommandStatus_OK);
|
||||
} else {
|
||||
rpc_send_and_release_empty(session, request->command_id, PB_CommandStatus_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
void* rpc_desktop_alloc(RpcSession* session) {
|
||||
furi_assert(session);
|
||||
|
||||
RpcDesktop* rpc_desktop = malloc(sizeof(RpcDesktop));
|
||||
rpc_desktop->desktop = furi_record_open(RECORD_DESKTOP);
|
||||
rpc_desktop->status_pubsub = desktop_api_get_status_pubsub(rpc_desktop->desktop);
|
||||
rpc_desktop->session = session;
|
||||
|
||||
RpcHandler rpc_handler = {
|
||||
@ -58,6 +112,12 @@ void* rpc_desktop_alloc(RpcSession* session) {
|
||||
rpc_handler.message_handler = rpc_desktop_on_unlock_request;
|
||||
rpc_add_handler(session, PB_Main_desktop_unlock_request_tag, &rpc_handler);
|
||||
|
||||
rpc_handler.message_handler = rpc_desktop_on_status_subscribe_request;
|
||||
rpc_add_handler(session, PB_Main_desktop_status_subscribe_request_tag, &rpc_handler);
|
||||
|
||||
rpc_handler.message_handler = rpc_desktop_on_status_unsubscribe_request;
|
||||
rpc_add_handler(session, PB_Main_desktop_status_unsubscribe_request_tag, &rpc_handler);
|
||||
|
||||
return rpc_desktop;
|
||||
}
|
||||
|
||||
@ -65,6 +125,10 @@ void rpc_desktop_free(void* context) {
|
||||
furi_assert(context);
|
||||
RpcDesktop* rpc_desktop = context;
|
||||
|
||||
if(rpc_desktop->status_subscription) {
|
||||
furi_pubsub_unsubscribe(rpc_desktop->status_pubsub, rpc_desktop->status_subscription);
|
||||
}
|
||||
|
||||
furi_assert(rpc_desktop->desktop);
|
||||
furi_record_close(RECORD_DESKTOP);
|
||||
|
||||
|
||||
@ -226,7 +226,7 @@ FS_Error storage_common_stat(Storage* storage, const char* path, FileInfo* filei
|
||||
*/
|
||||
FS_Error storage_common_remove(Storage* storage, const char* path);
|
||||
|
||||
/** Renames file/directory, file/directory must not be open
|
||||
/** Renames file/directory, file/directory must not be open. Will overwrite existing file.
|
||||
* @param app pointer to the api
|
||||
* @param old_path old path
|
||||
* @param new_path new path
|
||||
|
||||
@ -422,12 +422,27 @@ FS_Error storage_common_remove(Storage* storage, const char* path) {
|
||||
}
|
||||
|
||||
FS_Error storage_common_rename(Storage* storage, const char* old_path, const char* new_path) {
|
||||
FS_Error error = storage_common_copy(storage, old_path, new_path);
|
||||
if(error == FSE_OK) {
|
||||
FS_Error error;
|
||||
|
||||
do {
|
||||
if(!storage_common_exists(storage, old_path)) {
|
||||
error = FSE_INVALID_NAME;
|
||||
break;
|
||||
}
|
||||
|
||||
if(storage_file_exists(storage, new_path)) {
|
||||
storage_common_remove(storage, new_path);
|
||||
}
|
||||
|
||||
error = storage_common_copy(storage, old_path, new_path);
|
||||
if(error != FSE_OK) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(!storage_simply_remove_recursive(storage, old_path)) {
|
||||
error = FSE_INTERNAL;
|
||||
}
|
||||
}
|
||||
} while(false);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -5,6 +5,9 @@
|
||||
#include <dialogs/dialogs.h>
|
||||
#include <fap_loader/fap_loader_app.h>
|
||||
|
||||
#define EXTERNAL_APPLICATION_NAME ("[External Application]")
|
||||
#define EXTERNAL_APPLICATION_INDEX (FLIPPER_APPS_COUNT + 1)
|
||||
|
||||
static bool favorite_fap_selector_item_callback(
|
||||
FuriString* file_path,
|
||||
void* context,
|
||||
@ -44,6 +47,8 @@ void desktop_settings_scene_favorite_on_enter(void* context) {
|
||||
uint32_t primary_favorite =
|
||||
scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppSceneFavorite);
|
||||
uint32_t pre_select_item = 0;
|
||||
FavoriteApp* curr_favorite_app = primary_favorite ? &app->settings.favorite_primary :
|
||||
&app->settings.favorite_secondary;
|
||||
|
||||
for(size_t i = 0; i < FLIPPER_APPS_COUNT; i++) {
|
||||
submenu_add_item(
|
||||
@ -53,21 +58,25 @@ void desktop_settings_scene_favorite_on_enter(void* context) {
|
||||
desktop_settings_scene_favorite_submenu_callback,
|
||||
app);
|
||||
|
||||
if(primary_favorite) { // Select favorite item in submenu
|
||||
if((app->settings.favorite_primary.is_external &&
|
||||
!strcmp(FLIPPER_APPS[i].name, FAP_LOADER_APP_NAME)) ||
|
||||
(!strcmp(FLIPPER_APPS[i].name, app->settings.favorite_primary.name_or_path))) {
|
||||
pre_select_item = i;
|
||||
}
|
||||
} else {
|
||||
if((app->settings.favorite_secondary.is_external &&
|
||||
!strcmp(FLIPPER_APPS[i].name, FAP_LOADER_APP_NAME)) ||
|
||||
(!strcmp(FLIPPER_APPS[i].name, app->settings.favorite_secondary.name_or_path))) {
|
||||
pre_select_item = i;
|
||||
}
|
||||
// Select favorite item in submenu
|
||||
if(!curr_favorite_app->is_external &&
|
||||
!strcmp(FLIPPER_APPS[i].name, curr_favorite_app->name_or_path)) {
|
||||
pre_select_item = i;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef APP_FAP_LOADER
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
EXTERNAL_APPLICATION_NAME,
|
||||
EXTERNAL_APPLICATION_INDEX,
|
||||
desktop_settings_scene_favorite_submenu_callback,
|
||||
app);
|
||||
if(curr_favorite_app->is_external) {
|
||||
pre_select_item = EXTERNAL_APPLICATION_INDEX;
|
||||
}
|
||||
#endif
|
||||
|
||||
submenu_set_header(
|
||||
submenu, primary_favorite ? "Primary favorite app:" : "Secondary favorite app:");
|
||||
submenu_set_selected_item(submenu, pre_select_item); // If set during loop, visual glitch.
|
||||
@ -82,23 +91,11 @@ bool desktop_settings_scene_favorite_on_event(void* context, SceneManagerEvent e
|
||||
|
||||
uint32_t primary_favorite =
|
||||
scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppSceneFavorite);
|
||||
FavoriteApp* curr_favorite_app = primary_favorite ? &app->settings.favorite_primary :
|
||||
&app->settings.favorite_secondary;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(strcmp(FLIPPER_APPS[event.event].name, FAP_LOADER_APP_NAME) != 0) {
|
||||
if(primary_favorite) {
|
||||
app->settings.favorite_primary.is_external = false;
|
||||
strncpy(
|
||||
app->settings.favorite_primary.name_or_path,
|
||||
FLIPPER_APPS[event.event].name,
|
||||
MAX_APP_LENGTH);
|
||||
} else {
|
||||
app->settings.favorite_secondary.is_external = false;
|
||||
strncpy(
|
||||
app->settings.favorite_secondary.name_or_path,
|
||||
FLIPPER_APPS[event.event].name,
|
||||
MAX_APP_LENGTH);
|
||||
}
|
||||
} else {
|
||||
if(event.event == EXTERNAL_APPLICATION_INDEX) {
|
||||
const DialogsFileBrowserOptions browser_options = {
|
||||
.extension = ".fap",
|
||||
.icon = &I_unknown_10px,
|
||||
@ -109,36 +106,29 @@ bool desktop_settings_scene_favorite_on_event(void* context, SceneManagerEvent e
|
||||
.base_path = EXT_PATH("apps"),
|
||||
};
|
||||
|
||||
if(primary_favorite) { // Select favorite fap in file browser
|
||||
if(favorite_fap_selector_file_exists(
|
||||
app->settings.favorite_primary.name_or_path)) {
|
||||
furi_string_set_str(temp_path, app->settings.favorite_primary.name_or_path);
|
||||
}
|
||||
} else {
|
||||
if(favorite_fap_selector_file_exists(
|
||||
app->settings.favorite_secondary.name_or_path)) {
|
||||
furi_string_set_str(temp_path, app->settings.favorite_secondary.name_or_path);
|
||||
}
|
||||
// Select favorite fap in file browser
|
||||
if(favorite_fap_selector_file_exists(curr_favorite_app->name_or_path)) {
|
||||
furi_string_set_str(temp_path, curr_favorite_app->name_or_path);
|
||||
}
|
||||
|
||||
submenu_reset(app->submenu);
|
||||
if(dialog_file_browser_show(app->dialogs, temp_path, temp_path, &browser_options)) {
|
||||
if(primary_favorite) {
|
||||
app->settings.favorite_primary.is_external = true;
|
||||
strncpy(
|
||||
app->settings.favorite_primary.name_or_path,
|
||||
furi_string_get_cstr(temp_path),
|
||||
MAX_APP_LENGTH);
|
||||
} else {
|
||||
app->settings.favorite_secondary.is_external = true;
|
||||
strncpy(
|
||||
app->settings.favorite_secondary.name_or_path,
|
||||
furi_string_get_cstr(temp_path),
|
||||
MAX_APP_LENGTH);
|
||||
}
|
||||
submenu_reset(app->submenu); // Prevent menu from being shown when we exiting scene
|
||||
curr_favorite_app->is_external = true;
|
||||
strncpy(
|
||||
curr_favorite_app->name_or_path,
|
||||
furi_string_get_cstr(temp_path),
|
||||
MAX_APP_LENGTH);
|
||||
consumed = true;
|
||||
}
|
||||
} else {
|
||||
curr_favorite_app->is_external = false;
|
||||
strncpy(
|
||||
curr_favorite_app->name_or_path, FLIPPER_APPS[event.event].name, MAX_APP_LENGTH);
|
||||
consumed = true;
|
||||
}
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
if(consumed) {
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
};
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
|
||||
@ -1 +1 @@
|
||||
Subproject commit a13c5ddd0397511bd4c6de4afdd1031a5b6f5bca
|
||||
Subproject commit f71c4b7f750f2539a1fed08925d8da3abdc80ff9
|
||||
BIN
assets/resources/badusb/assets/layouts/fr-FR-mac.kl
Normal file
BIN
assets/resources/badusb/assets/layouts/fr-FR-mac.kl
Normal file
Binary file not shown.
@ -297,8 +297,8 @@ type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 2320 634 837 637 838 637 838 640 835 642 832 1378 836 645 826 670 809 667 808 1406 806 672 803 674 802 1412 802 1412 800 676 801 675 802 1412 802 674 802 1413 801 1412 801 1413 802 1412 802 50937 2285 671 801 1411 802 51225 2280 696 775 1412 801 51212 2283 671 775 1412 802
|
||||
# Model: Daikin FTXM20M.
|
||||
#
|
||||
# Model: Daikin FTXM20M.
|
||||
name: Off
|
||||
type: raw
|
||||
frequency: 38000
|
||||
@ -334,8 +334,8 @@ type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 503 365 500 364 501 366 499 365 500 364 502 25049 3535 1660 504 1228 503 390 474 391 473 393 471 1261 469 397 468 397 469 397 469 397 469 1264 468 398 468 1264 468 1264 468 398 468 1265 467 1265 467 1265 467 1265 467 1265 467 399 467 399 467 1266 466 399 467 400 466 400 466 400 466 423 443 423 443 401 465 423 442 424 442 424 442 1290 442 424 442 1290 442 424 442 424 441 424 442 1290 442 1291 441 425 441 424 442 425 441 425 441 1291 441 425 440 425 441 425 441 425 441 425 441 425 440 425 441 425 441 425 441 425 441 426 440 1292 440 1292 440 1292 440 426 440 426 440 1292 440 1293 439 1293 439 35480 3503 1696 467 1264 468 398 468 398 467 398 468 1265 467 398 467 399 467 399 466 399 467 1265 467 399 467 1266 466 1267 465 400 466 1290 442 1290 442 1290 442 1290 442 1290 442 424 442 424 442 1290 442 424 441 424 442 424 442 424 442 424 442 424 441 424 442 425 441 424 442 425 441 425 441 1291 441 425 441 425 441 425 441 425 440 1292 440 425 441 425 440 426 440 426 440 426 440 426 440 426 440 426 440 426 440 426 439 427 439 426 440 426 440 1293 439 427 439 427 439 427 438 427 439 428 438 1294 438 428 437 428 438 1295 437 1319 413 453 413 35480 3503 1696 468 1265 467 398 468 398 468 398 468 1265 467 398 468 399 466 399 467 399 467 1266 466 399 466 1267 465 1290 442 401 465 1290 442 1290 442 1290 442 1290 442 1290 442 424 442 424 441 1291 441 424 442 424 442 424 442 424 442 424 441 424 442 425 441 424 442 424 441 425 441 425 441 425 440 425 441 425 441 425 441 425 441 425 441 425 441 1292 440 426 440 426 440 1292 440 426 440 426 440 1293 439 426 440 426 440 1293 439 1293 439 1293 439 427 439 1294 438 427 438 427 439 427 438 428 438 428 438 428 438 428 438 453 413 429 437 453 413 1319 413 1320 412 1320 412 1320 412 454 412 1320 412 454 412 1321 411 1321 411 1321 411 1321 411 1321 411 455 410 455 411 455 411 455 410 456 410 456 410 456 410 481 384 481 385 482 383 482 383 483 358 507 359 1374 358 1374 358 508 358 508 358 508 358 509 357 509 357 535 331 535 331 535 330 535 330 536 330 1403 329 1403 329 563 302 564 301 564 302 564 301 565 301 591 274 619 246 593 273 620 245 620 245 621 245 673 189
|
||||
# Model: Mitsubishi SRK63HE.
|
||||
#
|
||||
# Model: Mitsubishi SRK63HE.
|
||||
name: Off
|
||||
type: raw
|
||||
frequency: 38000
|
||||
@ -371,3 +371,102 @@ type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 3234 1525 463 333 462 1127 465 332 462 333 436 1153 518 307 488 1073 518 307 488 308 434 1131 459 1155 435 1156 434 362 433 1159 432 363 432 1159 432 1159 432 1159 433 363 432 363 432 363 433 363 432 1159 433 1159 432 363 432 1159 433 1159 432 363 432 363 432 1159 432 363 433 363 432 1159 432 363 432 363 432 1159 432 1159 432 363 432 1160 432 1160 431 1160 432 1160 431 1160 431 1160 431 364 431 1160 431 1160 431 1160 431 364 431 364 431 364 431 364 431 1160 431 364 431 364 431 364 431 1160 432 1160 431 1160 432 364 431 1160 431 1160 431 1161 431 1161 430 364 431 364 431 364 431 1160 432 364 431 364 431 364 432 364 431 1161 431 1161 431 364 431 364 431 1161 430 364 432 364 431 1161 430 365 431 365 431 1161 430 1161 430 365 431 1161 430 1161 430 365 430
|
||||
#
|
||||
# Model: Airwell Prime DCI Series
|
||||
name: Off
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 3078 3852 2004 888 1054 1824 1045 894 1051 865 2062 861 1078 860 1080 865 1046 894 1015 1883 1945 899 1013 901 1013 901 1012 902 1012 900 1042 927 986 902 1012 927 987 901 1012 902 1012 927 986 903 1011 902 1012 931 1011 931 1011 904 1010 933 1009 928 985 928 986 1885 1944 927 3017 3943 1943 927 985 1915 984 929 985 929 1943 957 984 929 985 928 985 929 985 1886 1943 899 984 930 983 930 984 957 986 929 985 929 985 930 984 930 983 930 984 930 1013 930 984 959 983 931 982 931 983 930 984 930 984 930 984 960 1011 931 984 1918 1939 929 3016 3917 1940 930 982 1916 954 959 954 959 1913 957 955 933 981 959 928 1015 954 1916 1913 959 953 960 957 986 927 1015 928 1015 953 961 927 987 927 986 927 987 927 986 927 1016 927 987 927 1016 926 1044 928 987 926 1015 928 988 926 987 926 988 926 1946 1883 987 3974
|
||||
#
|
||||
name: Dh
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 3060 3870 1026 888 1984 886 1026 888 1053 888 1026 887 1055 858 1055 858 1052 860 1024 891 1044 1854 1016 897 1975 1853 1975 925 1015 898 1015 898 1016 897 1016 898 1015 898 1016 898 1015 898 1015 898 1015 899 1015 899 1014 899 1014 899 1016 927 1014 900 1014 899 1014 1856 1974 926 3048 3883 1015 898 1975 897 1014 899 1015 899 1014 900 1014 899 1015 900 1013 900 1014 899 1014 1857 1014 900 1973 1855 1973 899 1012 901 1013 902 1011 926 987 927 987 926 987 927 987 955 987 926 988 926 987 927 1015 927 987 927 987 926 988 926 1016 927 1015 1884 1945 925 3020 3911 986 928 1946 925 986 927 986 928 986 928 986 927 987 927 987 928 986 928 986 1884 987 956 1946 1882 1946 925 986 928 986 927 986 928 985 928 986 928 986 928 986 928 985 928 985 929 959 954 984 930 984 987 931 955 959 956 958 955 959 1968 1891 980 3982
|
||||
#
|
||||
name: Cool_hi
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 3054 3879 1977 892 1020 1846 1083 838 1073 840 2031 859 1051 864 1047 864 1077 896 1014 927 986 928 986 928 986 1885 1943 927 985 929 1013 928 986 929 985 928 985 928 985 928 985 929 985 929 985 957 985 928 1015 928 1015 928 985 929 984 929 985 929 985 1886 1943 927 3017 3914 1943 928 984 1886 985 958 984 929 1972 957 984 958 984 929 984 930 984 929 984 930 984 930 983 1887 1942 929 983 930 984 930 984 930 983 959 984 930 984 930 983 930 984 930 984 930 984 930 983 931 983 931 983 959 984 931 983 931 983 1888 1941 930 3014 3943 1914 931 981 1915 955 959 955 959 1913 958 955 959 954 959 955 959 955 959 955 988 955 960 953 1917 1941 959 953 960 953 961 953 961 953 961 927 987 927 987 927 987 926 987 927 1017 926 988 926 988 925 988 925 988 926 988 925 1018 925 1972 1857 1014 3946
|
||||
#
|
||||
name: Cool_lo
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 3080 3850 2007 863 1049 1851 1048 888 1054 887 2012 886 1026 887 1025 888 1050 865 1045 1854 2029 871 1041 872 1040 873 1042 899 1043 899 1043 872 1015 898 1016 899 1041 872 1042 872 1015 926 1017 898 1016 927 1016 926 1016 899 1014 898 1015 926 1016 899 1015 898 1015 1856 1973 897 3048 3910 1947 898 1015 1884 1015 925 988 899 2003 953 988 900 1014 954 988 926 987 1857 1972 896 988 899 1014 900 1014 900 1013 927 987 929 1014 929 1013 926 987 927 986 927 987 927 987 927 987 927 986 927 987 927 986 985 958 928 986 927 986 927 1012 1860 1943 927 3018 3914 1943 955 986 1914 986 929 984 928 1944 955 957 930 984 957 985 956 958 1913 1915 956 957 957 956 957 931 1012 957 930 983 958 955 931 982 958 956 960 983 958 956 958 955 958 930 984 930 984 930 984 930 984 930 1013 930 984 930 985 928 1942 1887 983 3977
|
||||
#
|
||||
name: Heat_hi
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 3083 3873 2012 1843 2013 1873 1054 888 2011 887 1025 887 1025 887 1052 890 1048 1852 1017 896 1018 895 1018 896 1976 895 1017 898 1016 898 1015 898 1016 897 1016 897 1016 897 1017 897 1016 897 1017 900 1043 899 1014 897 1016 897 1016 898 1016 898 1015 898 1015 1857 1972 896 3048 3911 1947 1853 1975 1854 1015 898 1973 897 1016 927 1015 926 987 926 1016 1857 1014 926 987 899 1015 901 1970 926 987 927 987 926 988 955 988 1013 958 900 1014 926 987 900 1014 900 1014 900 1013 927 986 927 987 927 1016 955 987 927 987 955 987 1884 1946 928 3045 3912 1974 1883 1974 1883 987 927 1974 926 986 927 987 928 987 956 987 1942 986 956 986 928 986 928 1944 926 986 928 985 929 984 929 985 928 986 956 987 928 986 958 984 929 984 930 984 930 983 929 985 958 984 930 984 957 957 956 957 1887 1971 956 4003
|
||||
#
|
||||
name: Heat_lo
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 3108 3851 2062 1793 2006 1821 1103 839 2031 859 1085 829 1081 833 1079 836 1045 1911 1973 897 1015 898 1016 899 1041 871 1016 899 1014 898 1015 899 1015 899 1014 899 1041 872 1015 899 1041 872 1041 872 1015 899 1015 899 1041 873 1014 899 1041 873 1014 899 1014 1883 1975 900 3045 3886 1997 1856 1945 1857 1012 927 1945 900 1013 901 1012 901 1013 901 1012 1859 1999 901 1012 930 1012 903 1011 903 1010 903 1011 902 1012 960 1011 928 986 932 1010 903 1011 928 1015 928 985 929 985 928 1014 928 985 929 985 929 984 929 985 928 986 1915 1971 928 3017 3915 1942 1885 1943 1885 985 930 1971 929 984 930 983 930 984 930 984 1887 1942 929 983 960 983 931 982 931 983 932 981 958 985 958 956 958 984 959 954 931 983 932 981 959 955 932 982 959 954 960 982 961 983 933 955 988 955 985 929 1943 1915 958 4003
|
||||
#
|
||||
# Model: Danby DAC060EB7WDB
|
||||
name: Off
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 4402 4442 527 1629 529 549 529 1628 530 550 529 548 531 549 530 550 529 1630 528 549 530 549 529 549 530 1630 527 1629 529 1630 528 548 530 550 529 547 531 1628 530 1629 529 1628 530 1628 529 1628 530 1628 530 549 530 1628 530 1628 530 1627 531 1628 530 1627 531 1631 527 1629 529 1628 530 1627 531 1628 530 1628 530 1629 529 1627 531 1627 531 1628 529 1627 531 1627 531 1629 529 1627 530 549 529 549 530 549 530 1628 529 1627 530 5234 4401 4440 530 550 528 1628 529 549 530 1628 529 1629 528 1626 531 1628 529 550 529 1628 530 1627 531 1629 529 549 529 548 530 549 530 1628 529 1628 530 1627 530 547 532 547 532 547 531 548 531 548 530 548 531 1626 531 549 530 547 531 547 531 548 530 548 530 549 530 548 531 546 532 578 500 547 532 548 531 548 531 548 530 548 531 548 530 548 531 547 531 547 532 547 531 1627 531 1627 530 1626 532 547 531 547 532
|
||||
#
|
||||
name: Dh
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 4454 4387 586 1573 585 494 584 1571 586 494 584 493 585 524 554 493 531 1626 586 1573 585 494 585 492 586 492 586 494 585 493 585 493 586 1571 586 493 585 1572 531 1627 530 549 584 494 586 1571 587 1572 529 1628 529 1628 530 1627 530 1626 532 1627 531 1626 532 1628 529 1627 531 1626 531 1627 531 1627 587 1569 532 1625 533 1626 532 1626 532 1627 531 1627 530 548 531 1626 532 1627 531 548 531 1627 531 548 531 546 532 547 531 5233 4401 4443 530 548 530 1627 530 547 531 1627 531 1626 531 1626 531 1627 530 549 530 548 530 1627 531 1627 531 1627 530 1627 531 1627 531 1626 531 548 530 1627 530 547 532 547 532 1627 531 1627 532 546 531 547 531 548 530 548 530 548 531 548 531 548 530 548 530 549 530 548 531 548 531 548 530 547 532 549 529 548 530 548 531 547 532 548 530 548 531 1627 530 548 530 548 531 1626 533 546 531 1627 530 1627 532 1626 530
|
||||
#
|
||||
name: Cool_hi
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 4492 4354 619 1537 619 459 621 1537 622 455 623 456 623 457 622 456 623 1535 622 1536 622 458 621 456 623 1536 621 1535 623 456 622 456 623 457 621 456 531 1627 621 1536 622 456 622 457 622 455 623 458 621 458 621 1537 621 1536 620 1539 618 1538 531 1628 531 1627 530 1628 530 1628 530 1627 531 1628 530 1628 530 1628 531 1627 530 1629 529 1628 529 1628 530 549 530 1627 531 1628 530 1628 530 1627 586 494 530 1627 530 549 530 5232 4400 4443 586 492 587 1571 587 493 585 1572 530 1628 586 1572 586 1572 586 492 587 493 586 1572 586 1571 586 492 587 493 585 1572 531 1627 585 1573 585 1572 585 492 586 494 585 1572 586 1571 531 1627 531 1628 530 1627 587 491 531 548 587 492 530 548 530 547 532 548 531 547 532 547 531 548 531 547 532 547 531 548 588 491 530 547 589 490 531 547 532 1626 532 548 531 548 531 547 532 547 532 1627 531 548 531 1626 532
|
||||
#
|
||||
name: Cool_lo
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 4401 4441 528 1629 529 550 528 1628 529 551 528 550 528 551 527 551 528 1629 529 1629 529 550 529 1630 528 551 528 549 530 550 529 551 528 549 529 550 529 1629 529 1628 530 549 530 1629 529 550 529 1628 529 1629 529 1631 527 1628 530 1628 529 1629 528 1628 530 1629 529 1629 529 1629 529 1629 528 1629 529 1629 529 1630 528 1629 529 1629 529 1628 529 1629 528 551 528 1629 529 550 529 550 530 548 529 1631 527 551 528 1629 529 5235 4402 4439 530 550 528 1629 529 549 530 1628 529 1629 529 1628 530 1629 529 549 530 550 529 1628 530 552 526 1628 529 1628 530 1628 530 1627 531 1628 529 1629 528 551 528 550 529 1628 530 550 528 1628 529 549 529 550 528 550 529 549 530 548 530 551 528 550 528 578 500 550 529 550 529 551 527 549 530 549 529 549 529 550 528 548 530 550 528 549 529 1629 528 550 529 1630 528 1628 530 1628 530 549 530 1628 529 549 529
|
||||
#
|
||||
# Model: Carrier 42QHB12D8S
|
||||
name: Off
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 4467 4363 599 1556 599 478 599 1556 599 1558 597 505 572 505 572 1583 571 505 572 506 624 1531 653 423 651 426 624 1530 622 1532 572 505 572 1583 571 506 571 1584 571 1583 571 1584 571 1584 571 507 570 1585 570 1585 570 1585 570 508 569 508 569 508 592 485 570 1585 593 484 570 508 569 1586 569 1586 592 1563 593 485 569 508 592 485 592 485 570 508 569 508 570 508 569 508 569 1586 569 1586 569 1586 569 1586 569 1586 569 5187 4461 4371 568 1586 569 508 593 1562 593 1563 569 509 591 486 591 1563 569 508 592 486 592 1563 592 485 592 486 591 1563 592 1563 591 486 592 1564 591 486 592 1563 593 1563 591 1563 592 1564 592 485 592 1563 592 1563 592 1564 591 486 591 486 592 485 592 485 592 1563 592 486 591 486 592 1564 591 1563 592 1563 592 486 592 485 592 486 591 486 592 485 592 486 591 486 591 486 591 1563 592 1563 593 1563 591 1564 591 1563 591
|
||||
#
|
||||
name: Dh
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 4440 4390 571 1583 572 505 572 1583 596 1559 571 505 572 505 572 1583 596 481 596 481 597 1559 625 451 654 423 625 1529 595 1560 596 480 572 1583 572 505 596 482 594 483 571 1583 571 1584 571 1584 571 1584 571 1585 569 1585 593 1562 594 1561 593 485 569 508 593 484 592 485 593 484 592 485 592 1563 569 508 592 1562 592 485 570 1586 592 485 592 486 569 1586 592 485 569 1585 570 508 569 1586 569 508 569 1585 570 1586 569 5186 4438 4393 569 1585 593 485 592 1562 569 1585 569 508 569 508 569 1585 591 486 593 484 591 1563 591 486 591 486 590 1564 569 1585 569 508 593 1562 592 486 592 485 569 508 591 1563 592 1562 569 1586 569 1586 591 1563 592 1563 590 1564 591 1563 592 486 569 508 569 508 569 508 569 508 592 486 592 1563 568 508 593 1563 591 486 592 1563 569 508 592 486 592 1563 591 486 592 1563 592 485 592 1563 592 486 592 1563 591 1563 592
|
||||
#
|
||||
name: Cool_hi
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 4465 4365 598 1557 598 479 598 1557 598 1557 598 479 598 479 598 1556 599 479 598 507 593 1562 652 424 624 452 595 1559 595 1560 594 483 571 1584 594 1561 593 484 593 1562 593 1562 593 1562 593 1562 593 1562 593 1563 592 485 592 1562 593 484 593 485 592 485 592 485 592 485 592 485 592 485 592 485 592 485 592 485 592 485 592 485 592 485 592 485 592 1562 592 1563 592 1562 593 1562 592 1563 592 1563 592 1562 592 1563 592 5165 4439 4394 569 1586 592 485 569 1586 569 1586 569 508 569 508 593 1562 592 485 570 508 592 1563 592 485 594 484 569 1586 569 1586 569 508 569 1586 592 1563 569 508 592 1563 569 1586 592 1563 592 1563 569 1586 569 1585 569 508 569 1586 569 508 569 508 569 508 569 508 592 485 569 508 592 485 569 508 593 485 569 508 569 508 569 508 593 484 570 508 569 1586 593 1562 570 1586 569 1586 592 1563 569 1586 592 1563 592 1563 592
|
||||
#
|
||||
name: Cool_lo
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 4465 4364 599 1556 599 479 598 1556 599 1556 599 478 599 479 598 1559 596 505 572 506 571 1584 653 424 624 452 571 1583 572 1583 571 506 571 1583 571 1584 571 506 571 1584 571 1585 570 1585 570 1585 592 1563 592 1562 593 485 592 1563 592 485 593 485 592 485 592 485 592 485 592 485 593 485 592 1563 592 485 592 1563 592 485 592 485 592 485 592 485 592 1563 592 485 592 1563 592 485 592 1563 592 1563 592 1563 592 1563 592 5164 4460 4372 592 1563 592 485 593 1563 592 1563 592 486 591 486 591 1563 592 485 592 485 592 1563 592 485 592 485 592 1563 592 1563 592 485 592 1563 592 1563 592 485 592 1563 592 1563 592 1563 592 1563 592 1563 592 1564 591 486 591 1563 591 485 592 485 592 485 592 485 592 485 592 485 592 485 592 1563 592 485 592 1563 591 486 591 485 592 486 591 485 592 1563 592 485 592 1563 592 485 592 1564 591 1563 592 1563 592 1563 592
|
||||
#
|
||||
name: Heat_hi
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 4440 4391 572 1583 572 505 572 1584 571 1583 572 505 572 505 572 1583 596 481 573 505 596 1559 626 451 655 422 625 1529 596 1559 572 505 572 1583 572 1582 572 505 572 1583 572 1583 571 1584 571 1584 571 1585 570 1584 594 484 593 1562 592 485 592 485 592 485 593 485 593 484 593 484 593 1562 593 484 593 1562 593 1563 592 1562 592 1563 592 485 593 484 592 485 593 1562 593 484 593 485 592 485 592 485 592 1562 593 1563 592 5163 4462 4370 592 1563 592 485 592 1563 592 1563 592 485 592 485 592 1563 592 485 592 485 593 1562 593 485 593 485 592 1563 592 1563 592 485 592 1562 593 1563 592 484 593 1563 592 1563 592 1563 592 1563 592 1563 592 1563 592 485 592 1563 592 485 592 485 592 485 592 485 592 485 593 485 592 1563 592 485 592 1563 592 1563 592 1563 592 1563 592 485 592 485 592 485 592 1563 591 485 592 486 591 485 592 485 593 1563 591 1563 593
|
||||
#
|
||||
name: Heat_lo
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 4467 4390 571 1583 572 505 595 1560 572 1583 572 505 572 505 596 1559 596 482 596 481 597 1559 626 451 655 422 625 1529 596 1559 596 481 572 1582 573 1583 571 505 572 1583 595 1560 594 1561 592 1562 594 1561 593 1562 593 484 593 1563 592 485 592 485 592 485 592 485 593 484 593 485 592 485 592 1562 593 485 592 1563 592 1562 593 1562 594 483 593 485 593 1562 592 485 593 1561 593 484 593 484 593 484 593 1562 593 1562 592 5163 4462 4370 592 1563 593 484 592 1563 592 1563 592 485 592 485 593 1562 593 484 593 485 592 1562 593 484 593 485 592 1562 593 1562 593 485 592 1563 592 1563 592 485 592 1563 592 1562 593 1562 593 1563 592 1563 592 1562 592 485 593 1562 592 485 592 485 592 485 592 485 592 485 592 485 592 485 592 1563 592 485 592 1563 591 1563 592 1563 593 485 592 485 592 1563 592 485 592 1563 591 485 593 485 592 485 592 1563 592 1563 591
|
||||
|
||||
113
documentation/FuriHalBus.md
Normal file
113
documentation/FuriHalBus.md
Normal file
@ -0,0 +1,113 @@
|
||||
# Using FuriHalBus API
|
||||
|
||||
## Basic info
|
||||
|
||||
On system startup, most of the peripheral devices are under reset and not clocked by default. This is done to reduce power consumption and to guarantee that the device will always be in the same state before use.
|
||||
Some crucial peripherals are enabled right away by the system, others must be explicitly enabled by the user code.
|
||||
|
||||
**NOTE:** Here and afterwards the word *"system"* refers to any code belonging to the operating system, hardware drivers or built-in applications.
|
||||
|
||||
To **ENABLE** a peripheral, call `furi_hal_bus_enable()`. At the time of the call, the peripheral in question MUST be disabled, otherwise a crash will occur to indicate improper use. This means that any given peripheral cannot be enabled twice or more without disabling it first.
|
||||
|
||||
To **DISABLE** a peripheral, call `furi_hal_bus_disable()`. Likewise, the peripheral in question MUST be enabled, otherwise a crash will occur.
|
||||
|
||||
To **RESET** a peripheral, call `furi_hal_bus_reset()`. The peripheral in question MUST be enabled, otherwise a crash will occur. This method is used whenever it is necessary to reset all the peripheral's registers to their initial states without disabling it.
|
||||
|
||||
## Peripherals
|
||||
|
||||
Built-in peripherals are divided into three categories:
|
||||
- Enabled by the system on startup, never disabled;
|
||||
- Enabled and disabled by the system on demand;
|
||||
- Enabled and disabled by the user code.
|
||||
|
||||
### Always-on peripherals
|
||||
|
||||
Below is the list of peripherals that are enabled by the system. The user code must NEVER attempt to disable them. If a corresponding API is provided, the user code must employ it in order to access the peripheral.
|
||||
|
||||
*Table 1* - Peripherals enabled by the system
|
||||
|
||||
| Peripheral | Enabled at |
|
||||
| :-----------: | :-----------------------: |
|
||||
| DMA1 | `furi_hal_dma.c` |
|
||||
| DMA2 | -- |
|
||||
| DMAMUX | -- |
|
||||
| GPIOA | `furi_hal_resources.c` |
|
||||
| GPIOB | -- |
|
||||
| GPIOC | -- |
|
||||
| GPIOD | -- |
|
||||
| GPIOE | -- |
|
||||
| GPIOH | -- |
|
||||
| PKA | `furi_hal_bt.c` |
|
||||
| AES2 | -- |
|
||||
| HSEM | -- |
|
||||
| IPCC | -- |
|
||||
| FLASH | enabled by hardware |
|
||||
|
||||
### On-demand system peripherals
|
||||
|
||||
Below is the list of peripherals that are enabled and disabled by the system. The user code must avoid using them directly, preferring the respective APIs instead.
|
||||
|
||||
When not using the API, these peripherals MUST be enabled by the user code and then disabled when not needed anymore.
|
||||
|
||||
*Table 2* - Peripherals enabled and disabled by the system
|
||||
|
||||
| Peripheral | API header file |
|
||||
| :-----------: | :-------------------: |
|
||||
| RNG | `furi_hal_random.h` |
|
||||
| SPI1 | `furi_hal_spi.h` |
|
||||
| SPI2 | -- |
|
||||
| I2C1 | `furi_hal_i2c.h` |
|
||||
| I2C3 | -- |
|
||||
| USART1 | `furi_hal_uart.h` |
|
||||
| LPUART1 | -- |
|
||||
| USB | `furi_hal_usb.h` |
|
||||
|
||||
### On-demand shared peripherals
|
||||
|
||||
Below is the list of peripherals that are not enabled by default and MUST be enabled by the user code each time it accesses them.
|
||||
|
||||
Note that some of these peripherals may also be used by the system to implement its certain features.
|
||||
The system will take over any given peripheral only when the respective feature is in use.
|
||||
|
||||
*Table 3* - Peripherals enabled and disabled by user
|
||||
|
||||
| Peripheral | System | Purpose |
|
||||
| :-----------: | :-------: | ------------------------------------- |
|
||||
| CRC | | |
|
||||
| TSC | | |
|
||||
| ADC | | |
|
||||
| QUADSPI | | |
|
||||
| TIM1 | yes | subghz, lfrfid, nfc, infrared, etc... |
|
||||
| TIM2 | yes | -- |
|
||||
| TIM16 | yes | speaker |
|
||||
| TIM17 | | |
|
||||
| LPTIM1 | yes | tickless idle timer |
|
||||
| LPTIM2 | yes | pwm |
|
||||
| SAI1 | | |
|
||||
| LCD | | |
|
||||
|
||||
|
||||
## DMA
|
||||
|
||||
The DMA1,2 peripherals are a special case in that they have multiple independent channels. Some of the channels may be in use by the system.
|
||||
|
||||
Below is the list of DMA channels and their usage by the system.
|
||||
|
||||
*Table 4* - DMA channels
|
||||
|
||||
| DMA | Channel | System | Purpose |
|
||||
| :---: | :-------: | :-------: | ------------------------- |
|
||||
| DMA1 | 1 | yes | digital signal |
|
||||
| -- | 2 | yes | -- |
|
||||
| -- | 3 | | |
|
||||
| -- | 4 | yes | pulse reader |
|
||||
| -- | 5 | | |
|
||||
| -- | 6 | | |
|
||||
| -- | 7 | | |
|
||||
| DMA2 | 1 | yes | infrared, lfrfid, subghz |
|
||||
| -- | 2 | yes | -- |
|
||||
| -- | 3 | yes | SPI |
|
||||
| -- | 4 | yes | SPI |
|
||||
| -- | 5 | | |
|
||||
| -- | 6 | | |
|
||||
| -- | 7 | | |
|
||||
@ -114,6 +114,8 @@ To run cleanup (think of `make clean`) for specified targets, add the `-c` optio
|
||||
Default configuration variables are set in the configuration file: `fbt_options.py`.
|
||||
Values set in the command line have higher precedence over the configuration file.
|
||||
|
||||
You can also create a file called `fbt_options_local.py` that will be evaluated when loading default options file, enabling persisent overriding of default options without modifying default configuration.
|
||||
|
||||
You can find out available options with `./fbt -h`.
|
||||
|
||||
### Firmware application set
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
from pathlib import Path
|
||||
import posixpath
|
||||
|
||||
# For more details on these options, run 'fbt -h'
|
||||
|
||||
FIRMWARE_ORIGIN = "Official"
|
||||
|
||||
# Default hardware target
|
||||
TARGET_HW = 7
|
||||
@ -75,3 +77,8 @@ FIRMWARE_APPS = {
|
||||
}
|
||||
|
||||
FIRMWARE_APP_SET = "default"
|
||||
|
||||
custom_options_fn = "fbt_options_local.py"
|
||||
|
||||
if Path(custom_options_fn).exists():
|
||||
exec(compile(Path(custom_options_fn).read_text(), custom_options_fn, "exec"))
|
||||
|
||||
@ -18,6 +18,7 @@ env = ENV.Clone(
|
||||
"fbt_apps",
|
||||
"pvsstudio",
|
||||
"fbt_hwtarget",
|
||||
"fbt_envhooks",
|
||||
],
|
||||
COMPILATIONDB_USE_ABSPATH=False,
|
||||
BUILD_DIR=fw_build_meta["build_dir"],
|
||||
@ -72,6 +73,8 @@ env = ENV.Clone(
|
||||
_APP_ICONS=None,
|
||||
)
|
||||
|
||||
env.PreConfigureFwEnvionment()
|
||||
|
||||
if env["IS_BASE_FIRMWARE"]:
|
||||
env.Append(
|
||||
FIRMWARE_BUILD_CFG="firmware",
|
||||
@ -100,6 +103,13 @@ lib_targets = env.BuildModules(
|
||||
],
|
||||
)
|
||||
|
||||
# Configure firmware origin definitions
|
||||
env.Append(
|
||||
CPPDEFINES=[
|
||||
env.subst("FW_ORIGIN_${FIRMWARE_ORIGIN}"),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
# Now, env is fully set up with everything to build apps
|
||||
fwenv = env.Clone(FW_ARTIFACTS=[])
|
||||
@ -271,5 +281,6 @@ if should_gen_cdb_and_link_dir(fwenv, BUILD_TARGETS):
|
||||
|
||||
Alias(fwenv["FIRMWARE_BUILD_CFG"] + "_all", fw_artifacts)
|
||||
|
||||
env.PostConfigureFwEnvionment()
|
||||
|
||||
Return("fwenv")
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
entry,status,name,type,params
|
||||
Version,+,26.3,,
|
||||
Version,+,28.1,,
|
||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||
Header,+,applications/services/cli/cli.h,,
|
||||
Header,+,applications/services/cli/cli_vcp.h,,
|
||||
@ -40,8 +40,10 @@ Header,-,firmware/targets/f18/furi_hal/furi_hal_power_calibration.h,,
|
||||
Header,+,firmware/targets/f18/furi_hal/furi_hal_resources.h,,
|
||||
Header,+,firmware/targets/f18/furi_hal/furi_hal_spi_config.h,,
|
||||
Header,+,firmware/targets/f18/furi_hal/furi_hal_target_hw.h,,
|
||||
Header,+,firmware/targets/f7/furi_hal/furi_hal_bus.h,,
|
||||
Header,+,firmware/targets/f7/furi_hal/furi_hal_clock.h,,
|
||||
Header,+,firmware/targets/f7/furi_hal/furi_hal_console.h,,
|
||||
Header,+,firmware/targets/f7/furi_hal/furi_hal_dma.h,,
|
||||
Header,+,firmware/targets/f7/furi_hal/furi_hal_flash.h,,
|
||||
Header,+,firmware/targets/f7/furi_hal/furi_hal_gpio.h,,
|
||||
Header,+,firmware/targets/f7/furi_hal/furi_hal_i2c_config.h,,
|
||||
@ -129,6 +131,7 @@ Header,+,lib/one_wire/maxim_crc.h,,
|
||||
Header,+,lib/one_wire/one_wire_host.h,,
|
||||
Header,+,lib/one_wire/one_wire_slave.h,,
|
||||
Header,+,lib/print/wrappers.h,,
|
||||
Header,+,lib/pulse_reader/pulse_reader.h,,
|
||||
Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_adc.h,,
|
||||
Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_bus.h,,
|
||||
Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_comp.h,,
|
||||
@ -156,7 +159,7 @@ Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_tim.h,,
|
||||
Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_usart.h,,
|
||||
Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_utils.h,,
|
||||
Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_wwdg.h,,
|
||||
Header,+,lib/pulse_reader/pulse_reader.h,,
|
||||
Header,+,lib/toolbox/api_lock.h,,
|
||||
Header,+,lib/toolbox/args.h,,
|
||||
Header,+,lib/toolbox/crc32_calc.h,,
|
||||
Header,+,lib/toolbox/dir_walk.h,,
|
||||
@ -872,6 +875,12 @@ Function,+,furi_hal_bt_stop_tone_tx,void,
|
||||
Function,+,furi_hal_bt_unlock_core2,void,
|
||||
Function,+,furi_hal_bt_update_battery_level,void,uint8_t
|
||||
Function,+,furi_hal_bt_update_power_state,void,
|
||||
Function,+,furi_hal_bus_deinit_early,void,
|
||||
Function,+,furi_hal_bus_disable,void,FuriHalBus
|
||||
Function,+,furi_hal_bus_enable,void,FuriHalBus
|
||||
Function,+,furi_hal_bus_init_early,void,
|
||||
Function,+,furi_hal_bus_is_enabled,_Bool,FuriHalBus
|
||||
Function,+,furi_hal_bus_reset,void,FuriHalBus
|
||||
Function,+,furi_hal_cdc_get_ctrl_line_state,uint8_t,uint8_t
|
||||
Function,+,furi_hal_cdc_get_port_settings,usb_cdc_line_coding*,uint8_t
|
||||
Function,+,furi_hal_cdc_receive,int32_t,"uint8_t, uint8_t*, uint16_t"
|
||||
@ -914,6 +923,8 @@ Function,+,furi_hal_debug_disable,void,
|
||||
Function,+,furi_hal_debug_enable,void,
|
||||
Function,+,furi_hal_debug_is_gdb_session_active,_Bool,
|
||||
Function,-,furi_hal_deinit_early,void,
|
||||
Function,+,furi_hal_dma_deinit_early,void,
|
||||
Function,+,furi_hal_dma_init_early,void,
|
||||
Function,-,furi_hal_flash_erase,void,uint8_t
|
||||
Function,-,furi_hal_flash_get_base,size_t,
|
||||
Function,-,furi_hal_flash_get_cycles_count,size_t,
|
||||
@ -1032,6 +1043,7 @@ Function,+,furi_hal_pwm_start,void,"FuriHalPwmOutputId, uint32_t, uint8_t"
|
||||
Function,+,furi_hal_pwm_stop,void,FuriHalPwmOutputId
|
||||
Function,+,furi_hal_random_fill_buf,void,"uint8_t*, uint32_t"
|
||||
Function,+,furi_hal_random_get,uint32_t,
|
||||
Function,+,furi_hal_random_init,void,
|
||||
Function,+,furi_hal_region_get,const FuriHalRegion*,
|
||||
Function,+,furi_hal_region_get_band,const FuriHalRegionBand*,uint32_t
|
||||
Function,+,furi_hal_region_get_name,const char*,
|
||||
@ -1047,6 +1059,8 @@ Function,+,furi_hal_rtc_datetime_to_timestamp,uint32_t,FuriHalRtcDateTime*
|
||||
Function,-,furi_hal_rtc_deinit_early,void,
|
||||
Function,+,furi_hal_rtc_get_boot_mode,FuriHalRtcBootMode,
|
||||
Function,+,furi_hal_rtc_get_datetime,void,FuriHalRtcDateTime*
|
||||
Function,+,furi_hal_rtc_get_days_per_month,uint8_t,"_Bool, uint8_t"
|
||||
Function,+,furi_hal_rtc_get_days_per_year,uint16_t,uint16_t
|
||||
Function,+,furi_hal_rtc_get_fault_data,uint32_t,
|
||||
Function,+,furi_hal_rtc_get_heap_track_mode,FuriHalRtcHeapTrackMode,
|
||||
Function,+,furi_hal_rtc_get_locale_dateformat,FuriHalRtcLocaleDateFormat,
|
||||
@ -1059,6 +1073,7 @@ Function,+,furi_hal_rtc_get_timestamp,uint32_t,
|
||||
Function,-,furi_hal_rtc_init,void,
|
||||
Function,-,furi_hal_rtc_init_early,void,
|
||||
Function,+,furi_hal_rtc_is_flag_set,_Bool,FuriHalRtcFlag
|
||||
Function,+,furi_hal_rtc_is_leap_year,_Bool,uint16_t
|
||||
Function,+,furi_hal_rtc_reset_flag,void,FuriHalRtcFlag
|
||||
Function,+,furi_hal_rtc_set_boot_mode,void,FuriHalRtcBootMode
|
||||
Function,+,furi_hal_rtc_set_datetime,void,FuriHalRtcDateTime*
|
||||
@ -1988,6 +2003,8 @@ Function,-,vdprintf,int,"int, const char*, __gnuc_va_list"
|
||||
Function,+,version_get,const Version*,
|
||||
Function,+,version_get_builddate,const char*,const Version*
|
||||
Function,+,version_get_dirty_flag,_Bool,const Version*
|
||||
Function,+,version_get_firmware_origin,const char*,const Version*
|
||||
Function,+,version_get_git_origin,const char*,const Version*
|
||||
Function,+,version_get_gitbranch,const char*,const Version*
|
||||
Function,+,version_get_gitbranchnum,const char*,const Version*
|
||||
Function,+,version_get_githash,const char*,const Version*
|
||||
|
||||
|
@ -9,6 +9,8 @@
|
||||
void furi_hal_init_early() {
|
||||
furi_hal_cortex_init_early();
|
||||
furi_hal_clock_init_early();
|
||||
furi_hal_bus_init_early();
|
||||
furi_hal_dma_init_early();
|
||||
furi_hal_resources_init_early();
|
||||
furi_hal_os_init();
|
||||
furi_hal_spi_config_init_early();
|
||||
@ -22,12 +24,15 @@ void furi_hal_deinit_early() {
|
||||
furi_hal_i2c_deinit_early();
|
||||
furi_hal_spi_config_deinit_early();
|
||||
furi_hal_resources_deinit_early();
|
||||
furi_hal_dma_deinit_early();
|
||||
furi_hal_bus_deinit_early();
|
||||
furi_hal_clock_deinit_early();
|
||||
}
|
||||
|
||||
void furi_hal_init() {
|
||||
furi_hal_mpu_init();
|
||||
furi_hal_clock_init();
|
||||
furi_hal_random_init();
|
||||
furi_hal_console_init();
|
||||
furi_hal_rtc_init();
|
||||
furi_hal_interrupt_init();
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
#include <furi_hal_resources.h>
|
||||
#include <furi_hal_bus.h>
|
||||
#include <furi.h>
|
||||
|
||||
#include <stm32wbxx_ll_rcc.h>
|
||||
@ -118,6 +119,13 @@ static void furi_hal_resources_init_input_pins(GpioMode mode) {
|
||||
}
|
||||
|
||||
void furi_hal_resources_init_early() {
|
||||
furi_hal_bus_enable(FuriHalBusGPIOA);
|
||||
furi_hal_bus_enable(FuriHalBusGPIOB);
|
||||
furi_hal_bus_enable(FuriHalBusGPIOC);
|
||||
furi_hal_bus_enable(FuriHalBusGPIOD);
|
||||
furi_hal_bus_enable(FuriHalBusGPIOE);
|
||||
furi_hal_bus_enable(FuriHalBusGPIOH);
|
||||
|
||||
furi_hal_resources_init_input_pins(GpioModeInput);
|
||||
|
||||
// SD Card stepdown control
|
||||
@ -162,6 +170,12 @@ void furi_hal_resources_init_early() {
|
||||
|
||||
void furi_hal_resources_deinit_early() {
|
||||
furi_hal_resources_init_input_pins(GpioModeAnalog);
|
||||
furi_hal_bus_disable(FuriHalBusGPIOA);
|
||||
furi_hal_bus_disable(FuriHalBusGPIOB);
|
||||
furi_hal_bus_disable(FuriHalBusGPIOC);
|
||||
furi_hal_bus_disable(FuriHalBusGPIOD);
|
||||
furi_hal_bus_disable(FuriHalBusGPIOE);
|
||||
furi_hal_bus_disable(FuriHalBusGPIOH);
|
||||
}
|
||||
|
||||
void furi_hal_resources_init() {
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
#include <furi_hal_spi_config.h>
|
||||
#include <furi_hal_resources.h>
|
||||
#include <furi_hal_bus.h>
|
||||
#include <furi_hal_spi.h>
|
||||
#include <furi.h>
|
||||
|
||||
@ -96,28 +97,17 @@ void furi_hal_spi_config_init() {
|
||||
static void furi_hal_spi_bus_r_event_callback(FuriHalSpiBus* bus, FuriHalSpiBusEvent event) {
|
||||
if(event == FuriHalSpiBusEventInit) {
|
||||
furi_hal_spi_bus_r_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1);
|
||||
FURI_CRITICAL_EXIT();
|
||||
bus->current_handle = NULL;
|
||||
} else if(event == FuriHalSpiBusEventDeinit) {
|
||||
furi_mutex_free(furi_hal_spi_bus_r_mutex);
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1);
|
||||
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI1);
|
||||
FURI_CRITICAL_EXIT();
|
||||
} else if(event == FuriHalSpiBusEventLock) {
|
||||
furi_check(furi_mutex_acquire(furi_hal_spi_bus_r_mutex, FuriWaitForever) == FuriStatusOk);
|
||||
} else if(event == FuriHalSpiBusEventUnlock) {
|
||||
furi_check(furi_mutex_release(furi_hal_spi_bus_r_mutex) == FuriStatusOk);
|
||||
} else if(event == FuriHalSpiBusEventActivate) {
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI1);
|
||||
FURI_CRITICAL_EXIT();
|
||||
furi_hal_bus_enable(FuriHalBusSPI1);
|
||||
} else if(event == FuriHalSpiBusEventDeactivate) {
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1);
|
||||
FURI_CRITICAL_EXIT();
|
||||
furi_hal_bus_disable(FuriHalBusSPI1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,28 +121,17 @@ FuriMutex* furi_hal_spi_bus_d_mutex = NULL;
|
||||
static void furi_hal_spi_bus_d_event_callback(FuriHalSpiBus* bus, FuriHalSpiBusEvent event) {
|
||||
if(event == FuriHalSpiBusEventInit) {
|
||||
furi_hal_spi_bus_d_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2);
|
||||
FURI_CRITICAL_EXIT();
|
||||
bus->current_handle = NULL;
|
||||
} else if(event == FuriHalSpiBusEventDeinit) {
|
||||
furi_mutex_free(furi_hal_spi_bus_d_mutex);
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2);
|
||||
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI2);
|
||||
FURI_CRITICAL_EXIT();
|
||||
} else if(event == FuriHalSpiBusEventLock) {
|
||||
furi_check(furi_mutex_acquire(furi_hal_spi_bus_d_mutex, FuriWaitForever) == FuriStatusOk);
|
||||
} else if(event == FuriHalSpiBusEventUnlock) {
|
||||
furi_check(furi_mutex_release(furi_hal_spi_bus_d_mutex) == FuriStatusOk);
|
||||
} else if(event == FuriHalSpiBusEventActivate) {
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI2);
|
||||
FURI_CRITICAL_EXIT();
|
||||
furi_hal_bus_enable(FuriHalBusSPI2);
|
||||
} else if(event == FuriHalSpiBusEventDeactivate) {
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2);
|
||||
FURI_CRITICAL_EXIT();
|
||||
furi_hal_bus_disable(FuriHalBusSPI2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
entry,status,name,type,params
|
||||
Version,+,26.3,,
|
||||
Version,+,28.1,,
|
||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||
Header,+,applications/services/cli/cli.h,,
|
||||
Header,+,applications/services/cli/cli_vcp.h,,
|
||||
@ -36,8 +36,10 @@ Header,+,applications/services/notification/notification_messages.h,,
|
||||
Header,+,applications/services/power/power_service/power.h,,
|
||||
Header,+,applications/services/rpc/rpc_app.h,,
|
||||
Header,+,applications/services/storage/storage.h,,
|
||||
Header,+,firmware/targets/f7/furi_hal/furi_hal_bus.h,,
|
||||
Header,+,firmware/targets/f7/furi_hal/furi_hal_clock.h,,
|
||||
Header,+,firmware/targets/f7/furi_hal/furi_hal_console.h,,
|
||||
Header,+,firmware/targets/f7/furi_hal/furi_hal_dma.h,,
|
||||
Header,+,firmware/targets/f7/furi_hal/furi_hal_flash.h,,
|
||||
Header,+,firmware/targets/f7/furi_hal/furi_hal_gpio.h,,
|
||||
Header,+,firmware/targets/f7/furi_hal/furi_hal_i2c_config.h,,
|
||||
@ -190,6 +192,7 @@ Header,+,lib/subghz/subghz_setting.h,,
|
||||
Header,+,lib/subghz/subghz_tx_rx_worker.h,,
|
||||
Header,+,lib/subghz/subghz_worker.h,,
|
||||
Header,+,lib/subghz/transmitter.h,,
|
||||
Header,+,lib/toolbox/api_lock.h,,
|
||||
Header,+,lib/toolbox/args.h,,
|
||||
Header,+,lib/toolbox/crc32_calc.h,,
|
||||
Header,+,lib/toolbox/dir_walk.h,,
|
||||
@ -1064,6 +1067,12 @@ Function,+,furi_hal_bt_stop_tone_tx,void,
|
||||
Function,+,furi_hal_bt_unlock_core2,void,
|
||||
Function,+,furi_hal_bt_update_battery_level,void,uint8_t
|
||||
Function,+,furi_hal_bt_update_power_state,void,
|
||||
Function,+,furi_hal_bus_deinit_early,void,
|
||||
Function,+,furi_hal_bus_disable,void,FuriHalBus
|
||||
Function,+,furi_hal_bus_enable,void,FuriHalBus
|
||||
Function,+,furi_hal_bus_init_early,void,
|
||||
Function,+,furi_hal_bus_is_enabled,_Bool,FuriHalBus
|
||||
Function,+,furi_hal_bus_reset,void,FuriHalBus
|
||||
Function,+,furi_hal_cdc_get_ctrl_line_state,uint8_t,uint8_t
|
||||
Function,+,furi_hal_cdc_get_port_settings,usb_cdc_line_coding*,uint8_t
|
||||
Function,+,furi_hal_cdc_receive,int32_t,"uint8_t, uint8_t*, uint16_t"
|
||||
@ -1106,6 +1115,8 @@ Function,+,furi_hal_debug_disable,void,
|
||||
Function,+,furi_hal_debug_enable,void,
|
||||
Function,+,furi_hal_debug_is_gdb_session_active,_Bool,
|
||||
Function,-,furi_hal_deinit_early,void,
|
||||
Function,+,furi_hal_dma_deinit_early,void,
|
||||
Function,+,furi_hal_dma_init_early,void,
|
||||
Function,-,furi_hal_flash_erase,void,uint8_t
|
||||
Function,-,furi_hal_flash_get_base,size_t,
|
||||
Function,-,furi_hal_flash_get_cycles_count,size_t,
|
||||
@ -1272,6 +1283,7 @@ Function,+,furi_hal_pwm_start,void,"FuriHalPwmOutputId, uint32_t, uint8_t"
|
||||
Function,+,furi_hal_pwm_stop,void,FuriHalPwmOutputId
|
||||
Function,+,furi_hal_random_fill_buf,void,"uint8_t*, uint32_t"
|
||||
Function,+,furi_hal_random_get,uint32_t,
|
||||
Function,+,furi_hal_random_init,void,
|
||||
Function,+,furi_hal_region_get,const FuriHalRegion*,
|
||||
Function,+,furi_hal_region_get_band,const FuriHalRegionBand*,uint32_t
|
||||
Function,+,furi_hal_region_get_name,const char*,
|
||||
@ -1283,35 +1295,29 @@ Function,-,furi_hal_resources_deinit_early,void,
|
||||
Function,+,furi_hal_resources_get_ext_pin_number,int32_t,const GpioPin*
|
||||
Function,-,furi_hal_resources_init,void,
|
||||
Function,-,furi_hal_resources_init_early,void,
|
||||
Function,+,furi_hal_rfid_change_read_config,void,"float, float"
|
||||
Function,+,furi_hal_rfid_comp_set_callback,void,"FuriHalRfidCompCallback, void*"
|
||||
Function,+,furi_hal_rfid_comp_start,void,
|
||||
Function,+,furi_hal_rfid_comp_stop,void,
|
||||
Function,-,furi_hal_rfid_init,void,
|
||||
Function,+,furi_hal_rfid_pin_pull_pulldown,void,
|
||||
Function,+,furi_hal_rfid_pin_pull_release,void,
|
||||
Function,+,furi_hal_rfid_pins_emulate,void,
|
||||
Function,+,furi_hal_rfid_pins_read,void,
|
||||
Function,+,furi_hal_rfid_pins_reset,void,
|
||||
Function,+,furi_hal_rfid_set_emulate_period,void,uint32_t
|
||||
Function,+,furi_hal_rfid_set_emulate_pulse,void,uint32_t
|
||||
Function,+,furi_hal_rfid_set_read_period,void,uint32_t
|
||||
Function,+,furi_hal_rfid_set_read_pulse,void,uint32_t
|
||||
Function,+,furi_hal_rfid_tim_emulate,void,float
|
||||
Function,+,furi_hal_rfid_tim_emulate_dma_start,void,"uint32_t*, uint32_t*, size_t, FuriHalRfidDMACallback, void*"
|
||||
Function,+,furi_hal_rfid_tim_emulate_dma_stop,void,
|
||||
Function,+,furi_hal_rfid_tim_emulate_start,void,"FuriHalRfidEmulateCallback, void*"
|
||||
Function,+,furi_hal_rfid_tim_emulate_stop,void,
|
||||
Function,+,furi_hal_rfid_tim_read,void,"float, float"
|
||||
Function,+,furi_hal_rfid_tim_read_capture_start,void,"FuriHalRfidReadCaptureCallback, void*"
|
||||
Function,+,furi_hal_rfid_tim_read_capture_stop,void,
|
||||
Function,+,furi_hal_rfid_tim_read_start,void,
|
||||
Function,+,furi_hal_rfid_tim_read_continue,void,
|
||||
Function,+,furi_hal_rfid_tim_read_pause,void,
|
||||
Function,+,furi_hal_rfid_tim_read_start,void,"float, float"
|
||||
Function,+,furi_hal_rfid_tim_read_stop,void,
|
||||
Function,+,furi_hal_rfid_tim_reset,void,
|
||||
Function,+,furi_hal_rtc_datetime_to_timestamp,uint32_t,FuriHalRtcDateTime*
|
||||
Function,-,furi_hal_rtc_deinit_early,void,
|
||||
Function,+,furi_hal_rtc_get_boot_mode,FuriHalRtcBootMode,
|
||||
Function,+,furi_hal_rtc_get_datetime,void,FuriHalRtcDateTime*
|
||||
Function,+,furi_hal_rtc_get_days_per_month,uint8_t,"_Bool, uint8_t"
|
||||
Function,+,furi_hal_rtc_get_days_per_year,uint16_t,uint16_t
|
||||
Function,+,furi_hal_rtc_get_fault_data,uint32_t,
|
||||
Function,+,furi_hal_rtc_get_heap_track_mode,FuriHalRtcHeapTrackMode,
|
||||
Function,+,furi_hal_rtc_get_locale_dateformat,FuriHalRtcLocaleDateFormat,
|
||||
@ -1324,6 +1330,7 @@ Function,+,furi_hal_rtc_get_timestamp,uint32_t,
|
||||
Function,-,furi_hal_rtc_init,void,
|
||||
Function,-,furi_hal_rtc_init_early,void,
|
||||
Function,+,furi_hal_rtc_is_flag_set,_Bool,FuriHalRtcFlag
|
||||
Function,+,furi_hal_rtc_is_leap_year,_Bool,uint16_t
|
||||
Function,+,furi_hal_rtc_reset_flag,void,FuriHalRtcFlag
|
||||
Function,+,furi_hal_rtc_set_boot_mode,void,FuriHalRtcBootMode
|
||||
Function,+,furi_hal_rtc_set_datetime,void,FuriHalRtcDateTime*
|
||||
@ -1715,7 +1722,7 @@ Function,+,infrared_worker_rx_set_received_signal_callback,void,"InfraredWorker*
|
||||
Function,+,infrared_worker_rx_start,void,InfraredWorker*
|
||||
Function,+,infrared_worker_rx_stop,void,InfraredWorker*
|
||||
Function,+,infrared_worker_set_decoded_signal,void,"InfraredWorker*, const InfraredMessage*"
|
||||
Function,+,infrared_worker_set_raw_signal,void,"InfraredWorker*, const uint32_t*, size_t"
|
||||
Function,+,infrared_worker_set_raw_signal,void,"InfraredWorker*, const uint32_t*, size_t, uint32_t, float"
|
||||
Function,+,infrared_worker_signal_is_decoded,_Bool,const InfraredWorkerSignal*
|
||||
Function,+,infrared_worker_tx_get_signal_steady_callback,InfraredWorkerGetSignalResponse,"void*, InfraredWorker*"
|
||||
Function,+,infrared_worker_tx_set_get_signal_callback,void,"InfraredWorker*, InfraredWorkerGetSignalCallback, void*"
|
||||
@ -1990,6 +1997,8 @@ Function,-,mf_df_cat_key_settings,void,"MifareDesfireKeySettings*, FuriString*"
|
||||
Function,-,mf_df_cat_version,void,"MifareDesfireVersion*, FuriString*"
|
||||
Function,-,mf_df_check_card_type,_Bool,"uint8_t, uint8_t, uint8_t"
|
||||
Function,-,mf_df_clear,void,MifareDesfireData*
|
||||
Function,-,mf_df_get_application,MifareDesfireApplication*,"MifareDesfireData*, const uint8_t[3]*"
|
||||
Function,-,mf_df_get_file,MifareDesfireFile*,"MifareDesfireApplication*, uint8_t"
|
||||
Function,-,mf_df_parse_get_application_ids_response,_Bool,"uint8_t*, uint16_t, MifareDesfireApplication**"
|
||||
Function,-,mf_df_parse_get_file_ids_response,_Bool,"uint8_t*, uint16_t, MifareDesfireFile**"
|
||||
Function,-,mf_df_parse_get_file_settings_response,_Bool,"uint8_t*, uint16_t, MifareDesfireFile*"
|
||||
@ -2012,6 +2021,7 @@ Function,-,mf_df_prepare_read_records,uint16_t,"uint8_t*, uint8_t, uint32_t, uin
|
||||
Function,-,mf_df_prepare_select_application,uint16_t,"uint8_t*, uint8_t[3]"
|
||||
Function,-,mf_df_read_card,_Bool,"FuriHalNfcTxRxContext*, MifareDesfireData*"
|
||||
Function,-,mf_ul_check_card_type,_Bool,"uint8_t, uint8_t, uint8_t"
|
||||
Function,-,mf_ul_emulation_supported,_Bool,MfUltralightData*
|
||||
Function,-,mf_ul_is_full_capture,_Bool,MfUltralightData*
|
||||
Function,-,mf_ul_prepare_emulation,void,"MfUltralightEmulator*, MfUltralightData*"
|
||||
Function,-,mf_ul_prepare_emulation_response,_Bool,"uint8_t*, uint16_t, uint8_t*, uint16_t*, uint32_t*, void*"
|
||||
@ -2935,6 +2945,8 @@ Function,-,vdprintf,int,"int, const char*, __gnuc_va_list"
|
||||
Function,+,version_get,const Version*,
|
||||
Function,+,version_get_builddate,const char*,const Version*
|
||||
Function,+,version_get_dirty_flag,_Bool,const Version*
|
||||
Function,+,version_get_firmware_origin,const char*,const Version*
|
||||
Function,+,version_get_git_origin,const char*,const Version*
|
||||
Function,+,version_get_gitbranch,const char*,const Version*
|
||||
Function,+,version_get_gitbranchnum,const char*,const Version*
|
||||
Function,+,version_get_githash,const char*,const Version*
|
||||
|
||||
|
@ -9,6 +9,8 @@
|
||||
void furi_hal_init_early() {
|
||||
furi_hal_cortex_init_early();
|
||||
furi_hal_clock_init_early();
|
||||
furi_hal_bus_init_early();
|
||||
furi_hal_dma_init_early();
|
||||
furi_hal_resources_init_early();
|
||||
furi_hal_os_init();
|
||||
furi_hal_spi_config_init_early();
|
||||
@ -22,12 +24,15 @@ void furi_hal_deinit_early() {
|
||||
furi_hal_i2c_deinit_early();
|
||||
furi_hal_spi_config_deinit_early();
|
||||
furi_hal_resources_deinit_early();
|
||||
furi_hal_dma_deinit_early();
|
||||
furi_hal_bus_deinit_early();
|
||||
furi_hal_clock_deinit_early();
|
||||
}
|
||||
|
||||
void furi_hal_init() {
|
||||
furi_hal_mpu_init();
|
||||
furi_hal_clock_init();
|
||||
furi_hal_random_init();
|
||||
furi_hal_console_init();
|
||||
furi_hal_rtc_init();
|
||||
furi_hal_interrupt_init();
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#include <furi_hal_version.h>
|
||||
#include <furi_hal_bt_hid.h>
|
||||
#include <furi_hal_bt_serial.h>
|
||||
#include <furi_hal_bus.c>
|
||||
#include "battery_service.h"
|
||||
|
||||
#include <furi.h>
|
||||
@ -80,6 +81,11 @@ FuriHalBtProfileConfig profile_config[FuriHalBtProfileNumber] = {
|
||||
FuriHalBtProfileConfig* current_profile = NULL;
|
||||
|
||||
void furi_hal_bt_init() {
|
||||
furi_hal_bus_enable(FuriHalBusHSEM);
|
||||
furi_hal_bus_enable(FuriHalBusIPCC);
|
||||
furi_hal_bus_enable(FuriHalBusAES2);
|
||||
furi_hal_bus_enable(FuriHalBusPKA);
|
||||
|
||||
if(!furi_hal_bt_core2_mtx) {
|
||||
furi_hal_bt_core2_mtx = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||
furi_assert(furi_hal_bt_core2_mtx);
|
||||
@ -256,6 +262,11 @@ void furi_hal_bt_reinit() {
|
||||
furi_delay_ms(100);
|
||||
ble_glue_thread_stop();
|
||||
|
||||
furi_hal_bus_disable(FuriHalBusHSEM);
|
||||
furi_hal_bus_disable(FuriHalBusIPCC);
|
||||
furi_hal_bus_disable(FuriHalBusAES2);
|
||||
furi_hal_bus_disable(FuriHalBusPKA);
|
||||
|
||||
FURI_LOG_I(TAG, "Start BT initialization");
|
||||
furi_hal_bt_init();
|
||||
|
||||
|
||||
302
firmware/targets/f7/furi_hal/furi_hal_bus.c
Normal file
302
firmware/targets/f7/furi_hal/furi_hal_bus.c
Normal file
@ -0,0 +1,302 @@
|
||||
#include <furi_hal_bus.h>
|
||||
#include <furi.h>
|
||||
|
||||
#include <stm32wbxx_ll_bus.h>
|
||||
|
||||
/* Bus bitmask definitions */
|
||||
#define FURI_HAL_BUS_IGNORE (0x0U)
|
||||
|
||||
#define FURI_HAL_BUS_AHB1_GRP1 \
|
||||
(LL_AHB1_GRP1_PERIPH_DMA1 | LL_AHB1_GRP1_PERIPH_DMA2 | LL_AHB1_GRP1_PERIPH_DMAMUX1 | \
|
||||
LL_AHB1_GRP1_PERIPH_CRC | LL_AHB1_GRP1_PERIPH_TSC)
|
||||
|
||||
#if defined(ADC_SUPPORT_5_MSPS)
|
||||
#define FURI_HAL_BUS_AHB2_GRP1 \
|
||||
(LL_AHB2_GRP1_PERIPH_GPIOA | LL_AHB2_GRP1_PERIPH_GPIOB | LL_AHB2_GRP1_PERIPH_GPIOC | \
|
||||
LL_AHB2_GRP1_PERIPH_GPIOD | LL_AHB2_GRP1_PERIPH_GPIOE | LL_AHB2_GRP1_PERIPH_GPIOH | \
|
||||
LL_AHB2_GRP1_PERIPH_ADC | LL_AHB2_GRP1_PERIPH_AES1)
|
||||
|
||||
#define FURI_HAL_BUS_APB2_GRP1 \
|
||||
(LL_APB2_GRP1_PERIPH_TIM1 | LL_APB2_GRP1_PERIPH_SPI1 | LL_APB2_GRP1_PERIPH_USART1 | \
|
||||
LL_APB2_GRP1_PERIPH_TIM16 | LL_APB2_GRP1_PERIPH_TIM17 | LL_APB2_GRP1_PERIPH_SAI1)
|
||||
#else
|
||||
#define FURI_HAL_BUS_AHB2_GRP1 \
|
||||
(LL_AHB2_GRP1_PERIPH_GPIOA | LL_AHB2_GRP1_PERIPH_GPIOB | LL_AHB2_GRP1_PERIPH_GPIOC | \
|
||||
LL_AHB2_GRP1_PERIPH_GPIOD | LL_AHB2_GRP1_PERIPH_GPIOE | LL_AHB2_GRP1_PERIPH_GPIOH | \
|
||||
LL_AHB2_GRP1_PERIPH_AES1)
|
||||
|
||||
#define FURI_HAL_BUS_APB2_GRP1 \
|
||||
(LL_APB2_GRP1_PERIPH_ADC | LL_APB2_GRP1_PERIPH_TIM1 | LL_APB2_GRP1_PERIPH_SPI1 | \
|
||||
LL_APB2_GRP1_PERIPH_USART1 | LL_APB2_GRP1_PERIPH_TIM16 | LL_APB2_GRP1_PERIPH_TIM17 | \
|
||||
LL_APB2_GRP1_PERIPH_SAI1)
|
||||
#endif
|
||||
|
||||
#define FURI_HAL_BUS_AHB3_GRP1 \
|
||||
(LL_AHB3_GRP1_PERIPH_QUADSPI | LL_AHB3_GRP1_PERIPH_PKA | LL_AHB3_GRP1_PERIPH_AES2 | \
|
||||
LL_AHB3_GRP1_PERIPH_RNG | LL_AHB3_GRP1_PERIPH_HSEM | LL_AHB3_GRP1_PERIPH_IPCC)
|
||||
// LL_AHB3_GRP1_PERIPH_FLASH enabled by default
|
||||
|
||||
#define FURI_HAL_BUS_APB1_GRP1 \
|
||||
(LL_APB1_GRP1_PERIPH_TIM2 | LL_APB1_GRP1_PERIPH_LCD | LL_APB1_GRP1_PERIPH_RTCAPB | \
|
||||
LL_APB1_GRP1_PERIPH_SPI2 | LL_APB1_GRP1_PERIPH_I2C1 | LL_APB1_GRP1_PERIPH_I2C3 | \
|
||||
LL_APB1_GRP1_PERIPH_CRS | LL_APB1_GRP1_PERIPH_USB | LL_APB1_GRP1_PERIPH_LPTIM1)
|
||||
|
||||
#define FURI_HAL_BUS_APB1_GRP2 (LL_APB1_GRP2_PERIPH_LPUART1 | LL_APB1_GRP2_PERIPH_LPTIM2)
|
||||
#define FURI_HAL_BUS_APB3_GRP1 (LL_APB3_GRP1_PERIPH_RF)
|
||||
|
||||
/* Test macro definitions */
|
||||
#define FURI_HAL_BUS_IS_ALL_CLEAR(reg, value) (READ_BIT((reg), (value)) == 0UL)
|
||||
#define FURI_HAL_BUS_IS_ALL_SET(reg, value) (READ_BIT((reg), (value)) == (value))
|
||||
|
||||
#define FURI_HAL_BUS_IS_CLOCK_ENABLED(bus, value, ...) \
|
||||
(FURI_HAL_BUS_IS_ALL_SET(RCC->bus##ENR##__VA_ARGS__, (value)))
|
||||
#define FURI_HAL_BUS_IS_CLOCK_DISABLED(bus, value, ...) \
|
||||
(FURI_HAL_BUS_IS_ALL_CLEAR(RCC->bus##ENR##__VA_ARGS__, (value)))
|
||||
|
||||
#define FURI_HAL_BUS_IS_RESET_ASSERTED(bus, value, ...) \
|
||||
(FURI_HAL_BUS_IS_ALL_SET(RCC->bus##RSTR##__VA_ARGS__, (value)))
|
||||
#define FURI_HAL_BUS_IS_RESET_DEASSERTED(bus, value, ...) \
|
||||
(FURI_HAL_BUS_IS_ALL_CLEAR(RCC->bus##RSTR##__VA_ARGS__, (value)))
|
||||
|
||||
#define FURI_HAL_BUS_IS_PERIPH_ENABLED(bus, value, ...) \
|
||||
(FURI_HAL_BUS_IS_RESET_DEASSERTED(bus, (value), __VA_ARGS__) && \
|
||||
FURI_HAL_BUS_IS_CLOCK_ENABLED(bus, (value), __VA_ARGS__))
|
||||
|
||||
#define FURI_HAL_BUS_IS_PERIPH_DISABLED(bus, value, ...) \
|
||||
(FURI_HAL_BUS_IS_CLOCK_DISABLED(bus, (value), __VA_ARGS__) && \
|
||||
FURI_HAL_BUS_IS_RESET_ASSERTED(bus, (value), __VA_ARGS__))
|
||||
|
||||
/* Control macro definitions */
|
||||
#define FURI_HAL_BUS_RESET_ASSERT(bus, value, grp) LL_##bus##_GRP##grp##_ForceReset(value)
|
||||
#define FURI_HAL_BUS_RESET_DEASSERT(bus, value, grp) LL_##bus##_GRP##grp##_ReleaseReset(value)
|
||||
|
||||
#define FURI_HAL_BUS_CLOCK_ENABLE(bus, value, grp) LL_##bus##_GRP##grp##_EnableClock(value)
|
||||
#define FURI_HAL_BUS_CLOCK_DISABLE(bus, value, grp) LL_##bus##_GRP##grp##_DisableClock(value)
|
||||
|
||||
#define FURI_HAL_BUS_PERIPH_ENABLE(bus, value, grp) \
|
||||
FURI_HAL_BUS_CLOCK_ENABLE(bus, value, grp); \
|
||||
FURI_HAL_BUS_RESET_DEASSERT(bus, value, grp)
|
||||
|
||||
#define FURI_HAL_BUS_PERIPH_DISABLE(bus, value, grp) \
|
||||
FURI_HAL_BUS_RESET_ASSERT(bus, value, grp); \
|
||||
FURI_HAL_BUS_CLOCK_DISABLE(bus, value, grp)
|
||||
|
||||
#define FURI_HAL_BUS_PERIPH_RESET(bus, value, grp) \
|
||||
FURI_HAL_BUS_RESET_ASSERT(bus, value, grp); \
|
||||
FURI_HAL_BUS_RESET_DEASSERT(bus, value, grp)
|
||||
|
||||
static const uint32_t furi_hal_bus[] = {
|
||||
[FuriHalBusAHB1_GRP1] = FURI_HAL_BUS_AHB1_GRP1,
|
||||
[FuriHalBusDMA1] = LL_AHB1_GRP1_PERIPH_DMA1,
|
||||
[FuriHalBusDMA2] = LL_AHB1_GRP1_PERIPH_DMA2,
|
||||
[FuriHalBusDMAMUX1] = LL_AHB1_GRP1_PERIPH_DMAMUX1,
|
||||
[FuriHalBusCRC] = LL_AHB1_GRP1_PERIPH_CRC,
|
||||
[FuriHalBusTSC] = LL_AHB1_GRP1_PERIPH_TSC,
|
||||
|
||||
[FuriHalBusAHB2_GRP1] = FURI_HAL_BUS_AHB2_GRP1,
|
||||
[FuriHalBusGPIOA] = LL_AHB2_GRP1_PERIPH_GPIOA,
|
||||
[FuriHalBusGPIOB] = LL_AHB2_GRP1_PERIPH_GPIOB,
|
||||
[FuriHalBusGPIOC] = LL_AHB2_GRP1_PERIPH_GPIOC,
|
||||
[FuriHalBusGPIOD] = LL_AHB2_GRP1_PERIPH_GPIOD,
|
||||
[FuriHalBusGPIOE] = LL_AHB2_GRP1_PERIPH_GPIOE,
|
||||
[FuriHalBusGPIOH] = LL_AHB2_GRP1_PERIPH_GPIOH,
|
||||
#if defined(ADC_SUPPORT_5_MSPS)
|
||||
[FuriHalBusADC] = LL_AHB2_GRP1_PERIPH_ADC,
|
||||
#endif
|
||||
[FuriHalBusAES1] = LL_AHB2_GRP1_PERIPH_AES1,
|
||||
|
||||
[FuriHalBusAHB3_GRP1] = FURI_HAL_BUS_AHB3_GRP1,
|
||||
[FuriHalBusQUADSPI] = LL_AHB3_GRP1_PERIPH_QUADSPI,
|
||||
[FuriHalBusPKA] = LL_AHB3_GRP1_PERIPH_PKA,
|
||||
[FuriHalBusAES2] = LL_AHB3_GRP1_PERIPH_AES2,
|
||||
[FuriHalBusRNG] = LL_AHB3_GRP1_PERIPH_RNG,
|
||||
[FuriHalBusHSEM] = LL_AHB3_GRP1_PERIPH_HSEM,
|
||||
[FuriHalBusIPCC] = LL_AHB3_GRP1_PERIPH_IPCC,
|
||||
[FuriHalBusFLASH] = LL_AHB3_GRP1_PERIPH_FLASH,
|
||||
|
||||
[FuriHalBusAPB1_GRP1] = FURI_HAL_BUS_APB1_GRP1,
|
||||
[FuriHalBusTIM2] = LL_APB1_GRP1_PERIPH_TIM2,
|
||||
[FuriHalBusLCD] = LL_APB1_GRP1_PERIPH_LCD,
|
||||
[FuriHalBusSPI2] = LL_APB1_GRP1_PERIPH_SPI2,
|
||||
[FuriHalBusI2C1] = LL_APB1_GRP1_PERIPH_I2C1,
|
||||
[FuriHalBusI2C3] = LL_APB1_GRP1_PERIPH_I2C3,
|
||||
[FuriHalBusCRS] = LL_APB1_GRP1_PERIPH_CRS,
|
||||
[FuriHalBusUSB] = LL_APB1_GRP1_PERIPH_USB,
|
||||
[FuriHalBusLPTIM1] = LL_APB1_GRP1_PERIPH_LPTIM1,
|
||||
|
||||
[FuriHalBusAPB1_GRP2] = FURI_HAL_BUS_APB1_GRP2,
|
||||
[FuriHalBusLPUART1] = LL_APB1_GRP2_PERIPH_LPUART1,
|
||||
[FuriHalBusLPTIM2] = LL_APB1_GRP2_PERIPH_LPTIM2,
|
||||
|
||||
[FuriHalBusAPB2_GRP1] = FURI_HAL_BUS_APB2_GRP1,
|
||||
#if defined(ADC_SUPPORT_2_5_MSPS)
|
||||
[FuriHalBusADC] = LL_APB2_GRP1_PERIPH_ADC,
|
||||
#endif
|
||||
[FuriHalBusTIM1] = LL_APB2_GRP1_PERIPH_TIM1,
|
||||
[FuriHalBusSPI1] = LL_APB2_GRP1_PERIPH_SPI1,
|
||||
[FuriHalBusUSART1] = LL_APB2_GRP1_PERIPH_USART1,
|
||||
[FuriHalBusTIM16] = LL_APB2_GRP1_PERIPH_TIM16,
|
||||
[FuriHalBusTIM17] = LL_APB2_GRP1_PERIPH_TIM17,
|
||||
[FuriHalBusSAI1] = LL_APB2_GRP1_PERIPH_SAI1,
|
||||
|
||||
[FuriHalBusAPB3_GRP1] = FURI_HAL_BUS_IGNORE, // APB3_GRP1 clocking cannot be changed
|
||||
[FuriHalBusRF] = LL_APB3_GRP1_PERIPH_RF,
|
||||
};
|
||||
|
||||
void furi_hal_bus_init_early() {
|
||||
FURI_CRITICAL_ENTER();
|
||||
|
||||
FURI_HAL_BUS_PERIPH_DISABLE(AHB1, FURI_HAL_BUS_AHB1_GRP1, 1);
|
||||
FURI_HAL_BUS_PERIPH_DISABLE(AHB2, FURI_HAL_BUS_AHB2_GRP1, 1);
|
||||
FURI_HAL_BUS_PERIPH_DISABLE(AHB3, FURI_HAL_BUS_AHB3_GRP1, 1);
|
||||
FURI_HAL_BUS_PERIPH_DISABLE(APB1, FURI_HAL_BUS_APB1_GRP1, 1);
|
||||
FURI_HAL_BUS_PERIPH_DISABLE(APB1, FURI_HAL_BUS_APB1_GRP2, 2);
|
||||
FURI_HAL_BUS_PERIPH_DISABLE(APB2, FURI_HAL_BUS_APB2_GRP1, 1);
|
||||
|
||||
FURI_HAL_BUS_RESET_ASSERT(APB3, FURI_HAL_BUS_APB3_GRP1, 1);
|
||||
|
||||
FURI_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
void furi_hal_bus_deinit_early() {
|
||||
FURI_CRITICAL_ENTER();
|
||||
|
||||
FURI_HAL_BUS_PERIPH_ENABLE(AHB1, FURI_HAL_BUS_AHB1_GRP1, 1);
|
||||
FURI_HAL_BUS_PERIPH_ENABLE(AHB2, FURI_HAL_BUS_AHB2_GRP1, 1);
|
||||
FURI_HAL_BUS_PERIPH_ENABLE(AHB3, FURI_HAL_BUS_AHB3_GRP1, 1);
|
||||
FURI_HAL_BUS_PERIPH_ENABLE(APB1, FURI_HAL_BUS_APB1_GRP1, 1);
|
||||
FURI_HAL_BUS_PERIPH_ENABLE(APB1, FURI_HAL_BUS_APB1_GRP2, 2);
|
||||
FURI_HAL_BUS_PERIPH_ENABLE(APB2, FURI_HAL_BUS_APB2_GRP1, 1);
|
||||
|
||||
FURI_HAL_BUS_RESET_DEASSERT(APB3, FURI_HAL_BUS_APB3_GRP1, 1);
|
||||
|
||||
FURI_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
void furi_hal_bus_enable(FuriHalBus bus) {
|
||||
furi_check(bus < FuriHalBusMAX);
|
||||
const uint32_t value = furi_hal_bus[bus];
|
||||
if(!value) {
|
||||
return;
|
||||
}
|
||||
|
||||
FURI_CRITICAL_ENTER();
|
||||
if(bus < FuriHalBusAHB2_GRP1) {
|
||||
furi_check(FURI_HAL_BUS_IS_PERIPH_DISABLED(AHB1, value));
|
||||
FURI_HAL_BUS_PERIPH_ENABLE(AHB1, value, 1);
|
||||
} else if(bus < FuriHalBusAHB3_GRP1) {
|
||||
furi_check(FURI_HAL_BUS_IS_PERIPH_DISABLED(AHB2, value));
|
||||
FURI_HAL_BUS_PERIPH_ENABLE(AHB2, value, 1);
|
||||
} else if(bus < FuriHalBusAPB1_GRP1) {
|
||||
furi_check(FURI_HAL_BUS_IS_PERIPH_DISABLED(AHB3, value));
|
||||
FURI_HAL_BUS_PERIPH_ENABLE(AHB3, value, 1);
|
||||
} else if(bus < FuriHalBusAPB1_GRP2) {
|
||||
furi_check(FURI_HAL_BUS_IS_PERIPH_DISABLED(APB1, value, 1));
|
||||
FURI_HAL_BUS_PERIPH_ENABLE(APB1, value, 1);
|
||||
} else if(bus < FuriHalBusAPB2_GRP1) {
|
||||
furi_check(FURI_HAL_BUS_IS_PERIPH_DISABLED(APB1, value, 2));
|
||||
FURI_HAL_BUS_PERIPH_ENABLE(APB1, value, 2);
|
||||
} else if(bus < FuriHalBusAPB3_GRP1) {
|
||||
furi_check(FURI_HAL_BUS_IS_PERIPH_DISABLED(APB2, value));
|
||||
FURI_HAL_BUS_PERIPH_ENABLE(APB2, value, 1);
|
||||
} else {
|
||||
furi_check(FURI_HAL_BUS_IS_RESET_ASSERTED(APB3, value));
|
||||
FURI_HAL_BUS_RESET_DEASSERT(APB3, FURI_HAL_BUS_APB3_GRP1, 1);
|
||||
}
|
||||
FURI_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
void furi_hal_bus_reset(FuriHalBus bus) {
|
||||
furi_check(bus < FuriHalBusMAX);
|
||||
const uint32_t value = furi_hal_bus[bus];
|
||||
if(!value) {
|
||||
return;
|
||||
}
|
||||
|
||||
FURI_CRITICAL_ENTER();
|
||||
if(bus < FuriHalBusAHB2_GRP1) {
|
||||
furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(AHB1, value));
|
||||
FURI_HAL_BUS_PERIPH_RESET(AHB1, value, 1);
|
||||
} else if(bus < FuriHalBusAHB3_GRP1) {
|
||||
furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(AHB2, value));
|
||||
FURI_HAL_BUS_PERIPH_RESET(AHB2, value, 1);
|
||||
} else if(bus < FuriHalBusAPB1_GRP1) {
|
||||
furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(AHB3, value));
|
||||
FURI_HAL_BUS_PERIPH_RESET(AHB3, value, 1);
|
||||
} else if(bus < FuriHalBusAPB1_GRP2) {
|
||||
furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(APB1, value, 1));
|
||||
FURI_HAL_BUS_PERIPH_RESET(APB1, value, 1);
|
||||
} else if(bus < FuriHalBusAPB2_GRP1) {
|
||||
furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(APB1, value, 2));
|
||||
FURI_HAL_BUS_PERIPH_RESET(APB1, value, 2);
|
||||
} else if(bus < FuriHalBusAPB3_GRP1) {
|
||||
furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(APB2, value));
|
||||
FURI_HAL_BUS_PERIPH_RESET(APB2, value, 1);
|
||||
} else {
|
||||
furi_check(FURI_HAL_BUS_IS_RESET_DEASSERTED(APB3, value));
|
||||
FURI_HAL_BUS_PERIPH_RESET(APB3, value, 1);
|
||||
}
|
||||
FURI_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
void furi_hal_bus_disable(FuriHalBus bus) {
|
||||
furi_check(bus < FuriHalBusMAX);
|
||||
const uint32_t value = furi_hal_bus[bus];
|
||||
if(!value) {
|
||||
return;
|
||||
}
|
||||
|
||||
FURI_CRITICAL_ENTER();
|
||||
if(bus < FuriHalBusAHB2_GRP1) {
|
||||
furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(AHB1, value));
|
||||
FURI_HAL_BUS_PERIPH_DISABLE(AHB1, value, 1);
|
||||
} else if(bus < FuriHalBusAHB3_GRP1) {
|
||||
furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(AHB2, value));
|
||||
FURI_HAL_BUS_PERIPH_DISABLE(AHB2, value, 1);
|
||||
} else if(bus < FuriHalBusAPB1_GRP1) {
|
||||
furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(AHB3, value));
|
||||
FURI_HAL_BUS_PERIPH_DISABLE(AHB3, value, 1);
|
||||
} else if(bus < FuriHalBusAPB1_GRP2) {
|
||||
furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(APB1, value, 1));
|
||||
FURI_HAL_BUS_PERIPH_DISABLE(APB1, value, 1);
|
||||
} else if(bus < FuriHalBusAPB2_GRP1) {
|
||||
furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(APB1, value, 2));
|
||||
FURI_HAL_BUS_PERIPH_DISABLE(APB1, value, 2);
|
||||
} else if(bus < FuriHalBusAPB3_GRP1) {
|
||||
furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(APB2, value));
|
||||
FURI_HAL_BUS_PERIPH_DISABLE(APB2, value, 1);
|
||||
} else {
|
||||
furi_check(FURI_HAL_BUS_IS_RESET_DEASSERTED(APB3, value));
|
||||
FURI_HAL_BUS_RESET_ASSERT(APB3, FURI_HAL_BUS_APB3_GRP1, 1);
|
||||
}
|
||||
FURI_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
bool furi_hal_bus_is_enabled(FuriHalBus bus) {
|
||||
furi_check(bus < FuriHalBusMAX);
|
||||
const uint32_t value = furi_hal_bus[bus];
|
||||
if(value == FURI_HAL_BUS_IGNORE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
FURI_CRITICAL_ENTER();
|
||||
if(bus < FuriHalBusAHB2_GRP1) {
|
||||
ret = FURI_HAL_BUS_IS_PERIPH_ENABLED(AHB1, value);
|
||||
} else if(bus < FuriHalBusAHB3_GRP1) {
|
||||
ret = FURI_HAL_BUS_IS_PERIPH_ENABLED(AHB2, value);
|
||||
} else if(bus < FuriHalBusAPB1_GRP1) {
|
||||
ret = FURI_HAL_BUS_IS_PERIPH_ENABLED(AHB3, value);
|
||||
} else if(bus < FuriHalBusAPB1_GRP2) {
|
||||
ret = FURI_HAL_BUS_IS_PERIPH_ENABLED(APB1, value, 1);
|
||||
} else if(bus < FuriHalBusAPB2_GRP1) {
|
||||
ret = FURI_HAL_BUS_IS_PERIPH_ENABLED(APB1, value, 2);
|
||||
} else if(bus < FuriHalBusAPB3_GRP1) {
|
||||
ret = FURI_HAL_BUS_IS_PERIPH_ENABLED(APB2, value);
|
||||
} else {
|
||||
ret = FURI_HAL_BUS_IS_RESET_DEASSERTED(APB3, value);
|
||||
}
|
||||
FURI_CRITICAL_EXIT();
|
||||
|
||||
return ret;
|
||||
}
|
||||
112
firmware/targets/f7/furi_hal/furi_hal_bus.h
Normal file
112
firmware/targets/f7/furi_hal/furi_hal_bus.h
Normal file
@ -0,0 +1,112 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "stm32wbxx.h"
|
||||
#include "stdbool.h"
|
||||
|
||||
typedef enum {
|
||||
FuriHalBusAHB1_GRP1,
|
||||
FuriHalBusDMA1,
|
||||
FuriHalBusDMA2,
|
||||
FuriHalBusDMAMUX1,
|
||||
FuriHalBusCRC,
|
||||
FuriHalBusTSC,
|
||||
|
||||
FuriHalBusAHB2_GRP1,
|
||||
FuriHalBusGPIOA,
|
||||
FuriHalBusGPIOB,
|
||||
FuriHalBusGPIOC,
|
||||
FuriHalBusGPIOD,
|
||||
FuriHalBusGPIOE,
|
||||
FuriHalBusGPIOH,
|
||||
#if defined(ADC_SUPPORT_5_MSPS)
|
||||
FuriHalBusADC,
|
||||
#endif
|
||||
FuriHalBusAES1,
|
||||
|
||||
FuriHalBusAHB3_GRP1,
|
||||
FuriHalBusQUADSPI,
|
||||
FuriHalBusPKA,
|
||||
FuriHalBusAES2,
|
||||
FuriHalBusRNG,
|
||||
FuriHalBusHSEM,
|
||||
FuriHalBusIPCC,
|
||||
FuriHalBusFLASH,
|
||||
|
||||
FuriHalBusAPB1_GRP1,
|
||||
FuriHalBusTIM2,
|
||||
FuriHalBusLCD,
|
||||
FuriHalBusSPI2,
|
||||
FuriHalBusI2C1,
|
||||
FuriHalBusI2C3,
|
||||
FuriHalBusCRS,
|
||||
FuriHalBusUSB,
|
||||
FuriHalBusLPTIM1,
|
||||
|
||||
FuriHalBusAPB1_GRP2,
|
||||
FuriHalBusLPUART1,
|
||||
FuriHalBusLPTIM2,
|
||||
|
||||
FuriHalBusAPB2_GRP1,
|
||||
#if defined(ADC_SUPPORT_2_5_MSPS)
|
||||
FuriHalBusADC,
|
||||
#endif
|
||||
FuriHalBusTIM1,
|
||||
FuriHalBusSPI1,
|
||||
FuriHalBusUSART1,
|
||||
FuriHalBusTIM16,
|
||||
FuriHalBusTIM17,
|
||||
FuriHalBusSAI1,
|
||||
|
||||
FuriHalBusAPB3_GRP1,
|
||||
FuriHalBusRF,
|
||||
|
||||
FuriHalBusMAX,
|
||||
} FuriHalBus;
|
||||
|
||||
/** Early initialization */
|
||||
void furi_hal_bus_init_early();
|
||||
|
||||
/** Early de-initialization */
|
||||
void furi_hal_bus_deinit_early();
|
||||
|
||||
/**
|
||||
* Enable a peripheral by turning the clocking on and deasserting the reset.
|
||||
* @param [in] bus Peripheral to be enabled.
|
||||
* @warning Peripheral must be in disabled state in order to be enabled.
|
||||
*/
|
||||
void furi_hal_bus_enable(FuriHalBus bus);
|
||||
|
||||
/**
|
||||
* Reset a peripheral by sequentially asserting and deasserting the reset.
|
||||
* @param [in] bus Peripheral to be reset.
|
||||
* @warning Peripheral must be in enabled state in order to be reset.
|
||||
*/
|
||||
void furi_hal_bus_reset(FuriHalBus bus);
|
||||
|
||||
/**
|
||||
* Disable a peripheral by turning the clocking off and asserting the reset.
|
||||
* @param [in] bus Peripheral to be disabled.
|
||||
* @warning Peripheral must be in enabled state in order to be disabled.
|
||||
*/
|
||||
void furi_hal_bus_disable(FuriHalBus bus);
|
||||
|
||||
/** Check if peripheral is enabled
|
||||
*
|
||||
* @warning FuriHalBusAPB3_GRP1 is a special group of shared peripherals, for
|
||||
* core1 its clock is always on and the only status we can report is
|
||||
* peripheral reset status. Check code and Reference Manual for
|
||||
* details.
|
||||
*
|
||||
* @param[in] bus The peripheral to check
|
||||
*
|
||||
* @return true if enabled or always enabled, false otherwise
|
||||
*/
|
||||
bool furi_hal_bus_is_enabled(FuriHalBus bus);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -6,7 +6,6 @@
|
||||
#include <stm32wbxx_ll_rcc.h>
|
||||
#include <stm32wbxx_ll_utils.h>
|
||||
#include <stm32wbxx_ll_cortex.h>
|
||||
#include <stm32wbxx_ll_bus.h>
|
||||
|
||||
#define TAG "FuriHalClock"
|
||||
|
||||
@ -19,36 +18,9 @@
|
||||
void furi_hal_clock_init_early() {
|
||||
LL_SetSystemCoreClock(CPU_CLOCK_HZ_EARLY);
|
||||
LL_Init1msTick(SystemCoreClock);
|
||||
|
||||
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
|
||||
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB);
|
||||
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC);
|
||||
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOD);
|
||||
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOE);
|
||||
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOH);
|
||||
|
||||
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2);
|
||||
|
||||
LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_LPTIM2);
|
||||
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C3);
|
||||
}
|
||||
|
||||
void furi_hal_clock_deinit_early() {
|
||||
LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_I2C1);
|
||||
LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_I2C3);
|
||||
|
||||
LL_APB2_GRP1_DisableClock(LL_APB2_GRP1_PERIPH_SPI1);
|
||||
LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_SPI2);
|
||||
|
||||
LL_AHB2_GRP1_DisableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
|
||||
LL_AHB2_GRP1_DisableClock(LL_AHB2_GRP1_PERIPH_GPIOB);
|
||||
LL_AHB2_GRP1_DisableClock(LL_AHB2_GRP1_PERIPH_GPIOC);
|
||||
LL_AHB2_GRP1_DisableClock(LL_AHB2_GRP1_PERIPH_GPIOD);
|
||||
LL_AHB2_GRP1_DisableClock(LL_AHB2_GRP1_PERIPH_GPIOE);
|
||||
LL_AHB2_GRP1_DisableClock(LL_AHB2_GRP1_PERIPH_GPIOH);
|
||||
}
|
||||
|
||||
void furi_hal_clock_init() {
|
||||
@ -137,68 +109,12 @@ void furi_hal_clock_init() {
|
||||
SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), TICK_INT_PRIORITY, 0));
|
||||
NVIC_EnableIRQ(SysTick_IRQn);
|
||||
|
||||
LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2);
|
||||
LL_RCC_SetLPUARTClockSource(LL_RCC_LPUART1_CLKSOURCE_PCLK1);
|
||||
LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_PLLSAI1);
|
||||
LL_RCC_SetI2CClockSource(LL_RCC_I2C1_CLKSOURCE_PCLK1);
|
||||
LL_RCC_SetRNGClockSource(LL_RCC_RNG_CLKSOURCE_CLK48);
|
||||
LL_RCC_SetUSBClockSource(LL_RCC_USB_CLKSOURCE_PLLSAI1);
|
||||
LL_RCC_SetCLK48ClockSource(LL_RCC_CLK48_CLKSOURCE_PLLSAI1);
|
||||
LL_RCC_HSI_EnableInStopMode(); // Ensure that MR is capable of work in STOP0
|
||||
LL_RCC_SetSMPSClockSource(LL_RCC_SMPS_CLKSOURCE_HSE);
|
||||
LL_RCC_SetSMPSPrescaler(LL_RCC_SMPS_DIV_1);
|
||||
LL_RCC_SetRFWKPClockSource(LL_RCC_RFWKP_CLKSOURCE_LSE);
|
||||
|
||||
// AHB1 GRP1
|
||||
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
|
||||
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA2);
|
||||
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMAMUX1);
|
||||
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_CRC);
|
||||
// LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_TSC);
|
||||
|
||||
// AHB2 GRP1
|
||||
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
|
||||
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB);
|
||||
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC);
|
||||
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOD);
|
||||
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOE);
|
||||
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOH);
|
||||
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_ADC);
|
||||
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_AES1);
|
||||
|
||||
// AHB3 GRP1
|
||||
// LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_QUADSPI);
|
||||
LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_PKA);
|
||||
LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_AES2);
|
||||
LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_RNG);
|
||||
LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_HSEM);
|
||||
LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_IPCC);
|
||||
LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_FLASH);
|
||||
|
||||
// APB1 GRP1
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2);
|
||||
// LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_LCD);
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_RTCAPB);
|
||||
// LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_WWDG);
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2);
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C3);
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_CRS);
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USB);
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_LPTIM1);
|
||||
|
||||
// APB1 GRP2
|
||||
LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_LPUART1);
|
||||
|
||||
// APB2
|
||||
// LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_ADC);
|
||||
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM1);
|
||||
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);
|
||||
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART1);
|
||||
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM16);
|
||||
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM17);
|
||||
// LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SAI1);
|
||||
|
||||
FURI_LOG_I(TAG, "Init OK");
|
||||
}
|
||||
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
#include <furi_hal_crypto.h>
|
||||
#include <furi_hal_bt.h>
|
||||
#include <furi_hal_random.h>
|
||||
#include <furi_hal_bus.h>
|
||||
|
||||
#include <stm32wbxx_ll_cortex.h>
|
||||
#include <stm32wbxx_ll_bus.h>
|
||||
#include <furi.h>
|
||||
#include <interface/patterns/ble_thread/shci/shci.h>
|
||||
|
||||
@ -241,6 +242,8 @@ bool furi_hal_crypto_store_load_key(uint8_t slot, const uint8_t* iv) {
|
||||
furi_assert(furi_hal_crypto_mutex);
|
||||
furi_check(furi_mutex_acquire(furi_hal_crypto_mutex, FuriWaitForever) == FuriStatusOk);
|
||||
|
||||
furi_hal_bus_enable(FuriHalBusAES1);
|
||||
|
||||
if(!furi_hal_bt_is_alive()) {
|
||||
return false;
|
||||
}
|
||||
@ -267,10 +270,7 @@ bool furi_hal_crypto_store_unload_key(uint8_t slot) {
|
||||
SHCI_CmdStatus_t shci_state = SHCI_C2_FUS_UnloadUsrKey(slot);
|
||||
furi_assert(shci_state == SHCI_Success);
|
||||
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_AHB2_GRP1_ForceReset(LL_AHB2_GRP1_PERIPH_AES1);
|
||||
LL_AHB2_GRP1_ReleaseReset(LL_AHB2_GRP1_PERIPH_AES1);
|
||||
FURI_CRITICAL_EXIT();
|
||||
furi_hal_bus_disable(FuriHalBusAES1);
|
||||
|
||||
furi_check(furi_mutex_release(furi_hal_crypto_mutex) == FuriStatusOk);
|
||||
return (shci_state == SHCI_Success);
|
||||
|
||||
14
firmware/targets/f7/furi_hal/furi_hal_dma.c
Normal file
14
firmware/targets/f7/furi_hal/furi_hal_dma.c
Normal file
@ -0,0 +1,14 @@
|
||||
#include <furi_hal_dma.h>
|
||||
#include <furi_hal_bus.h>
|
||||
|
||||
void furi_hal_dma_init_early() {
|
||||
furi_hal_bus_enable(FuriHalBusDMA1);
|
||||
furi_hal_bus_enable(FuriHalBusDMA2);
|
||||
furi_hal_bus_enable(FuriHalBusDMAMUX1);
|
||||
}
|
||||
|
||||
void furi_hal_dma_deinit_early() {
|
||||
furi_hal_bus_disable(FuriHalBusDMA1);
|
||||
furi_hal_bus_disable(FuriHalBusDMA2);
|
||||
furi_hal_bus_disable(FuriHalBusDMAMUX1);
|
||||
}
|
||||
15
firmware/targets/f7/furi_hal/furi_hal_dma.h
Normal file
15
firmware/targets/f7/furi_hal/furi_hal_dma.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Early initialization */
|
||||
void furi_hal_dma_init_early();
|
||||
|
||||
/** Early de-initialization */
|
||||
void furi_hal_dma_deinit_early();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -11,20 +11,20 @@
|
||||
#define TAG "FuriHalFlash"
|
||||
|
||||
#define FURI_HAL_CRITICAL_MSG "Critical flash operation fail"
|
||||
#define FURI_HAL_FLASH_READ_BLOCK 8
|
||||
#define FURI_HAL_FLASH_WRITE_BLOCK 8
|
||||
#define FURI_HAL_FLASH_PAGE_SIZE 4096
|
||||
#define FURI_HAL_FLASH_CYCLES_COUNT 10000
|
||||
#define FURI_HAL_FLASH_TIMEOUT 1000
|
||||
#define FURI_HAL_FLASH_KEY1 0x45670123U
|
||||
#define FURI_HAL_FLASH_KEY2 0xCDEF89ABU
|
||||
#define FURI_HAL_FLASH_TOTAL_PAGES 256
|
||||
#define FURI_HAL_FLASH_READ_BLOCK (8U)
|
||||
#define FURI_HAL_FLASH_WRITE_BLOCK (8U)
|
||||
#define FURI_HAL_FLASH_PAGE_SIZE (4096U)
|
||||
#define FURI_HAL_FLASH_CYCLES_COUNT (10000U)
|
||||
#define FURI_HAL_FLASH_TIMEOUT (1000U)
|
||||
#define FURI_HAL_FLASH_KEY1 (0x45670123U)
|
||||
#define FURI_HAL_FLASH_KEY2 (0xCDEF89ABU)
|
||||
#define FURI_HAL_FLASH_TOTAL_PAGES (256U)
|
||||
#define FURI_HAL_FLASH_SR_ERRORS \
|
||||
(FLASH_SR_OPERR | FLASH_SR_PROGERR | FLASH_SR_WRPERR | FLASH_SR_PGAERR | FLASH_SR_SIZERR | \
|
||||
FLASH_SR_PGSERR | FLASH_SR_MISERR | FLASH_SR_FASTERR | FLASH_SR_RDERR | FLASH_SR_OPTVERR)
|
||||
|
||||
#define FURI_HAL_FLASH_OPT_KEY1 0x08192A3B
|
||||
#define FURI_HAL_FLASH_OPT_KEY2 0x4C5D6E7F
|
||||
#define FURI_HAL_FLASH_OPT_KEY1 (0x08192A3BU)
|
||||
#define FURI_HAL_FLASH_OPT_KEY2 (0x4C5D6E7FU)
|
||||
#define FURI_HAL_FLASH_OB_TOTAL_WORDS (0x80 / (sizeof(uint32_t) * 2))
|
||||
|
||||
/* STM32CubeWB/Projects/P-NUCLEO-WB55.Nucleo/Applications/BLE/BLE_RfWithFlash/Core/Src/flash_driver.c
|
||||
@ -35,7 +35,7 @@
|
||||
> If for any reason this test is never passed, this means there is a failure in the system and there is no other
|
||||
> way to recover than applying a device reset.
|
||||
*/
|
||||
#define FURI_HAL_FLASH_C2_LOCK_TIMEOUT_MS 3000u /* 3 seconds */
|
||||
#define FURI_HAL_FLASH_C2_LOCK_TIMEOUT_MS (3000U) /* 3 seconds */
|
||||
|
||||
#define IS_ADDR_ALIGNED_64BITS(__VALUE__) (((__VALUE__)&0x7U) == (0x00UL))
|
||||
#define IS_FLASH_PROGRAM_ADDRESS(__VALUE__) \
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
#include <furi_hal_i2c_config.h>
|
||||
#include <furi_hal_resources.h>
|
||||
#include <furi_hal_version.h>
|
||||
#include <stm32wbxx_ll_bus.h>
|
||||
#include <furi_hal_bus.h>
|
||||
|
||||
#include <stm32wbxx_ll_rcc.h>
|
||||
|
||||
/** Timing register value is computed with the STM32CubeMX Tool,
|
||||
@ -21,17 +22,9 @@ FuriMutex* furi_hal_i2c_bus_power_mutex = NULL;
|
||||
static void furi_hal_i2c_bus_power_event(FuriHalI2cBus* bus, FuriHalI2cBusEvent event) {
|
||||
if(event == FuriHalI2cBusEventInit) {
|
||||
furi_hal_i2c_bus_power_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_RCC_SetI2CClockSource(LL_RCC_I2C1_CLKSOURCE_PCLK1);
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C1);
|
||||
FURI_CRITICAL_EXIT();
|
||||
bus->current_handle = NULL;
|
||||
} else if(event == FuriHalI2cBusEventDeinit) {
|
||||
furi_mutex_free(furi_hal_i2c_bus_power_mutex);
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C1);
|
||||
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C1);
|
||||
FURI_CRITICAL_EXIT();
|
||||
} else if(event == FuriHalI2cBusEventLock) {
|
||||
furi_check(
|
||||
furi_mutex_acquire(furi_hal_i2c_bus_power_mutex, FuriWaitForever) == FuriStatusOk);
|
||||
@ -39,12 +32,11 @@ static void furi_hal_i2c_bus_power_event(FuriHalI2cBus* bus, FuriHalI2cBusEvent
|
||||
furi_check(furi_mutex_release(furi_hal_i2c_bus_power_mutex) == FuriStatusOk);
|
||||
} else if(event == FuriHalI2cBusEventActivate) {
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C1);
|
||||
furi_hal_bus_enable(FuriHalBusI2C1);
|
||||
LL_RCC_SetI2CClockSource(LL_RCC_I2C1_CLKSOURCE_PCLK1);
|
||||
FURI_CRITICAL_EXIT();
|
||||
} else if(event == FuriHalI2cBusEventDeactivate) {
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C1);
|
||||
FURI_CRITICAL_EXIT();
|
||||
furi_hal_bus_disable(FuriHalBusI2C1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,17 +50,9 @@ FuriMutex* furi_hal_i2c_bus_external_mutex = NULL;
|
||||
static void furi_hal_i2c_bus_external_event(FuriHalI2cBus* bus, FuriHalI2cBusEvent event) {
|
||||
if(event == FuriHalI2cBusEventInit) {
|
||||
furi_hal_i2c_bus_external_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_RCC_SetI2CClockSource(LL_RCC_I2C3_CLKSOURCE_PCLK1);
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C3);
|
||||
FURI_CRITICAL_EXIT();
|
||||
bus->current_handle = NULL;
|
||||
} else if(event == FuriHalI2cBusEventDeinit) {
|
||||
furi_mutex_free(furi_hal_i2c_bus_external_mutex);
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C3);
|
||||
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C3);
|
||||
FURI_CRITICAL_EXIT();
|
||||
} else if(event == FuriHalI2cBusEventLock) {
|
||||
furi_check(
|
||||
furi_mutex_acquire(furi_hal_i2c_bus_external_mutex, FuriWaitForever) == FuriStatusOk);
|
||||
@ -76,13 +60,11 @@ static void furi_hal_i2c_bus_external_event(FuriHalI2cBus* bus, FuriHalI2cBusEve
|
||||
furi_check(furi_mutex_release(furi_hal_i2c_bus_external_mutex) == FuriStatusOk);
|
||||
} else if(event == FuriHalI2cBusEventActivate) {
|
||||
FURI_CRITICAL_ENTER();
|
||||
furi_hal_bus_enable(FuriHalBusI2C3);
|
||||
LL_RCC_SetI2CClockSource(LL_RCC_I2C3_CLKSOURCE_PCLK1);
|
||||
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C3);
|
||||
FURI_CRITICAL_EXIT();
|
||||
} else if(event == FuriHalI2cBusEventDeactivate) {
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C3);
|
||||
FURI_CRITICAL_EXIT();
|
||||
furi_hal_bus_disable(FuriHalBusI2C3);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,14 +1,15 @@
|
||||
#include <furi_hal_ibutton.h>
|
||||
#include <furi_hal_interrupt.h>
|
||||
#include <furi_hal_resources.h>
|
||||
#include <furi_hal_bus.h>
|
||||
|
||||
#include <stm32wbxx_ll_tim.h>
|
||||
#include <stm32wbxx_ll_exti.h>
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#define TAG "FuriHalIbutton"
|
||||
#define FURI_HAL_IBUTTON_TIMER TIM1
|
||||
#define FURI_HAL_IBUTTON_TIMER_BUS FuriHalBusTIM1
|
||||
#define FURI_HAL_IBUTTON_TIMER_IRQ FuriHalInterruptIdTim1UpTim16
|
||||
|
||||
typedef enum {
|
||||
@ -49,9 +50,7 @@ void furi_hal_ibutton_emulate_start(
|
||||
furi_hal_ibutton->callback = callback;
|
||||
furi_hal_ibutton->context = context;
|
||||
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_TIM_DeInit(FURI_HAL_IBUTTON_TIMER);
|
||||
FURI_CRITICAL_EXIT();
|
||||
furi_hal_bus_enable(FURI_HAL_IBUTTON_TIMER_BUS);
|
||||
|
||||
furi_hal_interrupt_set_isr(FURI_HAL_IBUTTON_TIMER_IRQ, furi_hal_ibutton_emulate_isr, NULL);
|
||||
|
||||
@ -81,10 +80,7 @@ void furi_hal_ibutton_emulate_stop() {
|
||||
furi_hal_ibutton->state = FuriHalIbuttonStateIdle;
|
||||
LL_TIM_DisableCounter(FURI_HAL_IBUTTON_TIMER);
|
||||
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_TIM_DeInit(FURI_HAL_IBUTTON_TIMER);
|
||||
FURI_CRITICAL_EXIT();
|
||||
|
||||
furi_hal_bus_disable(FURI_HAL_IBUTTON_TIMER_BUS);
|
||||
furi_hal_interrupt_set_isr(FURI_HAL_IBUTTON_TIMER_IRQ, NULL, NULL);
|
||||
|
||||
furi_hal_ibutton->callback = NULL;
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <stm32wbxx_ll_lptim.h>
|
||||
#include <stm32wbxx_ll_bus.h>
|
||||
#include <stm32wbxx_ll_rcc.h>
|
||||
#include <stdint.h>
|
||||
#include <stm32wbxx_ll_bus.h>
|
||||
|
||||
#include <furi_hal_bus.h>
|
||||
|
||||
// Timer used for tickless idle
|
||||
#define FURI_HAL_IDLE_TIMER_MAX 0xFFFF
|
||||
@ -11,6 +12,7 @@
|
||||
#define FURI_HAL_IDLE_TIMER_IRQ LPTIM1_IRQn
|
||||
|
||||
static inline void furi_hal_idle_timer_init() {
|
||||
furi_hal_bus_enable(FuriHalBusLPTIM1);
|
||||
// Configure clock source
|
||||
LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM1_CLKSOURCE_LSE);
|
||||
// There is a theoretical possibility that we need it
|
||||
@ -41,7 +43,7 @@ static inline void furi_hal_idle_timer_start(uint32_t count) {
|
||||
static inline void furi_hal_idle_timer_reset() {
|
||||
// Hard reset timer
|
||||
// THE ONLY RELIABLE WAY to stop it according to errata
|
||||
LL_LPTIM_DeInit(FURI_HAL_IDLE_TIMER);
|
||||
furi_hal_bus_reset(FuriHalBusLPTIM1);
|
||||
// Prevent IRQ handler call
|
||||
NVIC_ClearPendingIRQ(FURI_HAL_IDLE_TIMER_IRQ);
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@ void furi_hal_info_get(PropertyValueCallback out, char sep, void* context) {
|
||||
property_value_out(&property_context, NULL, 2, "format", "minor", "1");
|
||||
} else {
|
||||
property_value_out(&property_context, NULL, 3, "device", "info", "major", "2");
|
||||
property_value_out(&property_context, NULL, 3, "device", "info", "minor", "1");
|
||||
property_value_out(&property_context, NULL, 3, "device", "info", "minor", "2");
|
||||
}
|
||||
|
||||
// Model name
|
||||
@ -173,6 +173,24 @@ void furi_hal_info_get(PropertyValueCallback out, char sep, void* context) {
|
||||
&property_context, "%d", 3, "firmware", "api", "major", api_version_major);
|
||||
property_value_out(
|
||||
&property_context, "%d", 3, "firmware", "api", "minor", api_version_minor);
|
||||
|
||||
property_value_out(
|
||||
&property_context,
|
||||
NULL,
|
||||
3,
|
||||
"firmware",
|
||||
"origin",
|
||||
"fork",
|
||||
version_get_firmware_origin(firmware_version));
|
||||
|
||||
property_value_out(
|
||||
&property_context,
|
||||
NULL,
|
||||
3,
|
||||
"firmware",
|
||||
"origin",
|
||||
"git",
|
||||
version_get_git_origin(firmware_version));
|
||||
}
|
||||
|
||||
if(furi_hal_bt_is_alive()) {
|
||||
|
||||
@ -1,23 +1,18 @@
|
||||
#include <furi_hal_infrared.h>
|
||||
#include <core/check.h>
|
||||
#include "stm32wbxx_ll_dma.h"
|
||||
#include "sys/_stdint.h"
|
||||
#include <furi_hal_interrupt.h>
|
||||
#include <furi_hal_resources.h>
|
||||
#include <furi_hal_bus.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stm32wbxx_ll_tim.h>
|
||||
#include <stm32wbxx_ll_gpio.h>
|
||||
#include <stm32wbxx_ll_dma.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <furi.h>
|
||||
#include <math.h>
|
||||
|
||||
#define INFRARED_TX_DEBUG 0
|
||||
// #define INFRARED_TX_DEBUG
|
||||
|
||||
#if INFRARED_TX_DEBUG == 1
|
||||
#define gpio_infrared_tx gpio_infrared_tx_debug
|
||||
const GpioPin gpio_infrared_tx_debug = {.port = GPIOA, .pin = GpioModeAnalog};
|
||||
#if defined INFRARED_TX_DEBUG
|
||||
#define gpio_infrared_tx gpio_ext_pa7
|
||||
#endif
|
||||
|
||||
#define INFRARED_TIM_TX_DMA_BUFFER_SIZE 200
|
||||
@ -29,13 +24,23 @@ const GpioPin gpio_infrared_tx_debug = {.port = GPIOA, .pin = GpioModeAnalog};
|
||||
(TIM_CCMR2_OC3PE | LL_TIM_OCMODE_FORCED_INACTIVE) /* Space time - force low */
|
||||
|
||||
/* DMA Channels definition */
|
||||
#define IR_DMA DMA2
|
||||
#define IR_DMA_CH1_CHANNEL LL_DMA_CHANNEL_1
|
||||
#define IR_DMA_CH2_CHANNEL LL_DMA_CHANNEL_2
|
||||
#define IR_DMA_CH1_IRQ FuriHalInterruptIdDma2Ch1
|
||||
#define IR_DMA_CH2_IRQ FuriHalInterruptIdDma2Ch2
|
||||
#define IR_DMA_CH1_DEF IR_DMA, IR_DMA_CH1_CHANNEL
|
||||
#define IR_DMA_CH2_DEF IR_DMA, IR_DMA_CH2_CHANNEL
|
||||
#define INFRARED_DMA DMA2
|
||||
#define INFRARED_DMA_CH1_CHANNEL LL_DMA_CHANNEL_1
|
||||
#define INFRARED_DMA_CH2_CHANNEL LL_DMA_CHANNEL_2
|
||||
#define INFRARED_DMA_CH1_IRQ FuriHalInterruptIdDma2Ch1
|
||||
#define INFRARED_DMA_CH2_IRQ FuriHalInterruptIdDma2Ch2
|
||||
#define INFRARED_DMA_CH1_DEF INFRARED_DMA, INFRARED_DMA_CH1_CHANNEL
|
||||
#define INFRARED_DMA_CH2_DEF INFRARED_DMA, INFRARED_DMA_CH2_CHANNEL
|
||||
|
||||
/* Timers definition */
|
||||
#define INFRARED_RX_TIMER TIM2
|
||||
#define INFRARED_DMA_TIMER TIM1
|
||||
#define INFRARED_RX_TIMER_BUS FuriHalBusTIM2
|
||||
#define INFRARED_DMA_TIMER_BUS FuriHalBusTIM1
|
||||
|
||||
/* Misc */
|
||||
#define INFRARED_RX_GPIO_ALT GpioAltFn1TIM2
|
||||
#define INFRARED_RX_IRQ FuriHalInterruptIdTIM2
|
||||
|
||||
typedef struct {
|
||||
FuriHalInfraredRxCaptureCallback capture_callback;
|
||||
@ -93,8 +98,8 @@ static void furi_hal_infrared_tim_rx_isr() {
|
||||
static uint32_t previous_captured_ch2 = 0;
|
||||
|
||||
/* Timeout */
|
||||
if(LL_TIM_IsActiveFlag_CC3(TIM2)) {
|
||||
LL_TIM_ClearFlag_CC3(TIM2);
|
||||
if(LL_TIM_IsActiveFlag_CC3(INFRARED_RX_TIMER)) {
|
||||
LL_TIM_ClearFlag_CC3(INFRARED_RX_TIMER);
|
||||
furi_assert(furi_hal_infrared_state == InfraredStateAsyncRx);
|
||||
|
||||
/* Timers CNT register starts to counting from 0 to ARR, but it is
|
||||
@ -110,13 +115,13 @@ static void furi_hal_infrared_tim_rx_isr() {
|
||||
}
|
||||
|
||||
/* Rising Edge */
|
||||
if(LL_TIM_IsActiveFlag_CC1(TIM2)) {
|
||||
LL_TIM_ClearFlag_CC1(TIM2);
|
||||
if(LL_TIM_IsActiveFlag_CC1(INFRARED_RX_TIMER)) {
|
||||
LL_TIM_ClearFlag_CC1(INFRARED_RX_TIMER);
|
||||
furi_assert(furi_hal_infrared_state == InfraredStateAsyncRx);
|
||||
|
||||
if(READ_BIT(TIM2->CCMR1, TIM_CCMR1_CC1S)) {
|
||||
if(READ_BIT(INFRARED_RX_TIMER->CCMR1, TIM_CCMR1_CC1S)) {
|
||||
/* Low pin level is a Mark state of INFRARED signal. Invert level for further processing. */
|
||||
uint32_t duration = LL_TIM_IC_GetCaptureCH1(TIM2) - previous_captured_ch2;
|
||||
uint32_t duration = LL_TIM_IC_GetCaptureCH1(INFRARED_RX_TIMER) - previous_captured_ch2;
|
||||
if(infrared_tim_rx.capture_callback)
|
||||
infrared_tim_rx.capture_callback(infrared_tim_rx.capture_context, 1, duration);
|
||||
} else {
|
||||
@ -125,13 +130,13 @@ static void furi_hal_infrared_tim_rx_isr() {
|
||||
}
|
||||
|
||||
/* Falling Edge */
|
||||
if(LL_TIM_IsActiveFlag_CC2(TIM2)) {
|
||||
LL_TIM_ClearFlag_CC2(TIM2);
|
||||
if(LL_TIM_IsActiveFlag_CC2(INFRARED_RX_TIMER)) {
|
||||
LL_TIM_ClearFlag_CC2(INFRARED_RX_TIMER);
|
||||
furi_assert(furi_hal_infrared_state == InfraredStateAsyncRx);
|
||||
|
||||
if(READ_BIT(TIM2->CCMR1, TIM_CCMR1_CC2S)) {
|
||||
if(READ_BIT(INFRARED_RX_TIMER->CCMR1, TIM_CCMR1_CC2S)) {
|
||||
/* High pin level is a Space state of INFRARED signal. Invert level for further processing. */
|
||||
uint32_t duration = LL_TIM_IC_GetCaptureCH2(TIM2);
|
||||
uint32_t duration = LL_TIM_IC_GetCaptureCH2(INFRARED_RX_TIMER);
|
||||
previous_captured_ch2 = duration;
|
||||
if(infrared_tim_rx.capture_callback)
|
||||
infrared_tim_rx.capture_callback(infrared_tim_rx.capture_context, 0, duration);
|
||||
@ -145,62 +150,66 @@ void furi_hal_infrared_async_rx_start(void) {
|
||||
furi_assert(furi_hal_infrared_state == InfraredStateIdle);
|
||||
|
||||
furi_hal_gpio_init_ex(
|
||||
&gpio_infrared_rx, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedLow, GpioAltFn1TIM2);
|
||||
&gpio_infrared_rx,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedLow,
|
||||
INFRARED_RX_GPIO_ALT);
|
||||
|
||||
furi_hal_bus_enable(INFRARED_RX_TIMER_BUS);
|
||||
|
||||
LL_TIM_InitTypeDef TIM_InitStruct = {0};
|
||||
TIM_InitStruct.Prescaler = 64 - 1;
|
||||
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
|
||||
TIM_InitStruct.Autoreload = 0x7FFFFFFE;
|
||||
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
|
||||
LL_TIM_Init(TIM2, &TIM_InitStruct);
|
||||
LL_TIM_Init(INFRARED_RX_TIMER, &TIM_InitStruct);
|
||||
|
||||
LL_TIM_SetClockSource(TIM2, LL_TIM_CLOCKSOURCE_INTERNAL);
|
||||
LL_TIM_DisableARRPreload(TIM2);
|
||||
LL_TIM_SetTriggerInput(TIM2, LL_TIM_TS_TI1FP1);
|
||||
LL_TIM_SetSlaveMode(TIM2, LL_TIM_SLAVEMODE_RESET);
|
||||
LL_TIM_CC_DisableChannel(TIM2, LL_TIM_CHANNEL_CH2);
|
||||
LL_TIM_IC_SetFilter(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_IC_FILTER_FDIV1);
|
||||
LL_TIM_IC_SetPolarity(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_IC_POLARITY_FALLING);
|
||||
LL_TIM_DisableIT_TRIG(TIM2);
|
||||
LL_TIM_DisableDMAReq_TRIG(TIM2);
|
||||
LL_TIM_SetTriggerOutput(TIM2, LL_TIM_TRGO_RESET);
|
||||
LL_TIM_EnableMasterSlaveMode(TIM2);
|
||||
LL_TIM_IC_SetActiveInput(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_ACTIVEINPUT_DIRECTTI);
|
||||
LL_TIM_IC_SetPrescaler(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_ICPSC_DIV1);
|
||||
LL_TIM_IC_SetFilter(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_IC_FILTER_FDIV1);
|
||||
LL_TIM_IC_SetPolarity(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_IC_POLARITY_RISING);
|
||||
LL_TIM_IC_SetActiveInput(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_ACTIVEINPUT_INDIRECTTI);
|
||||
LL_TIM_IC_SetPrescaler(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_ICPSC_DIV1);
|
||||
LL_TIM_SetClockSource(INFRARED_RX_TIMER, LL_TIM_CLOCKSOURCE_INTERNAL);
|
||||
LL_TIM_DisableARRPreload(INFRARED_RX_TIMER);
|
||||
LL_TIM_SetTriggerInput(INFRARED_RX_TIMER, LL_TIM_TS_TI1FP1);
|
||||
LL_TIM_SetSlaveMode(INFRARED_RX_TIMER, LL_TIM_SLAVEMODE_RESET);
|
||||
LL_TIM_CC_DisableChannel(INFRARED_RX_TIMER, LL_TIM_CHANNEL_CH2);
|
||||
LL_TIM_IC_SetFilter(INFRARED_RX_TIMER, LL_TIM_CHANNEL_CH2, LL_TIM_IC_FILTER_FDIV1);
|
||||
LL_TIM_IC_SetPolarity(INFRARED_RX_TIMER, LL_TIM_CHANNEL_CH2, LL_TIM_IC_POLARITY_FALLING);
|
||||
LL_TIM_DisableIT_TRIG(INFRARED_RX_TIMER);
|
||||
LL_TIM_DisableDMAReq_TRIG(INFRARED_RX_TIMER);
|
||||
LL_TIM_SetTriggerOutput(INFRARED_RX_TIMER, LL_TIM_TRGO_RESET);
|
||||
LL_TIM_EnableMasterSlaveMode(INFRARED_RX_TIMER);
|
||||
LL_TIM_IC_SetActiveInput(INFRARED_RX_TIMER, LL_TIM_CHANNEL_CH1, LL_TIM_ACTIVEINPUT_DIRECTTI);
|
||||
LL_TIM_IC_SetPrescaler(INFRARED_RX_TIMER, LL_TIM_CHANNEL_CH1, LL_TIM_ICPSC_DIV1);
|
||||
LL_TIM_IC_SetFilter(INFRARED_RX_TIMER, LL_TIM_CHANNEL_CH1, LL_TIM_IC_FILTER_FDIV1);
|
||||
LL_TIM_IC_SetPolarity(INFRARED_RX_TIMER, LL_TIM_CHANNEL_CH1, LL_TIM_IC_POLARITY_RISING);
|
||||
LL_TIM_IC_SetActiveInput(INFRARED_RX_TIMER, LL_TIM_CHANNEL_CH2, LL_TIM_ACTIVEINPUT_INDIRECTTI);
|
||||
LL_TIM_IC_SetPrescaler(INFRARED_RX_TIMER, LL_TIM_CHANNEL_CH2, LL_TIM_ICPSC_DIV1);
|
||||
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, furi_hal_infrared_tim_rx_isr, NULL);
|
||||
furi_hal_interrupt_set_isr(INFRARED_RX_IRQ, furi_hal_infrared_tim_rx_isr, NULL);
|
||||
furi_hal_infrared_state = InfraredStateAsyncRx;
|
||||
|
||||
LL_TIM_EnableIT_CC1(TIM2);
|
||||
LL_TIM_EnableIT_CC2(TIM2);
|
||||
LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH1);
|
||||
LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH2);
|
||||
LL_TIM_EnableIT_CC1(INFRARED_RX_TIMER);
|
||||
LL_TIM_EnableIT_CC2(INFRARED_RX_TIMER);
|
||||
LL_TIM_CC_EnableChannel(INFRARED_RX_TIMER, LL_TIM_CHANNEL_CH1);
|
||||
LL_TIM_CC_EnableChannel(INFRARED_RX_TIMER, LL_TIM_CHANNEL_CH2);
|
||||
|
||||
LL_TIM_SetCounter(TIM2, 0);
|
||||
LL_TIM_EnableCounter(TIM2);
|
||||
LL_TIM_SetCounter(INFRARED_RX_TIMER, 0);
|
||||
LL_TIM_EnableCounter(INFRARED_RX_TIMER);
|
||||
}
|
||||
|
||||
void furi_hal_infrared_async_rx_stop(void) {
|
||||
furi_assert(furi_hal_infrared_state == InfraredStateAsyncRx);
|
||||
|
||||
FURI_CRITICAL_ENTER();
|
||||
|
||||
LL_TIM_DeInit(TIM2);
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, NULL, NULL);
|
||||
furi_hal_bus_disable(INFRARED_RX_TIMER_BUS);
|
||||
furi_hal_interrupt_set_isr(INFRARED_RX_IRQ, NULL, NULL);
|
||||
furi_hal_infrared_state = InfraredStateIdle;
|
||||
|
||||
FURI_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
void furi_hal_infrared_async_rx_set_timeout(uint32_t timeout_us) {
|
||||
LL_TIM_OC_SetCompareCH3(TIM2, timeout_us);
|
||||
LL_TIM_OC_SetMode(TIM2, LL_TIM_CHANNEL_CH3, LL_TIM_OCMODE_ACTIVE);
|
||||
LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH3);
|
||||
LL_TIM_EnableIT_CC3(TIM2);
|
||||
LL_TIM_OC_SetCompareCH3(INFRARED_RX_TIMER, timeout_us);
|
||||
LL_TIM_OC_SetMode(INFRARED_RX_TIMER, LL_TIM_CHANNEL_CH3, LL_TIM_OCMODE_ACTIVE);
|
||||
LL_TIM_CC_EnableChannel(INFRARED_RX_TIMER, LL_TIM_CHANNEL_CH3);
|
||||
LL_TIM_EnableIT_CC3(INFRARED_RX_TIMER);
|
||||
}
|
||||
|
||||
bool furi_hal_infrared_is_busy(void) {
|
||||
@ -222,16 +231,16 @@ void furi_hal_infrared_async_rx_set_timeout_isr_callback(
|
||||
}
|
||||
|
||||
static void furi_hal_infrared_tx_dma_terminate(void) {
|
||||
LL_DMA_DisableIT_TC(IR_DMA_CH1_DEF);
|
||||
LL_DMA_DisableIT_HT(IR_DMA_CH2_DEF);
|
||||
LL_DMA_DisableIT_TC(IR_DMA_CH2_DEF);
|
||||
LL_DMA_DisableIT_TC(INFRARED_DMA_CH1_DEF);
|
||||
LL_DMA_DisableIT_HT(INFRARED_DMA_CH2_DEF);
|
||||
LL_DMA_DisableIT_TC(INFRARED_DMA_CH2_DEF);
|
||||
|
||||
furi_assert(furi_hal_infrared_state == InfraredStateAsyncTxStopInProgress);
|
||||
|
||||
LL_DMA_DisableIT_TC(IR_DMA_CH1_DEF);
|
||||
LL_DMA_DisableChannel(IR_DMA_CH2_DEF);
|
||||
LL_DMA_DisableChannel(IR_DMA_CH1_DEF);
|
||||
LL_TIM_DisableCounter(TIM1);
|
||||
LL_DMA_DisableIT_TC(INFRARED_DMA_CH1_DEF);
|
||||
LL_DMA_DisableChannel(INFRARED_DMA_CH2_DEF);
|
||||
LL_DMA_DisableChannel(INFRARED_DMA_CH1_DEF);
|
||||
LL_TIM_DisableCounter(INFRARED_DMA_TIMER);
|
||||
FuriStatus status = furi_semaphore_release(infrared_tim_tx.stop_semaphore);
|
||||
furi_check(status == FuriStatusOk);
|
||||
furi_hal_infrared_state = InfraredStateAsyncTxStopped;
|
||||
@ -239,7 +248,7 @@ static void furi_hal_infrared_tx_dma_terminate(void) {
|
||||
|
||||
static uint8_t furi_hal_infrared_get_current_dma_tx_buffer(void) {
|
||||
uint8_t buf_num = 0;
|
||||
uint32_t buffer_adr = LL_DMA_GetMemoryAddress(IR_DMA_CH2_DEF);
|
||||
uint32_t buffer_adr = LL_DMA_GetMemoryAddress(INFRARED_DMA_CH2_DEF);
|
||||
if(buffer_adr == (uint32_t)infrared_tim_tx.buffer[0].data) {
|
||||
buf_num = 0;
|
||||
} else if(buffer_adr == (uint32_t)infrared_tim_tx.buffer[1].data) {
|
||||
@ -251,13 +260,13 @@ static uint8_t furi_hal_infrared_get_current_dma_tx_buffer(void) {
|
||||
}
|
||||
|
||||
static void furi_hal_infrared_tx_dma_polarity_isr() {
|
||||
#if IR_DMA_CH1_CHANNEL == LL_DMA_CHANNEL_1
|
||||
if(LL_DMA_IsActiveFlag_TE1(IR_DMA)) {
|
||||
LL_DMA_ClearFlag_TE1(IR_DMA);
|
||||
#if INFRARED_DMA_CH1_CHANNEL == LL_DMA_CHANNEL_1
|
||||
if(LL_DMA_IsActiveFlag_TE1(INFRARED_DMA)) {
|
||||
LL_DMA_ClearFlag_TE1(INFRARED_DMA);
|
||||
furi_crash(NULL);
|
||||
}
|
||||
if(LL_DMA_IsActiveFlag_TC1(IR_DMA) && LL_DMA_IsEnabledIT_TC(IR_DMA_CH1_DEF)) {
|
||||
LL_DMA_ClearFlag_TC1(IR_DMA);
|
||||
if(LL_DMA_IsActiveFlag_TC1(INFRARED_DMA) && LL_DMA_IsEnabledIT_TC(INFRARED_DMA_CH1_DEF)) {
|
||||
LL_DMA_ClearFlag_TC1(INFRARED_DMA);
|
||||
|
||||
furi_check(
|
||||
(furi_hal_infrared_state == InfraredStateAsyncTx) ||
|
||||
@ -273,23 +282,23 @@ static void furi_hal_infrared_tx_dma_polarity_isr() {
|
||||
}
|
||||
|
||||
static void furi_hal_infrared_tx_dma_isr() {
|
||||
#if IR_DMA_CH2_CHANNEL == LL_DMA_CHANNEL_2
|
||||
if(LL_DMA_IsActiveFlag_TE2(IR_DMA)) {
|
||||
LL_DMA_ClearFlag_TE2(IR_DMA);
|
||||
#if INFRARED_DMA_CH2_CHANNEL == LL_DMA_CHANNEL_2
|
||||
if(LL_DMA_IsActiveFlag_TE2(INFRARED_DMA)) {
|
||||
LL_DMA_ClearFlag_TE2(INFRARED_DMA);
|
||||
furi_crash(NULL);
|
||||
}
|
||||
if(LL_DMA_IsActiveFlag_HT2(IR_DMA) && LL_DMA_IsEnabledIT_HT(IR_DMA_CH2_DEF)) {
|
||||
LL_DMA_ClearFlag_HT2(IR_DMA);
|
||||
if(LL_DMA_IsActiveFlag_HT2(INFRARED_DMA) && LL_DMA_IsEnabledIT_HT(INFRARED_DMA_CH2_DEF)) {
|
||||
LL_DMA_ClearFlag_HT2(INFRARED_DMA);
|
||||
uint8_t buf_num = furi_hal_infrared_get_current_dma_tx_buffer();
|
||||
uint8_t next_buf_num = !buf_num;
|
||||
if(infrared_tim_tx.buffer[buf_num].last_packet_end) {
|
||||
LL_DMA_DisableIT_HT(IR_DMA_CH2_DEF);
|
||||
LL_DMA_DisableIT_HT(INFRARED_DMA_CH2_DEF);
|
||||
} else if(
|
||||
!infrared_tim_tx.buffer[buf_num].packet_end ||
|
||||
(furi_hal_infrared_state == InfraredStateAsyncTx)) {
|
||||
furi_hal_infrared_tx_fill_buffer(next_buf_num, 0);
|
||||
if(infrared_tim_tx.buffer[next_buf_num].last_packet_end) {
|
||||
LL_DMA_DisableIT_HT(IR_DMA_CH2_DEF);
|
||||
LL_DMA_DisableIT_HT(INFRARED_DMA_CH2_DEF);
|
||||
}
|
||||
} else if(furi_hal_infrared_state == InfraredStateAsyncTxStopReq) {
|
||||
/* fallthrough */
|
||||
@ -297,8 +306,8 @@ static void furi_hal_infrared_tx_dma_isr() {
|
||||
furi_crash(NULL);
|
||||
}
|
||||
}
|
||||
if(LL_DMA_IsActiveFlag_TC2(IR_DMA) && LL_DMA_IsEnabledIT_TC(IR_DMA_CH2_DEF)) {
|
||||
LL_DMA_ClearFlag_TC2(IR_DMA);
|
||||
if(LL_DMA_IsActiveFlag_TC2(INFRARED_DMA) && LL_DMA_IsEnabledIT_TC(INFRARED_DMA_CH2_DEF)) {
|
||||
LL_DMA_ClearFlag_TC2(INFRARED_DMA);
|
||||
furi_check(
|
||||
(furi_hal_infrared_state == InfraredStateAsyncTxStopInProgress) ||
|
||||
(furi_hal_infrared_state == InfraredStateAsyncTxStopReq) ||
|
||||
@ -330,39 +339,40 @@ static void furi_hal_infrared_tx_dma_isr() {
|
||||
}
|
||||
|
||||
static void furi_hal_infrared_configure_tim_pwm_tx(uint32_t freq, float duty_cycle) {
|
||||
/* LL_DBGMCU_APB2_GRP1_FreezePeriph(LL_DBGMCU_APB2_GRP1_TIM1_STOP); */
|
||||
|
||||
LL_TIM_DisableCounter(TIM1);
|
||||
LL_TIM_SetRepetitionCounter(TIM1, 0);
|
||||
LL_TIM_SetCounter(TIM1, 0);
|
||||
LL_TIM_SetPrescaler(TIM1, 0);
|
||||
LL_TIM_SetCounterMode(TIM1, LL_TIM_COUNTERMODE_UP);
|
||||
LL_TIM_EnableARRPreload(TIM1);
|
||||
LL_TIM_DisableCounter(INFRARED_DMA_TIMER);
|
||||
LL_TIM_SetRepetitionCounter(INFRARED_DMA_TIMER, 0);
|
||||
LL_TIM_SetCounter(INFRARED_DMA_TIMER, 0);
|
||||
LL_TIM_SetPrescaler(INFRARED_DMA_TIMER, 0);
|
||||
LL_TIM_SetCounterMode(INFRARED_DMA_TIMER, LL_TIM_COUNTERMODE_UP);
|
||||
LL_TIM_EnableARRPreload(INFRARED_DMA_TIMER);
|
||||
LL_TIM_SetAutoReload(
|
||||
TIM1, __LL_TIM_CALC_ARR(SystemCoreClock, LL_TIM_GetPrescaler(TIM1), freq));
|
||||
#if INFRARED_TX_DEBUG == 1
|
||||
LL_TIM_OC_SetCompareCH1(TIM1, ((LL_TIM_GetAutoReload(TIM1) + 1) * (1 - duty_cycle)));
|
||||
LL_TIM_OC_EnablePreload(TIM1, LL_TIM_CHANNEL_CH1);
|
||||
INFRARED_DMA_TIMER,
|
||||
__LL_TIM_CALC_ARR(SystemCoreClock, LL_TIM_GetPrescaler(INFRARED_DMA_TIMER), freq));
|
||||
#if defined INFRARED_TX_DEBUG
|
||||
LL_TIM_OC_SetCompareCH1(
|
||||
INFRARED_DMA_TIMER, ((LL_TIM_GetAutoReload(INFRARED_DMA_TIMER) + 1) * (1 - duty_cycle)));
|
||||
LL_TIM_OC_EnablePreload(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1);
|
||||
/* LL_TIM_OCMODE_PWM2 set by DMA */
|
||||
LL_TIM_OC_SetMode(TIM1, LL_TIM_CHANNEL_CH1, LL_TIM_OCMODE_FORCED_INACTIVE);
|
||||
LL_TIM_OC_SetPolarity(TIM1, LL_TIM_CHANNEL_CH1N, LL_TIM_OCPOLARITY_HIGH);
|
||||
LL_TIM_OC_DisableFast(TIM1, LL_TIM_CHANNEL_CH1);
|
||||
LL_TIM_CC_EnableChannel(TIM1, LL_TIM_CHANNEL_CH1N);
|
||||
LL_TIM_DisableIT_CC1(TIM1);
|
||||
LL_TIM_OC_SetMode(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1, LL_TIM_OCMODE_FORCED_INACTIVE);
|
||||
LL_TIM_OC_SetPolarity(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1N, LL_TIM_OCPOLARITY_HIGH);
|
||||
LL_TIM_OC_DisableFast(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1);
|
||||
LL_TIM_CC_EnableChannel(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1N);
|
||||
LL_TIM_DisableIT_CC1(INFRARED_DMA_TIMER);
|
||||
#else
|
||||
LL_TIM_OC_SetCompareCH3(TIM1, ((LL_TIM_GetAutoReload(TIM1) + 1) * (1 - duty_cycle)));
|
||||
LL_TIM_OC_EnablePreload(TIM1, LL_TIM_CHANNEL_CH3);
|
||||
LL_TIM_OC_SetCompareCH3(
|
||||
INFRARED_DMA_TIMER, ((LL_TIM_GetAutoReload(INFRARED_DMA_TIMER) + 1) * (1 - duty_cycle)));
|
||||
LL_TIM_OC_EnablePreload(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH3);
|
||||
/* LL_TIM_OCMODE_PWM2 set by DMA */
|
||||
LL_TIM_OC_SetMode(TIM1, LL_TIM_CHANNEL_CH3, LL_TIM_OCMODE_FORCED_INACTIVE);
|
||||
LL_TIM_OC_SetPolarity(TIM1, LL_TIM_CHANNEL_CH3N, LL_TIM_OCPOLARITY_HIGH);
|
||||
LL_TIM_OC_DisableFast(TIM1, LL_TIM_CHANNEL_CH3);
|
||||
LL_TIM_CC_EnableChannel(TIM1, LL_TIM_CHANNEL_CH3N);
|
||||
LL_TIM_DisableIT_CC3(TIM1);
|
||||
LL_TIM_OC_SetMode(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH3, LL_TIM_OCMODE_FORCED_INACTIVE);
|
||||
LL_TIM_OC_SetPolarity(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH3N, LL_TIM_OCPOLARITY_HIGH);
|
||||
LL_TIM_OC_DisableFast(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH3);
|
||||
LL_TIM_CC_EnableChannel(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH3N);
|
||||
LL_TIM_DisableIT_CC3(INFRARED_DMA_TIMER);
|
||||
#endif
|
||||
LL_TIM_DisableMasterSlaveMode(TIM1);
|
||||
LL_TIM_EnableAllOutputs(TIM1);
|
||||
LL_TIM_DisableIT_UPDATE(TIM1);
|
||||
LL_TIM_EnableDMAReq_UPDATE(TIM1);
|
||||
LL_TIM_DisableMasterSlaveMode(INFRARED_DMA_TIMER);
|
||||
LL_TIM_EnableAllOutputs(INFRARED_DMA_TIMER);
|
||||
LL_TIM_DisableIT_UPDATE(INFRARED_DMA_TIMER);
|
||||
LL_TIM_EnableDMAReq_UPDATE(INFRARED_DMA_TIMER);
|
||||
|
||||
NVIC_SetPriority(TIM1_UP_TIM16_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
|
||||
NVIC_EnableIRQ(TIM1_UP_TIM16_IRQn);
|
||||
@ -370,10 +380,10 @@ static void furi_hal_infrared_configure_tim_pwm_tx(uint32_t freq, float duty_cyc
|
||||
|
||||
static void furi_hal_infrared_configure_tim_cmgr2_dma_tx(void) {
|
||||
LL_DMA_InitTypeDef dma_config = {0};
|
||||
#if INFRARED_TX_DEBUG == 1
|
||||
dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (TIM1->CCMR1);
|
||||
#if defined INFRARED_TX_DEBUG
|
||||
dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (INFRARED_DMA_TIMER->CCMR1);
|
||||
#else
|
||||
dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (TIM1->CCMR2);
|
||||
dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (INFRARED_DMA_TIMER->CCMR2);
|
||||
#endif
|
||||
dma_config.MemoryOrM2MDstAddress = (uint32_t)NULL;
|
||||
dma_config.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;
|
||||
@ -386,24 +396,25 @@ static void furi_hal_infrared_configure_tim_cmgr2_dma_tx(void) {
|
||||
dma_config.NbData = 0;
|
||||
dma_config.PeriphRequest = LL_DMAMUX_REQ_TIM1_UP;
|
||||
dma_config.Priority = LL_DMA_PRIORITY_VERYHIGH;
|
||||
LL_DMA_Init(IR_DMA_CH1_DEF, &dma_config);
|
||||
LL_DMA_Init(INFRARED_DMA_CH1_DEF, &dma_config);
|
||||
|
||||
#if IR_DMA_CH1_CHANNEL == LL_DMA_CHANNEL_1
|
||||
LL_DMA_ClearFlag_TE1(IR_DMA);
|
||||
LL_DMA_ClearFlag_TC1(IR_DMA);
|
||||
#if INFRARED_DMA_CH1_CHANNEL == LL_DMA_CHANNEL_1
|
||||
LL_DMA_ClearFlag_TE1(INFRARED_DMA);
|
||||
LL_DMA_ClearFlag_TC1(INFRARED_DMA);
|
||||
#else
|
||||
#error Update this code. Would you kindly?
|
||||
#endif
|
||||
|
||||
LL_DMA_EnableIT_TE(IR_DMA_CH1_DEF);
|
||||
LL_DMA_EnableIT_TC(IR_DMA_CH1_DEF);
|
||||
LL_DMA_EnableIT_TE(INFRARED_DMA_CH1_DEF);
|
||||
LL_DMA_EnableIT_TC(INFRARED_DMA_CH1_DEF);
|
||||
|
||||
furi_hal_interrupt_set_isr_ex(IR_DMA_CH1_IRQ, 4, furi_hal_infrared_tx_dma_polarity_isr, NULL);
|
||||
furi_hal_interrupt_set_isr_ex(
|
||||
INFRARED_DMA_CH1_IRQ, 4, furi_hal_infrared_tx_dma_polarity_isr, NULL);
|
||||
}
|
||||
|
||||
static void furi_hal_infrared_configure_tim_rcr_dma_tx(void) {
|
||||
LL_DMA_InitTypeDef dma_config = {0};
|
||||
dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (TIM1->RCR);
|
||||
dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (INFRARED_DMA_TIMER->RCR);
|
||||
dma_config.MemoryOrM2MDstAddress = (uint32_t)NULL;
|
||||
dma_config.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;
|
||||
dma_config.Mode = LL_DMA_MODE_NORMAL;
|
||||
@ -414,21 +425,21 @@ static void furi_hal_infrared_configure_tim_rcr_dma_tx(void) {
|
||||
dma_config.NbData = 0;
|
||||
dma_config.PeriphRequest = LL_DMAMUX_REQ_TIM1_UP;
|
||||
dma_config.Priority = LL_DMA_PRIORITY_MEDIUM;
|
||||
LL_DMA_Init(IR_DMA_CH2_DEF, &dma_config);
|
||||
LL_DMA_Init(INFRARED_DMA_CH2_DEF, &dma_config);
|
||||
|
||||
#if IR_DMA_CH2_CHANNEL == LL_DMA_CHANNEL_2
|
||||
LL_DMA_ClearFlag_TC2(IR_DMA);
|
||||
LL_DMA_ClearFlag_HT2(IR_DMA);
|
||||
LL_DMA_ClearFlag_TE2(IR_DMA);
|
||||
#if INFRARED_DMA_CH2_CHANNEL == LL_DMA_CHANNEL_2
|
||||
LL_DMA_ClearFlag_TC2(INFRARED_DMA);
|
||||
LL_DMA_ClearFlag_HT2(INFRARED_DMA);
|
||||
LL_DMA_ClearFlag_TE2(INFRARED_DMA);
|
||||
#else
|
||||
#error Update this code. Would you kindly?
|
||||
#endif
|
||||
|
||||
LL_DMA_EnableIT_TC(IR_DMA_CH2_DEF);
|
||||
LL_DMA_EnableIT_HT(IR_DMA_CH2_DEF);
|
||||
LL_DMA_EnableIT_TE(IR_DMA_CH2_DEF);
|
||||
LL_DMA_EnableIT_TC(INFRARED_DMA_CH2_DEF);
|
||||
LL_DMA_EnableIT_HT(INFRARED_DMA_CH2_DEF);
|
||||
LL_DMA_EnableIT_TE(INFRARED_DMA_CH2_DEF);
|
||||
|
||||
furi_hal_interrupt_set_isr_ex(IR_DMA_CH2_IRQ, 5, furi_hal_infrared_tx_dma_isr, NULL);
|
||||
furi_hal_interrupt_set_isr_ex(INFRARED_DMA_CH2_IRQ, 5, furi_hal_infrared_tx_dma_isr, NULL);
|
||||
}
|
||||
|
||||
static void furi_hal_infrared_tx_fill_buffer_last(uint8_t buf_num) {
|
||||
@ -530,14 +541,14 @@ static void furi_hal_infrared_tx_dma_set_polarity(uint8_t buf_num, uint8_t polar
|
||||
furi_assert(buffer->polarity != NULL);
|
||||
|
||||
FURI_CRITICAL_ENTER();
|
||||
bool channel_enabled = LL_DMA_IsEnabledChannel(IR_DMA_CH1_DEF);
|
||||
bool channel_enabled = LL_DMA_IsEnabledChannel(INFRARED_DMA_CH1_DEF);
|
||||
if(channel_enabled) {
|
||||
LL_DMA_DisableChannel(IR_DMA_CH1_DEF);
|
||||
LL_DMA_DisableChannel(INFRARED_DMA_CH1_DEF);
|
||||
}
|
||||
LL_DMA_SetMemoryAddress(IR_DMA_CH1_DEF, (uint32_t)buffer->polarity);
|
||||
LL_DMA_SetDataLength(IR_DMA_CH1_DEF, buffer->size + polarity_shift);
|
||||
LL_DMA_SetMemoryAddress(INFRARED_DMA_CH1_DEF, (uint32_t)buffer->polarity);
|
||||
LL_DMA_SetDataLength(INFRARED_DMA_CH1_DEF, buffer->size + polarity_shift);
|
||||
if(channel_enabled) {
|
||||
LL_DMA_EnableChannel(IR_DMA_CH1_DEF);
|
||||
LL_DMA_EnableChannel(INFRARED_DMA_CH1_DEF);
|
||||
}
|
||||
FURI_CRITICAL_EXIT();
|
||||
}
|
||||
@ -550,14 +561,14 @@ static void furi_hal_infrared_tx_dma_set_buffer(uint8_t buf_num) {
|
||||
|
||||
/* non-circular mode requires disabled channel before setup */
|
||||
FURI_CRITICAL_ENTER();
|
||||
bool channel_enabled = LL_DMA_IsEnabledChannel(IR_DMA_CH2_DEF);
|
||||
bool channel_enabled = LL_DMA_IsEnabledChannel(INFRARED_DMA_CH2_DEF);
|
||||
if(channel_enabled) {
|
||||
LL_DMA_DisableChannel(IR_DMA_CH2_DEF);
|
||||
LL_DMA_DisableChannel(INFRARED_DMA_CH2_DEF);
|
||||
}
|
||||
LL_DMA_SetMemoryAddress(IR_DMA_CH2_DEF, (uint32_t)buffer->data);
|
||||
LL_DMA_SetDataLength(IR_DMA_CH2_DEF, buffer->size);
|
||||
LL_DMA_SetMemoryAddress(INFRARED_DMA_CH2_DEF, (uint32_t)buffer->data);
|
||||
LL_DMA_SetDataLength(INFRARED_DMA_CH2_DEF, buffer->size);
|
||||
if(channel_enabled) {
|
||||
LL_DMA_EnableChannel(IR_DMA_CH2_DEF);
|
||||
LL_DMA_EnableChannel(INFRARED_DMA_CH2_DEF);
|
||||
}
|
||||
FURI_CRITICAL_EXIT();
|
||||
}
|
||||
@ -568,9 +579,10 @@ static void furi_hal_infrared_async_tx_free_resources(void) {
|
||||
(furi_hal_infrared_state == InfraredStateAsyncTxStopped));
|
||||
|
||||
furi_hal_gpio_init(&gpio_infrared_tx, GpioModeAnalog, GpioPullDown, GpioSpeedLow);
|
||||
furi_hal_interrupt_set_isr(IR_DMA_CH1_IRQ, NULL, NULL);
|
||||
furi_hal_interrupt_set_isr(IR_DMA_CH2_IRQ, NULL, NULL);
|
||||
LL_TIM_DeInit(TIM1);
|
||||
furi_hal_interrupt_set_isr(INFRARED_DMA_CH1_IRQ, NULL, NULL);
|
||||
furi_hal_interrupt_set_isr(INFRARED_DMA_CH2_IRQ, NULL, NULL);
|
||||
|
||||
furi_hal_bus_disable(INFRARED_DMA_TIMER_BUS);
|
||||
|
||||
furi_semaphore_free(infrared_tim_tx.stop_semaphore);
|
||||
free(infrared_tim_tx.buffer[0].data);
|
||||
@ -611,6 +623,8 @@ void furi_hal_infrared_async_tx_start(uint32_t freq, float duty_cycle) {
|
||||
|
||||
furi_hal_infrared_tx_fill_buffer(0, INFRARED_POLARITY_SHIFT);
|
||||
|
||||
furi_hal_bus_enable(INFRARED_DMA_TIMER_BUS);
|
||||
|
||||
furi_hal_infrared_configure_tim_pwm_tx(freq, duty_cycle);
|
||||
furi_hal_infrared_configure_tim_cmgr2_dma_tx();
|
||||
furi_hal_infrared_configure_tim_rcr_dma_tx();
|
||||
@ -619,11 +633,11 @@ void furi_hal_infrared_async_tx_start(uint32_t freq, float duty_cycle) {
|
||||
|
||||
furi_hal_infrared_state = InfraredStateAsyncTx;
|
||||
|
||||
LL_TIM_ClearFlag_UPDATE(TIM1);
|
||||
LL_DMA_EnableChannel(IR_DMA_CH1_DEF);
|
||||
LL_DMA_EnableChannel(IR_DMA_CH2_DEF);
|
||||
LL_TIM_ClearFlag_UPDATE(INFRARED_DMA_TIMER);
|
||||
LL_DMA_EnableChannel(INFRARED_DMA_CH1_DEF);
|
||||
LL_DMA_EnableChannel(INFRARED_DMA_CH2_DEF);
|
||||
furi_delay_us(5);
|
||||
LL_TIM_GenerateEvent_UPDATE(TIM1); /* DMA -> TIMx_RCR */
|
||||
LL_TIM_GenerateEvent_UPDATE(INFRARED_DMA_TIMER); /* DMA -> TIMx_RCR */
|
||||
furi_delay_us(5);
|
||||
LL_GPIO_ResetOutputPin(
|
||||
gpio_infrared_tx.port, gpio_infrared_tx.pin); /* when disable it prevents false pulse */
|
||||
@ -631,8 +645,8 @@ void furi_hal_infrared_async_tx_start(uint32_t freq, float duty_cycle) {
|
||||
&gpio_infrared_tx, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedHigh, GpioAltFn1TIM1);
|
||||
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_TIM_GenerateEvent_UPDATE(TIM1); /* TIMx_RCR -> Repetition counter */
|
||||
LL_TIM_EnableCounter(TIM1);
|
||||
LL_TIM_GenerateEvent_UPDATE(INFRARED_DMA_TIMER); /* TIMx_RCR -> Repetition counter */
|
||||
LL_TIM_EnableCounter(INFRARED_DMA_TIMER);
|
||||
FURI_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
#include <furi_hal_pwm.h>
|
||||
#include <core/check.h>
|
||||
#include <furi_hal_resources.h>
|
||||
#include <furi_hal_bus.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stm32wbxx_ll_tim.h>
|
||||
#include <stm32wbxx_ll_lptim.h>
|
||||
#include <stm32wbxx_ll_rcc.h>
|
||||
@ -29,9 +28,7 @@ void furi_hal_pwm_start(FuriHalPwmOutputId channel, uint32_t freq, uint8_t duty)
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn1TIM1);
|
||||
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_TIM_DeInit(TIM1);
|
||||
FURI_CRITICAL_EXIT();
|
||||
furi_hal_bus_enable(FuriHalBusTIM1);
|
||||
|
||||
LL_TIM_SetCounterMode(TIM1, LL_TIM_COUNTERMODE_UP);
|
||||
LL_TIM_SetRepetitionCounter(TIM1, 0);
|
||||
@ -58,9 +55,7 @@ void furi_hal_pwm_start(FuriHalPwmOutputId channel, uint32_t freq, uint8_t duty)
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn14LPTIM2);
|
||||
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_LPTIM_DeInit(LPTIM2);
|
||||
FURI_CRITICAL_EXIT();
|
||||
furi_hal_bus_enable(FuriHalBusLPTIM2);
|
||||
|
||||
LL_LPTIM_SetUpdateMode(LPTIM2, LL_LPTIM_UPDATE_MODE_ENDOFPERIOD);
|
||||
LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM2_CLKSOURCE_PCLK1);
|
||||
@ -80,14 +75,10 @@ void furi_hal_pwm_start(FuriHalPwmOutputId channel, uint32_t freq, uint8_t duty)
|
||||
void furi_hal_pwm_stop(FuriHalPwmOutputId channel) {
|
||||
if(channel == FuriHalPwmOutputIdTim1PA7) {
|
||||
furi_hal_gpio_init_simple(&gpio_ext_pa7, GpioModeAnalog);
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_TIM_DeInit(TIM1);
|
||||
FURI_CRITICAL_EXIT();
|
||||
furi_hal_bus_disable(FuriHalBusTIM1);
|
||||
} else if(channel == FuriHalPwmOutputIdLptim2PA4) {
|
||||
furi_hal_gpio_init_simple(&gpio_ext_pa4, GpioModeAnalog);
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_LPTIM_DeInit(LPTIM2);
|
||||
FURI_CRITICAL_EXIT();
|
||||
furi_hal_bus_disable(FuriHalBusLPTIM2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
#include <furi_hal_random.h>
|
||||
#include <furi_hal_bus.h>
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
#include <stm32wbxx_ll_rng.h>
|
||||
#include <stm32wbxx_ll_rcc.h>
|
||||
#include <stm32wbxx_ll_hsem.h>
|
||||
|
||||
#include <hw_conf.h>
|
||||
@ -32,6 +33,11 @@ static uint32_t furi_hal_random_read_rng() {
|
||||
return LL_RNG_ReadRandData32(RNG);
|
||||
}
|
||||
|
||||
void furi_hal_random_init() {
|
||||
furi_hal_bus_enable(FuriHalBusRNG);
|
||||
LL_RCC_SetRNGClockSource(LL_RCC_RNG_CLKSOURCE_CLK48);
|
||||
}
|
||||
|
||||
uint32_t furi_hal_random_get() {
|
||||
while(LL_HSEM_1StepLock(HSEM, CFG_HW_RNG_SEMID))
|
||||
;
|
||||
@ -40,6 +46,7 @@ uint32_t furi_hal_random_get() {
|
||||
const uint32_t random_val = furi_hal_random_read_rng();
|
||||
|
||||
LL_RNG_Disable(RNG);
|
||||
;
|
||||
LL_HSEM_ReleaseLock(HSEM, CFG_HW_RNG_SEMID, 0);
|
||||
|
||||
return random_val;
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
#include <furi_hal_resources.h>
|
||||
#include <furi_hal_bus.h>
|
||||
#include <furi.h>
|
||||
|
||||
#include <stm32wbxx_ll_rcc.h>
|
||||
@ -106,6 +107,13 @@ static void furi_hal_resources_init_input_pins(GpioMode mode) {
|
||||
}
|
||||
|
||||
void furi_hal_resources_init_early() {
|
||||
furi_hal_bus_enable(FuriHalBusGPIOA);
|
||||
furi_hal_bus_enable(FuriHalBusGPIOB);
|
||||
furi_hal_bus_enable(FuriHalBusGPIOC);
|
||||
furi_hal_bus_enable(FuriHalBusGPIOD);
|
||||
furi_hal_bus_enable(FuriHalBusGPIOE);
|
||||
furi_hal_bus_enable(FuriHalBusGPIOH);
|
||||
|
||||
furi_hal_resources_init_input_pins(GpioModeInput);
|
||||
|
||||
// SD Card stepdown control
|
||||
@ -150,6 +158,12 @@ void furi_hal_resources_init_early() {
|
||||
|
||||
void furi_hal_resources_deinit_early() {
|
||||
furi_hal_resources_init_input_pins(GpioModeAnalog);
|
||||
furi_hal_bus_disable(FuriHalBusGPIOA);
|
||||
furi_hal_bus_disable(FuriHalBusGPIOB);
|
||||
furi_hal_bus_disable(FuriHalBusGPIOC);
|
||||
furi_hal_bus_disable(FuriHalBusGPIOD);
|
||||
furi_hal_bus_disable(FuriHalBusGPIOE);
|
||||
furi_hal_bus_disable(FuriHalBusGPIOH);
|
||||
}
|
||||
|
||||
void furi_hal_resources_init() {
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#include <furi_hal_ibutton.h>
|
||||
#include <furi_hal_interrupt.h>
|
||||
#include <furi_hal_resources.h>
|
||||
#include <furi_hal_bus.h>
|
||||
#include <furi.h>
|
||||
|
||||
#include <stm32wbxx_ll_tim.h>
|
||||
@ -9,15 +10,18 @@
|
||||
#include <stm32wbxx_ll_dma.h>
|
||||
|
||||
#define FURI_HAL_RFID_READ_TIMER TIM1
|
||||
#define FURI_HAL_RFID_READ_TIMER_BUS FuriHalBusTIM1
|
||||
#define FURI_HAL_RFID_READ_TIMER_CHANNEL LL_TIM_CHANNEL_CH1N
|
||||
// We can't use N channel for LL_TIM_OC_Init, so...
|
||||
#define FURI_HAL_RFID_READ_TIMER_CHANNEL_CONFIG LL_TIM_CHANNEL_CH1
|
||||
|
||||
#define FURI_HAL_RFID_EMULATE_TIMER TIM2
|
||||
#define FURI_HAL_RFID_EMULATE_TIMER_BUS FuriHalBusTIM2
|
||||
#define FURI_HAL_RFID_EMULATE_TIMER_IRQ FuriHalInterruptIdTIM2
|
||||
#define FURI_HAL_RFID_EMULATE_TIMER_CHANNEL LL_TIM_CHANNEL_CH3
|
||||
|
||||
#define RFID_CAPTURE_TIM TIM2
|
||||
#define RFID_CAPTURE_TIM_BUS FuriHalBusTIM2
|
||||
#define RFID_CAPTURE_IND_CH LL_TIM_CHANNEL_CH3
|
||||
#define RFID_CAPTURE_DIR_CH LL_TIM_CHANNEL_CH4
|
||||
|
||||
@ -30,7 +34,6 @@
|
||||
#define RFID_DMA_CH2_DEF RFID_DMA, RFID_DMA_CH2_CHANNEL
|
||||
|
||||
typedef struct {
|
||||
FuriHalRfidEmulateCallback callback;
|
||||
FuriHalRfidDMACallback dma_callback;
|
||||
FuriHalRfidReadCaptureCallback read_capture_callback;
|
||||
void* context;
|
||||
@ -56,11 +59,7 @@ void furi_hal_rfid_init() {
|
||||
COMP_InitStruct.InputPlus = LL_COMP_INPUT_PLUS_IO1;
|
||||
COMP_InitStruct.InputMinus = LL_COMP_INPUT_MINUS_1_2VREFINT;
|
||||
COMP_InitStruct.InputHysteresis = LL_COMP_HYSTERESIS_HIGH;
|
||||
#ifdef INVERT_RFID_IN
|
||||
COMP_InitStruct.OutputPolarity = LL_COMP_OUTPUTPOL_INVERTED;
|
||||
#else
|
||||
COMP_InitStruct.OutputPolarity = LL_COMP_OUTPUTPOL_NONINVERTED;
|
||||
#endif
|
||||
COMP_InitStruct.OutputBlankingSource = LL_COMP_BLANKINGSRC_NONE;
|
||||
LL_COMP_Init(COMP1, &COMP_InitStruct);
|
||||
LL_COMP_SetCommonWindowMode(__LL_COMP_COMMON_INSTANCE(COMP1), LL_COMP_WINDOWMODE_DISABLE);
|
||||
@ -92,7 +91,7 @@ void furi_hal_rfid_pins_reset() {
|
||||
furi_hal_gpio_init(&gpio_rfid_data_in, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
}
|
||||
|
||||
void furi_hal_rfid_pins_emulate() {
|
||||
static void furi_hal_rfid_pins_emulate() {
|
||||
// ibutton low
|
||||
furi_hal_ibutton_pin_configure();
|
||||
furi_hal_ibutton_pin_write(false);
|
||||
@ -113,7 +112,7 @@ void furi_hal_rfid_pins_emulate() {
|
||||
&gpio_rfid_carrier, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedLow, GpioAltFn2TIM2);
|
||||
}
|
||||
|
||||
void furi_hal_rfid_pins_read() {
|
||||
static void furi_hal_rfid_pins_read() {
|
||||
// ibutton low
|
||||
furi_hal_ibutton_pin_configure();
|
||||
furi_hal_ibutton_pin_write(false);
|
||||
@ -142,10 +141,10 @@ void furi_hal_rfid_pin_pull_pulldown() {
|
||||
furi_hal_gpio_write(&gpio_nfc_irq_rfid_pull, false);
|
||||
}
|
||||
|
||||
void furi_hal_rfid_tim_read(float freq, float duty_cycle) {
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_TIM_DeInit(FURI_HAL_RFID_READ_TIMER);
|
||||
FURI_CRITICAL_EXIT();
|
||||
void furi_hal_rfid_tim_read_start(float freq, float duty_cycle) {
|
||||
furi_hal_bus_enable(FURI_HAL_RFID_READ_TIMER_BUS);
|
||||
|
||||
furi_hal_rfid_pins_read();
|
||||
|
||||
LL_TIM_InitTypeDef TIM_InitStruct = {0};
|
||||
TIM_InitStruct.Autoreload = (SystemCoreClock / freq) - 1;
|
||||
@ -160,23 +159,23 @@ void furi_hal_rfid_tim_read(float freq, float duty_cycle) {
|
||||
FURI_HAL_RFID_READ_TIMER, FURI_HAL_RFID_READ_TIMER_CHANNEL_CONFIG, &TIM_OC_InitStruct);
|
||||
|
||||
LL_TIM_EnableCounter(FURI_HAL_RFID_READ_TIMER);
|
||||
|
||||
furi_hal_rfid_tim_read_continue();
|
||||
}
|
||||
|
||||
void furi_hal_rfid_tim_read_start() {
|
||||
void furi_hal_rfid_tim_read_continue() {
|
||||
LL_TIM_EnableAllOutputs(FURI_HAL_RFID_READ_TIMER);
|
||||
}
|
||||
|
||||
void furi_hal_rfid_tim_read_stop() {
|
||||
void furi_hal_rfid_tim_read_pause() {
|
||||
LL_TIM_DisableAllOutputs(FURI_HAL_RFID_READ_TIMER);
|
||||
}
|
||||
|
||||
void furi_hal_rfid_tim_emulate(float freq) {
|
||||
UNUSED(freq); // FIXME
|
||||
// basic PWM setup with needed freq and internal clock
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_TIM_DeInit(FURI_HAL_RFID_EMULATE_TIMER);
|
||||
FURI_CRITICAL_EXIT();
|
||||
void furi_hal_rfid_tim_read_stop() {
|
||||
furi_hal_bus_disable(FURI_HAL_RFID_READ_TIMER_BUS);
|
||||
}
|
||||
|
||||
static void furi_hal_rfid_tim_emulate() {
|
||||
LL_TIM_SetPrescaler(FURI_HAL_RFID_EMULATE_TIMER, 0);
|
||||
LL_TIM_SetCounterMode(FURI_HAL_RFID_EMULATE_TIMER, LL_TIM_COUNTERMODE_UP);
|
||||
LL_TIM_SetAutoReload(FURI_HAL_RFID_EMULATE_TIMER, 1);
|
||||
@ -201,32 +200,6 @@ void furi_hal_rfid_tim_emulate(float freq) {
|
||||
LL_TIM_GenerateEvent_UPDATE(FURI_HAL_RFID_EMULATE_TIMER);
|
||||
}
|
||||
|
||||
static void furi_hal_rfid_emulate_isr() {
|
||||
if(LL_TIM_IsActiveFlag_UPDATE(FURI_HAL_RFID_EMULATE_TIMER)) {
|
||||
LL_TIM_ClearFlag_UPDATE(FURI_HAL_RFID_EMULATE_TIMER);
|
||||
furi_hal_rfid->callback(furi_hal_rfid->context);
|
||||
}
|
||||
}
|
||||
|
||||
void furi_hal_rfid_tim_emulate_start(FuriHalRfidEmulateCallback callback, void* context) {
|
||||
furi_assert(furi_hal_rfid);
|
||||
|
||||
furi_hal_rfid->callback = callback;
|
||||
furi_hal_rfid->context = context;
|
||||
|
||||
furi_hal_interrupt_set_isr(FURI_HAL_RFID_EMULATE_TIMER_IRQ, furi_hal_rfid_emulate_isr, NULL);
|
||||
|
||||
LL_TIM_EnableIT_UPDATE(FURI_HAL_RFID_EMULATE_TIMER);
|
||||
LL_TIM_EnableAllOutputs(FURI_HAL_RFID_EMULATE_TIMER);
|
||||
LL_TIM_EnableCounter(FURI_HAL_RFID_EMULATE_TIMER);
|
||||
}
|
||||
|
||||
void furi_hal_rfid_tim_emulate_stop() {
|
||||
LL_TIM_DisableCounter(FURI_HAL_RFID_EMULATE_TIMER);
|
||||
LL_TIM_DisableAllOutputs(FURI_HAL_RFID_EMULATE_TIMER);
|
||||
furi_hal_interrupt_set_isr(FURI_HAL_RFID_EMULATE_TIMER_IRQ, NULL, NULL);
|
||||
}
|
||||
|
||||
static void furi_hal_capture_dma_isr(void* context) {
|
||||
UNUSED(context);
|
||||
|
||||
@ -247,15 +220,13 @@ static void furi_hal_capture_dma_isr(void* context) {
|
||||
}
|
||||
|
||||
void furi_hal_rfid_tim_read_capture_start(FuriHalRfidReadCaptureCallback callback, void* context) {
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_TIM_DeInit(RFID_CAPTURE_TIM);
|
||||
FURI_CRITICAL_EXIT();
|
||||
|
||||
furi_assert(furi_hal_rfid);
|
||||
|
||||
furi_hal_rfid->read_capture_callback = callback;
|
||||
furi_hal_rfid->context = context;
|
||||
|
||||
furi_hal_bus_enable(RFID_CAPTURE_TIM_BUS);
|
||||
|
||||
// Timer: base
|
||||
LL_TIM_InitTypeDef TIM_InitStruct = {0};
|
||||
TIM_InitStruct.Prescaler = 64 - 1;
|
||||
@ -303,10 +274,7 @@ void furi_hal_rfid_tim_read_capture_stop() {
|
||||
furi_hal_rfid_comp_stop();
|
||||
|
||||
furi_hal_interrupt_set_isr(FURI_HAL_RFID_EMULATE_TIMER_IRQ, NULL, NULL);
|
||||
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_TIM_DeInit(RFID_CAPTURE_TIM);
|
||||
FURI_CRITICAL_EXIT();
|
||||
furi_hal_bus_disable(RFID_CAPTURE_TIM_BUS);
|
||||
}
|
||||
|
||||
static void furi_hal_rfid_dma_isr() {
|
||||
@ -341,7 +309,8 @@ void furi_hal_rfid_tim_emulate_dma_start(
|
||||
furi_hal_rfid_pins_emulate();
|
||||
|
||||
// configure timer
|
||||
furi_hal_rfid_tim_emulate(125000);
|
||||
furi_hal_bus_enable(FURI_HAL_RFID_EMULATE_TIMER_BUS);
|
||||
furi_hal_rfid_tim_emulate();
|
||||
LL_TIM_OC_SetPolarity(
|
||||
FURI_HAL_RFID_EMULATE_TIMER, FURI_HAL_RFID_EMULATE_TIMER_CHANNEL, LL_TIM_OCPOLARITY_HIGH);
|
||||
LL_TIM_EnableDMAReq_UPDATE(FURI_HAL_RFID_EMULATE_TIMER);
|
||||
@ -405,32 +374,12 @@ void furi_hal_rfid_tim_emulate_dma_stop() {
|
||||
|
||||
LL_DMA_DeInit(RFID_DMA_CH1_DEF);
|
||||
LL_DMA_DeInit(RFID_DMA_CH2_DEF);
|
||||
LL_TIM_DeInit(FURI_HAL_RFID_EMULATE_TIMER);
|
||||
|
||||
furi_hal_bus_disable(FURI_HAL_RFID_EMULATE_TIMER_BUS);
|
||||
|
||||
FURI_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
void furi_hal_rfid_tim_reset() {
|
||||
FURI_CRITICAL_ENTER();
|
||||
|
||||
LL_TIM_DeInit(FURI_HAL_RFID_READ_TIMER);
|
||||
LL_TIM_DeInit(FURI_HAL_RFID_EMULATE_TIMER);
|
||||
|
||||
FURI_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
void furi_hal_rfid_set_emulate_period(uint32_t period) {
|
||||
LL_TIM_SetAutoReload(FURI_HAL_RFID_EMULATE_TIMER, period);
|
||||
}
|
||||
|
||||
void furi_hal_rfid_set_emulate_pulse(uint32_t pulse) {
|
||||
#if FURI_HAL_RFID_EMULATE_TIMER_CHANNEL == LL_TIM_CHANNEL_CH3
|
||||
LL_TIM_OC_SetCompareCH3(FURI_HAL_RFID_EMULATE_TIMER, pulse);
|
||||
#else
|
||||
#error Update this code. Would you kindly?
|
||||
#endif
|
||||
}
|
||||
|
||||
void furi_hal_rfid_set_read_period(uint32_t period) {
|
||||
LL_TIM_SetAutoReload(FURI_HAL_RFID_READ_TIMER, period);
|
||||
}
|
||||
@ -443,12 +392,6 @@ void furi_hal_rfid_set_read_pulse(uint32_t pulse) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void furi_hal_rfid_change_read_config(float freq, float duty_cycle) {
|
||||
uint32_t period = (uint32_t)((SystemCoreClock) / freq) - 1;
|
||||
furi_hal_rfid_set_read_period(period);
|
||||
furi_hal_rfid_set_read_pulse(period * duty_cycle);
|
||||
}
|
||||
|
||||
void furi_hal_rfid_comp_start() {
|
||||
LL_COMP_Enable(COMP1);
|
||||
// Magic
|
||||
|
||||
@ -21,14 +21,6 @@ void furi_hal_rfid_init();
|
||||
*/
|
||||
void furi_hal_rfid_pins_reset();
|
||||
|
||||
/** Config rfid pins to emulate state
|
||||
*/
|
||||
void furi_hal_rfid_pins_emulate();
|
||||
|
||||
/** Config rfid pins to read state
|
||||
*/
|
||||
void furi_hal_rfid_pins_read();
|
||||
|
||||
/** Release rfid pull pin
|
||||
*/
|
||||
void furi_hal_rfid_pin_pull_release();
|
||||
@ -37,33 +29,24 @@ void furi_hal_rfid_pin_pull_release();
|
||||
*/
|
||||
void furi_hal_rfid_pin_pull_pulldown();
|
||||
|
||||
/** Config rfid timer to read state
|
||||
*
|
||||
/** Start read timer
|
||||
* @param freq timer frequency
|
||||
* @param duty_cycle timer duty cycle, 0.0-1.0
|
||||
*/
|
||||
void furi_hal_rfid_tim_read(float freq, float duty_cycle);
|
||||
void furi_hal_rfid_tim_read_start(float freq, float duty_cycle);
|
||||
|
||||
/** Start read timer
|
||||
/** Pause read timer, to be able to continue later
|
||||
*/
|
||||
void furi_hal_rfid_tim_read_start();
|
||||
void furi_hal_rfid_tim_read_pause();
|
||||
|
||||
/** Continue read timer
|
||||
*/
|
||||
void furi_hal_rfid_tim_read_continue();
|
||||
|
||||
/** Stop read timer
|
||||
*/
|
||||
void furi_hal_rfid_tim_read_stop();
|
||||
|
||||
/** Config rfid timer to emulate state
|
||||
*
|
||||
* @param freq timer frequency
|
||||
*/
|
||||
void furi_hal_rfid_tim_emulate(float freq);
|
||||
|
||||
typedef void (*FuriHalRfidEmulateCallback)(void* context);
|
||||
|
||||
/** Start emulation timer
|
||||
*/
|
||||
void furi_hal_rfid_tim_emulate_start(FuriHalRfidEmulateCallback callback, void* context);
|
||||
|
||||
typedef void (*FuriHalRfidReadCaptureCallback)(bool level, uint32_t duration, void* context);
|
||||
|
||||
void furi_hal_rfid_tim_read_capture_start(FuriHalRfidReadCaptureCallback callback, void* context);
|
||||
@ -81,26 +64,6 @@ void furi_hal_rfid_tim_emulate_dma_start(
|
||||
|
||||
void furi_hal_rfid_tim_emulate_dma_stop();
|
||||
|
||||
/** Stop emulation timer
|
||||
*/
|
||||
void furi_hal_rfid_tim_emulate_stop();
|
||||
|
||||
/** Config rfid timers to reset state
|
||||
*/
|
||||
void furi_hal_rfid_tim_reset();
|
||||
|
||||
/** Set emulation timer period
|
||||
*
|
||||
* @param period overall duration
|
||||
*/
|
||||
void furi_hal_rfid_set_emulate_period(uint32_t period);
|
||||
|
||||
/** Set emulation timer pulse
|
||||
*
|
||||
* @param pulse duration of high level
|
||||
*/
|
||||
void furi_hal_rfid_set_emulate_pulse(uint32_t pulse);
|
||||
|
||||
/** Set read timer period
|
||||
*
|
||||
* @param period overall duration
|
||||
@ -113,13 +76,6 @@ void furi_hal_rfid_set_read_period(uint32_t period);
|
||||
*/
|
||||
void furi_hal_rfid_set_read_pulse(uint32_t pulse);
|
||||
|
||||
/** Сhanges the configuration of the RFID timer "on a fly"
|
||||
*
|
||||
* @param freq new frequency
|
||||
* @param duty_cycle new duty cycle
|
||||
*/
|
||||
void furi_hal_rfid_change_read_config(float freq, float duty_cycle);
|
||||
|
||||
/** Start/Enable comparator */
|
||||
void furi_hal_rfid_comp_start();
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@
|
||||
#include <furi_hal_light.h>
|
||||
#include <furi_hal_debug.h>
|
||||
|
||||
#include <stm32wbxx_ll_bus.h>
|
||||
#include <stm32wbxx_ll_pwr.h>
|
||||
#include <stm32wbxx_ll_bus.h>
|
||||
#include <stm32wbxx_ll_rcc.h>
|
||||
#include <stm32wbxx_ll_rtc.h>
|
||||
#include <stm32wbxx_ll_utils.h>
|
||||
@ -44,10 +44,8 @@ _Static_assert(sizeof(SystemReg) == 4, "SystemReg size mismatch");
|
||||
#define FURI_HAL_RTC_SECONDS_PER_DAY (FURI_HAL_RTC_SECONDS_PER_HOUR * 24)
|
||||
#define FURI_HAL_RTC_MONTHS_COUNT 12
|
||||
#define FURI_HAL_RTC_EPOCH_START_YEAR 1970
|
||||
#define FURI_HAL_RTC_IS_LEAP_YEAR(year) \
|
||||
((((year) % 4 == 0) && ((year) % 100 != 0)) || ((year) % 400 == 0))
|
||||
|
||||
static const uint8_t furi_hal_rtc_days_per_month[][FURI_HAL_RTC_MONTHS_COUNT] = {
|
||||
static const uint8_t furi_hal_rtc_days_per_month[2][FURI_HAL_RTC_MONTHS_COUNT] = {
|
||||
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
|
||||
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
|
||||
|
||||
@ -395,7 +393,7 @@ uint32_t furi_hal_rtc_datetime_to_timestamp(FuriHalRtcDateTime* datetime) {
|
||||
uint8_t leap_years = 0;
|
||||
|
||||
for(uint16_t y = FURI_HAL_RTC_EPOCH_START_YEAR; y < datetime->year; y++) {
|
||||
if(FURI_HAL_RTC_IS_LEAP_YEAR(y)) {
|
||||
if(furi_hal_rtc_is_leap_year(y)) {
|
||||
leap_years++;
|
||||
} else {
|
||||
years++;
|
||||
@ -406,10 +404,10 @@ uint32_t furi_hal_rtc_datetime_to_timestamp(FuriHalRtcDateTime* datetime) {
|
||||
((years * furi_hal_rtc_days_per_year[0]) + (leap_years * furi_hal_rtc_days_per_year[1])) *
|
||||
FURI_HAL_RTC_SECONDS_PER_DAY;
|
||||
|
||||
uint8_t year_index = (FURI_HAL_RTC_IS_LEAP_YEAR(datetime->year)) ? 1 : 0;
|
||||
bool leap_year = furi_hal_rtc_is_leap_year(datetime->year);
|
||||
|
||||
for(uint8_t m = 0; m < (datetime->month - 1); m++) {
|
||||
timestamp += furi_hal_rtc_days_per_month[year_index][m] * FURI_HAL_RTC_SECONDS_PER_DAY;
|
||||
for(uint8_t m = 1; m < datetime->month; m++) {
|
||||
timestamp += furi_hal_rtc_get_days_per_month(leap_year, m) * FURI_HAL_RTC_SECONDS_PER_DAY;
|
||||
}
|
||||
|
||||
timestamp += (datetime->day - 1) * FURI_HAL_RTC_SECONDS_PER_DAY;
|
||||
@ -419,3 +417,15 @@ uint32_t furi_hal_rtc_datetime_to_timestamp(FuriHalRtcDateTime* datetime) {
|
||||
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
uint16_t furi_hal_rtc_get_days_per_year(uint16_t year) {
|
||||
return furi_hal_rtc_days_per_year[furi_hal_rtc_is_leap_year(year) ? 1 : 0];
|
||||
}
|
||||
|
||||
bool furi_hal_rtc_is_leap_year(uint16_t year) {
|
||||
return (((year) % 4 == 0) && ((year) % 100 != 0)) || ((year) % 400 == 0);
|
||||
}
|
||||
|
||||
uint8_t furi_hal_rtc_get_days_per_month(bool leap_year, uint8_t month) {
|
||||
return furi_hal_rtc_days_per_month[leap_year ? 1 : 0][month - 1];
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#include <furi_hal_gpio.h>
|
||||
#include <furi_hal_resources.h>
|
||||
#include <furi_hal_power.h>
|
||||
#include <furi_hal_bus.h>
|
||||
|
||||
#include <stm32wbxx_ll_tim.h>
|
||||
#include <furi_hal_cortex.h>
|
||||
@ -20,16 +21,11 @@ static FuriMutex* furi_hal_speaker_mutex = NULL;
|
||||
void furi_hal_speaker_init() {
|
||||
furi_assert(furi_hal_speaker_mutex == NULL);
|
||||
furi_hal_speaker_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_TIM_DeInit(FURI_HAL_SPEAKER_TIMER);
|
||||
FURI_CRITICAL_EXIT();
|
||||
FURI_LOG_I(TAG, "Init OK");
|
||||
}
|
||||
|
||||
void furi_hal_speaker_deinit() {
|
||||
furi_check(furi_hal_speaker_mutex != NULL);
|
||||
LL_TIM_DeInit(FURI_HAL_SPEAKER_TIMER);
|
||||
furi_hal_gpio_init(&gpio_speaker, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
furi_mutex_free(furi_hal_speaker_mutex);
|
||||
furi_hal_speaker_mutex = NULL;
|
||||
}
|
||||
@ -39,6 +35,7 @@ bool furi_hal_speaker_acquire(uint32_t timeout) {
|
||||
|
||||
if(furi_mutex_acquire(furi_hal_speaker_mutex, timeout) == FuriStatusOk) {
|
||||
furi_hal_power_insomnia_enter();
|
||||
furi_hal_bus_enable(FuriHalBusTIM16);
|
||||
furi_hal_gpio_init_ex(
|
||||
&gpio_speaker, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedLow, GpioAltFn14TIM16);
|
||||
return true;
|
||||
@ -53,6 +50,8 @@ void furi_hal_speaker_release() {
|
||||
|
||||
furi_hal_speaker_stop();
|
||||
furi_hal_gpio_init(&gpio_speaker, GpioModeAnalog, GpioPullDown, GpioSpeedLow);
|
||||
|
||||
furi_hal_bus_disable(FuriHalBusTIM16);
|
||||
furi_hal_power_insomnia_exit();
|
||||
|
||||
furi_check(furi_mutex_release(furi_hal_speaker_mutex) == FuriStatusOk);
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#include <furi_hal_spi_config.h>
|
||||
#include <furi_hal_resources.h>
|
||||
#include <furi_hal_spi.h>
|
||||
#include <furi_hal_bus.h>
|
||||
#include <furi.h>
|
||||
|
||||
#define TAG "FuriHalSpiConfig"
|
||||
@ -100,28 +101,17 @@ void furi_hal_spi_config_init() {
|
||||
static void furi_hal_spi_bus_r_event_callback(FuriHalSpiBus* bus, FuriHalSpiBusEvent event) {
|
||||
if(event == FuriHalSpiBusEventInit) {
|
||||
furi_hal_spi_bus_r_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1);
|
||||
FURI_CRITICAL_EXIT();
|
||||
bus->current_handle = NULL;
|
||||
} else if(event == FuriHalSpiBusEventDeinit) {
|
||||
furi_mutex_free(furi_hal_spi_bus_r_mutex);
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1);
|
||||
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI1);
|
||||
FURI_CRITICAL_EXIT();
|
||||
} else if(event == FuriHalSpiBusEventLock) {
|
||||
furi_check(furi_mutex_acquire(furi_hal_spi_bus_r_mutex, FuriWaitForever) == FuriStatusOk);
|
||||
} else if(event == FuriHalSpiBusEventUnlock) {
|
||||
furi_check(furi_mutex_release(furi_hal_spi_bus_r_mutex) == FuriStatusOk);
|
||||
} else if(event == FuriHalSpiBusEventActivate) {
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI1);
|
||||
FURI_CRITICAL_EXIT();
|
||||
furi_hal_bus_enable(FuriHalBusSPI1);
|
||||
} else if(event == FuriHalSpiBusEventDeactivate) {
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1);
|
||||
FURI_CRITICAL_EXIT();
|
||||
furi_hal_bus_disable(FuriHalBusSPI1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -135,28 +125,17 @@ FuriMutex* furi_hal_spi_bus_d_mutex = NULL;
|
||||
static void furi_hal_spi_bus_d_event_callback(FuriHalSpiBus* bus, FuriHalSpiBusEvent event) {
|
||||
if(event == FuriHalSpiBusEventInit) {
|
||||
furi_hal_spi_bus_d_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2);
|
||||
FURI_CRITICAL_EXIT();
|
||||
bus->current_handle = NULL;
|
||||
} else if(event == FuriHalSpiBusEventDeinit) {
|
||||
furi_mutex_free(furi_hal_spi_bus_d_mutex);
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2);
|
||||
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI2);
|
||||
FURI_CRITICAL_EXIT();
|
||||
} else if(event == FuriHalSpiBusEventLock) {
|
||||
furi_check(furi_mutex_acquire(furi_hal_spi_bus_d_mutex, FuriWaitForever) == FuriStatusOk);
|
||||
} else if(event == FuriHalSpiBusEventUnlock) {
|
||||
furi_check(furi_mutex_release(furi_hal_spi_bus_d_mutex) == FuriStatusOk);
|
||||
} else if(event == FuriHalSpiBusEventActivate) {
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI2);
|
||||
FURI_CRITICAL_EXIT();
|
||||
furi_hal_bus_enable(FuriHalBusSPI2);
|
||||
} else if(event == FuriHalSpiBusEventDeactivate) {
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2);
|
||||
FURI_CRITICAL_EXIT();
|
||||
furi_hal_bus_disable(FuriHalBusSPI2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -6,8 +6,6 @@
|
||||
#include <furi_hal_gpio.h>
|
||||
|
||||
#include <stm32wbxx_ll_spi.h>
|
||||
#include <stm32wbxx_ll_rcc.h>
|
||||
#include <stm32wbxx_ll_bus.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#include <furi_hal_spi.h>
|
||||
#include <furi_hal_interrupt.h>
|
||||
#include <furi_hal_resources.h>
|
||||
#include <furi_hal_bus.h>
|
||||
|
||||
#include <stm32wbxx_ll_dma.h>
|
||||
|
||||
@ -433,6 +434,8 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void*
|
||||
furi_hal_gpio_init_ex(
|
||||
&gpio_cc1101_g0, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedLow, GpioAltFn1TIM2);
|
||||
|
||||
furi_hal_bus_enable(FuriHalBusTIM2);
|
||||
|
||||
// Timer: base
|
||||
LL_TIM_InitTypeDef TIM_InitStruct = {0};
|
||||
TIM_InitStruct.Prescaler = 64 - 1;
|
||||
@ -496,7 +499,7 @@ void furi_hal_subghz_stop_async_rx() {
|
||||
furi_hal_subghz_idle();
|
||||
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_TIM_DeInit(TIM2);
|
||||
furi_hal_bus_disable(FuriHalBusTIM2);
|
||||
|
||||
// Stop debug
|
||||
furi_hal_subghz_stop_debug();
|
||||
@ -658,6 +661,8 @@ bool furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void*
|
||||
LL_DMA_EnableIT_HT(SUBGHZ_DMA_CH1_DEF);
|
||||
LL_DMA_EnableChannel(SUBGHZ_DMA_CH1_DEF);
|
||||
|
||||
furi_hal_bus_enable(FuriHalBusTIM2);
|
||||
|
||||
// Configure TIM2
|
||||
LL_TIM_InitTypeDef TIM_InitStruct = {0};
|
||||
TIM_InitStruct.Prescaler = 64 - 1;
|
||||
@ -740,7 +745,7 @@ void furi_hal_subghz_stop_async_tx() {
|
||||
|
||||
// Deinitialize Timer
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_TIM_DeInit(TIM2);
|
||||
furi_hal_bus_disable(FuriHalBusTIM2);
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, NULL, NULL);
|
||||
|
||||
// Deinitialize DMA
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
#include <stm32wbxx_ll_usart.h>
|
||||
#include <stm32wbxx_ll_rcc.h>
|
||||
#include <furi_hal_resources.h>
|
||||
#include <furi_hal_bus.h>
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
@ -13,6 +14,9 @@ static void (*irq_cb[2])(uint8_t ev, uint8_t data, void* context);
|
||||
static void* irq_ctx[2];
|
||||
|
||||
static void furi_hal_usart_init(uint32_t baud) {
|
||||
furi_hal_bus_enable(FuriHalBusUSART1);
|
||||
LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2);
|
||||
|
||||
furi_hal_gpio_init_ex(
|
||||
&gpio_usart_tx,
|
||||
GpioModeAltFunctionPushPull,
|
||||
@ -50,6 +54,9 @@ static void furi_hal_usart_init(uint32_t baud) {
|
||||
}
|
||||
|
||||
static void furi_hal_lpuart_init(uint32_t baud) {
|
||||
furi_hal_bus_enable(FuriHalBusLPUART1);
|
||||
LL_RCC_SetLPUARTClockSource(LL_RCC_LPUART1_CLKSOURCE_PCLK1);
|
||||
|
||||
furi_hal_gpio_init_ex(
|
||||
&gpio_ext_pc0,
|
||||
GpioModeAltFunctionPushPull,
|
||||
@ -86,10 +93,11 @@ static void furi_hal_lpuart_init(uint32_t baud) {
|
||||
}
|
||||
|
||||
void furi_hal_uart_init(FuriHalUartId ch, uint32_t baud) {
|
||||
if(ch == FuriHalUartIdLPUART1)
|
||||
if(ch == FuriHalUartIdLPUART1) {
|
||||
furi_hal_lpuart_init(baud);
|
||||
else if(ch == FuriHalUartIdUSART1)
|
||||
} else if(ch == FuriHalUartIdUSART1) {
|
||||
furi_hal_usart_init(baud);
|
||||
}
|
||||
}
|
||||
|
||||
void furi_hal_uart_set_br(FuriHalUartId ch, uint32_t baud) {
|
||||
@ -126,11 +134,15 @@ void furi_hal_uart_set_br(FuriHalUartId ch, uint32_t baud) {
|
||||
void furi_hal_uart_deinit(FuriHalUartId ch) {
|
||||
furi_hal_uart_set_irq_cb(ch, NULL, NULL);
|
||||
if(ch == FuriHalUartIdUSART1) {
|
||||
LL_USART_Disable(USART1);
|
||||
if(furi_hal_bus_is_enabled(FuriHalBusUSART1)) {
|
||||
furi_hal_bus_disable(FuriHalBusUSART1);
|
||||
}
|
||||
furi_hal_gpio_init(&gpio_usart_tx, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_init(&gpio_usart_rx, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
} else if(ch == FuriHalUartIdLPUART1) {
|
||||
LL_LPUART_Disable(LPUART1);
|
||||
if(furi_hal_bus_is_enabled(FuriHalBusLPUART1)) {
|
||||
furi_hal_bus_disable(FuriHalBusLPUART1);
|
||||
}
|
||||
furi_hal_gpio_init(&gpio_ext_pc0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_init(&gpio_ext_pc1, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
}
|
||||
|
||||
@ -2,7 +2,9 @@
|
||||
#include <furi_hal_usb_i.h>
|
||||
#include <furi_hal_usb.h>
|
||||
#include <furi_hal_power.h>
|
||||
|
||||
#include <stm32wbxx_ll_pwr.h>
|
||||
#include <stm32wbxx_ll_rcc.h>
|
||||
#include <furi.h>
|
||||
#include <toolbox/api_lock.h>
|
||||
|
||||
@ -86,6 +88,8 @@ static void wkup_evt(usbd_device* dev, uint8_t event, uint8_t ep);
|
||||
|
||||
/* Low-level init */
|
||||
void furi_hal_usb_init(void) {
|
||||
LL_RCC_SetUSBClockSource(LL_RCC_USB_CLKSOURCE_PLLSAI1);
|
||||
|
||||
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||
LL_PWR_EnableVddUSB();
|
||||
|
||||
@ -98,7 +102,10 @@ void furi_hal_usb_init(void) {
|
||||
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||
|
||||
usbd_init(&udev, &usbd_hw, USB_EP0_SIZE, ubuf, sizeof(ubuf));
|
||||
|
||||
FURI_CRITICAL_ENTER();
|
||||
usbd_enable(&udev, true);
|
||||
FURI_CRITICAL_EXIT();
|
||||
|
||||
usbd_reg_descr(&udev, usb_descriptor_get);
|
||||
usbd_reg_event(&udev, usbd_evt_susp, susp_evt);
|
||||
@ -359,8 +366,10 @@ static void usb_process_mode_reinit() {
|
||||
usbd_connect(&udev, false);
|
||||
usb.enabled = false;
|
||||
|
||||
FURI_CRITICAL_ENTER();
|
||||
usbd_enable(&udev, false);
|
||||
usbd_enable(&udev, true);
|
||||
FURI_CRITICAL_EXIT();
|
||||
|
||||
furi_delay_ms(USB_RECONNECT_DELAY);
|
||||
usb_process_mode_start(usb.interface, usb.interface_context);
|
||||
|
||||
@ -436,7 +436,11 @@ static bool hid_send_report(uint8_t report_id) {
|
||||
if((hid_semaphore == NULL) || (hid_connected == false)) return false;
|
||||
if((boot_protocol == true) && (report_id != ReportIdKeyboard)) return false;
|
||||
|
||||
furi_check(furi_semaphore_acquire(hid_semaphore, FuriWaitForever) == FuriStatusOk);
|
||||
FuriStatus status = furi_semaphore_acquire(hid_semaphore, HID_INTERVAL * 2);
|
||||
if(status == FuriStatusErrorTimeout) {
|
||||
return false;
|
||||
}
|
||||
furi_check(status == FuriStatusOk);
|
||||
if(hid_connected == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -38,6 +38,12 @@ static bool flipper_update_mount_sd() {
|
||||
}
|
||||
|
||||
static bool flipper_update_init() {
|
||||
// TODO: Configure missing peripherals properly
|
||||
furi_hal_bus_enable(FuriHalBusHSEM);
|
||||
furi_hal_bus_enable(FuriHalBusIPCC);
|
||||
furi_hal_bus_enable(FuriHalBusRNG);
|
||||
furi_hal_bus_enable(FuriHalBusUSART1);
|
||||
|
||||
furi_hal_clock_init();
|
||||
furi_hal_rtc_init();
|
||||
furi_hal_interrupt_init();
|
||||
|
||||
@ -12,9 +12,11 @@ struct STOP_EXTERNING_ME {};
|
||||
|
||||
#include <furi_hal_cortex.h>
|
||||
#include <furi_hal_clock.h>
|
||||
#include <furi_hal_bus.h>
|
||||
#include <furi_hal_crypto.h>
|
||||
#include <furi_hal_console.h>
|
||||
#include <furi_hal_debug.h>
|
||||
#include <furi_hal_dma.h>
|
||||
#include <furi_hal_os.h>
|
||||
#include <furi_hal_sd.h>
|
||||
#include <furi_hal_i2c.h>
|
||||
|
||||
@ -6,6 +6,9 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Initialize random subsystem */
|
||||
void furi_hal_random_init();
|
||||
|
||||
/** Get random value
|
||||
*
|
||||
* @return random value
|
||||
|
||||
@ -255,6 +255,30 @@ uint32_t furi_hal_rtc_get_timestamp();
|
||||
*/
|
||||
uint32_t furi_hal_rtc_datetime_to_timestamp(FuriHalRtcDateTime* datetime);
|
||||
|
||||
/** Gets the number of days in the year according to the Gregorian calendar.
|
||||
*
|
||||
* @param year Input year.
|
||||
*
|
||||
* @return number of days in `year`.
|
||||
*/
|
||||
uint16_t furi_hal_rtc_get_days_per_year(uint16_t year);
|
||||
|
||||
/** Check if a year a leap year in the Gregorian calendar.
|
||||
*
|
||||
* @param year Input year.
|
||||
*
|
||||
* @return true if `year` is a leap year.
|
||||
*/
|
||||
bool furi_hal_rtc_is_leap_year(uint16_t year);
|
||||
|
||||
/** Get the number of days in the month.
|
||||
*
|
||||
* @param leap_year true to calculate based on leap years
|
||||
* @param month month to check, where 1 = January
|
||||
* @return the number of days in the month
|
||||
*/
|
||||
uint8_t furi_hal_rtc_get_days_per_month(bool leap_year, uint8_t month);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -78,6 +78,11 @@ extern "C" {
|
||||
#define TOSTRING(x) STRINGIFY(x)
|
||||
#endif
|
||||
|
||||
#ifndef CONCATENATE
|
||||
#define CONCATENATE(a, b) CONCATENATE_(a, b)
|
||||
#define CONCATENATE_(a, b) a##b
|
||||
#endif
|
||||
|
||||
#ifndef REVERSE_BYTES_U32
|
||||
#define REVERSE_BYTES_U32(x) \
|
||||
((((x)&0x000000FF) << 24) | (((x)&0x0000FF00) << 8) | (((x)&0x00FF0000) >> 8) | \
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user