Merge remote-tracking branch 'OFW/dev' into dev
@@ -265,6 +265,7 @@ static bool test_write(const char* file_name) {
|
|||||||
if(!flipper_format_file_open_always(file, file_name)) break;
|
if(!flipper_format_file_open_always(file, file_name)) break;
|
||||||
if(!flipper_format_write_header_cstr(file, test_filetype, test_version)) break;
|
if(!flipper_format_write_header_cstr(file, test_filetype, test_version)) break;
|
||||||
if(!flipper_format_write_comment_cstr(file, "This is comment")) break;
|
if(!flipper_format_write_comment_cstr(file, "This is comment")) break;
|
||||||
|
if(!flipper_format_write_empty_line(file)) break;
|
||||||
if(!flipper_format_write_string_cstr(file, test_string_key, test_string_data)) break;
|
if(!flipper_format_write_string_cstr(file, test_string_key, test_string_data)) break;
|
||||||
if(!flipper_format_write_int32(file, test_int_key, test_int_data, COUNT_OF(test_int_data)))
|
if(!flipper_format_write_int32(file, test_int_key, test_int_data, COUNT_OF(test_int_data)))
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -8,12 +8,35 @@
|
|||||||
#include <flipper_format/flipper_format.h>
|
#include <flipper_format/flipper_format.h>
|
||||||
|
|
||||||
#define TAG "Skylanders"
|
#define TAG "Skylanders"
|
||||||
|
#define POLY UINT64_C(0x42f0e1eba9ea3693)
|
||||||
|
#define TOP UINT64_C(0x800000000000)
|
||||||
|
#define UID_LEN 4
|
||||||
|
#define KEY_MASK 0xFFFFFFFFFFFF
|
||||||
|
|
||||||
static const uint64_t skylanders_key = 0x4b0b20107ccb;
|
static const uint64_t skylanders_key = 0x4b0b20107ccb;
|
||||||
|
|
||||||
static const char* nfc_resources_header = "Flipper NFC resources";
|
static const char* nfc_resources_header = "Flipper NFC resources";
|
||||||
static const uint32_t nfc_resources_file_version = 1;
|
static const uint32_t nfc_resources_file_version = 1;
|
||||||
|
|
||||||
|
uint64_t crc64_like(uint64_t result, uint8_t sector) {
|
||||||
|
result ^= (uint64_t)sector << 40;
|
||||||
|
for(int i = 0; i < 8; i++) {
|
||||||
|
result = (result & TOP) ? (result << 1) ^ POLY : result << 1;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t taghash(uint32_t uid) {
|
||||||
|
uint64_t result = 0x9AE903260CC4;
|
||||||
|
uint8_t uidBytes[UID_LEN] = {0};
|
||||||
|
memcpy(uidBytes, &uid, UID_LEN);
|
||||||
|
|
||||||
|
for(int i = 0; i < UID_LEN; i++) {
|
||||||
|
result = crc64_like(result, uidBytes[i]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static bool skylanders_search_data(
|
static bool skylanders_search_data(
|
||||||
Storage* storage,
|
Storage* storage,
|
||||||
const char* file_name,
|
const char* file_name,
|
||||||
@@ -88,6 +111,12 @@ static bool skylanders_read(Nfc* nfc, NfcDevice* device) {
|
|||||||
MfClassicData* data = mf_classic_alloc();
|
MfClassicData* data = mf_classic_alloc();
|
||||||
nfc_device_copy_data(device, NfcProtocolMfClassic, data);
|
nfc_device_copy_data(device, NfcProtocolMfClassic, data);
|
||||||
|
|
||||||
|
size_t* uid_len = 0;
|
||||||
|
const uint8_t* uid_bytes = mf_classic_get_uid(data, uid_len);
|
||||||
|
uint32_t uid = 0;
|
||||||
|
memcpy(&uid, uid_bytes, sizeof(uid));
|
||||||
|
uint64_t hash = taghash(uid);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
MfClassicType type = MfClassicType1k;
|
MfClassicType type = MfClassicType1k;
|
||||||
MfClassicError error = mf_classic_poller_sync_detect_type(nfc, &type);
|
MfClassicError error = mf_classic_poller_sync_detect_type(nfc, &type);
|
||||||
@@ -96,11 +125,19 @@ static bool skylanders_read(Nfc* nfc, NfcDevice* device) {
|
|||||||
data->type = type;
|
data->type = type;
|
||||||
MfClassicDeviceKeys keys = {};
|
MfClassicDeviceKeys keys = {};
|
||||||
for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) {
|
for(size_t i = 0; i < mf_classic_get_total_sectors_num(data->type); i++) {
|
||||||
|
if(i == 0) {
|
||||||
bit_lib_num_to_bytes_be(skylanders_key, sizeof(MfClassicKey), keys.key_a[i].data);
|
bit_lib_num_to_bytes_be(skylanders_key, sizeof(MfClassicKey), keys.key_a[i].data);
|
||||||
FURI_BIT_SET(keys.key_a_mask, i);
|
FURI_BIT_SET(keys.key_a_mask, i);
|
||||||
bit_lib_num_to_bytes_be(skylanders_key, sizeof(MfClassicKey), keys.key_b[i].data);
|
} else {
|
||||||
|
uint64_t sectorhash = crc64_like(hash, i);
|
||||||
|
uint64_t key = sectorhash & KEY_MASK;
|
||||||
|
uint8_t* keyBytes = (uint8_t*)&key;
|
||||||
|
memcpy(keys.key_a[i].data, keyBytes, sizeof(MfClassicKey));
|
||||||
|
FURI_BIT_SET(keys.key_a_mask, i);
|
||||||
|
memset(keys.key_b[i].data, 0, sizeof(MfClassicKey));
|
||||||
FURI_BIT_SET(keys.key_b_mask, i);
|
FURI_BIT_SET(keys.key_b_mask, i);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
error = mf_classic_poller_sync_read(nfc, &keys, data);
|
error = mf_classic_poller_sync_read(nfc, &keys, data);
|
||||||
if(error != MfClassicErrorNone) {
|
if(error != MfClassicErrorNone) {
|
||||||
@@ -134,7 +171,7 @@ static bool skylanders_parse(const NfcDevice* device, FuriString* parsed_data) {
|
|||||||
uint64_t key = bit_lib_bytes_to_num_be(sec_tr->key_a.data, 6);
|
uint64_t key = bit_lib_bytes_to_num_be(sec_tr->key_a.data, 6);
|
||||||
if(key != skylanders_key) break;
|
if(key != skylanders_key) break;
|
||||||
|
|
||||||
const uint16_t id = (uint16_t)*data->block[1].data;
|
const uint16_t id = data->block[1].data[1] << 8 | data->block[1].data[0];
|
||||||
if(id == 0) break;
|
if(id == 0) break;
|
||||||
|
|
||||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@darkflippers/fz-sdk-ul",
|
"name": "@darkflippers/fz-sdk-ul",
|
||||||
"version": "0.1.2",
|
"version": "0.1.3",
|
||||||
"description": "Type declarations and documentation for native JS modules available on Unleashed Custom Firmware for Flipper Zero",
|
"description": "Type declarations and documentation for native JS modules available on Unleashed Custom Firmware for Flipper Zero",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"unleashed",
|
"unleashed",
|
||||||
|
|||||||
@@ -8,13 +8,6 @@ importers:
|
|||||||
|
|
||||||
.:
|
.:
|
||||||
dependencies:
|
dependencies:
|
||||||
prompts:
|
|
||||||
specifier: ^2.4.2
|
|
||||||
version: 2.4.2
|
|
||||||
serialport:
|
|
||||||
specifier: ^12.0.0
|
|
||||||
version: 12.0.0
|
|
||||||
devDependencies:
|
|
||||||
esbuild:
|
esbuild:
|
||||||
specifier: ^0.24.0
|
specifier: ^0.24.0
|
||||||
version: 0.24.0
|
version: 0.24.0
|
||||||
@@ -24,6 +17,12 @@ importers:
|
|||||||
json5:
|
json5:
|
||||||
specifier: ^2.2.3
|
specifier: ^2.2.3
|
||||||
version: 2.2.3
|
version: 2.2.3
|
||||||
|
prompts:
|
||||||
|
specifier: ^2.4.2
|
||||||
|
version: 2.4.2
|
||||||
|
serialport:
|
||||||
|
specifier: ^12.0.0
|
||||||
|
version: 12.0.0
|
||||||
typedoc:
|
typedoc:
|
||||||
specifier: ^0.26.10
|
specifier: ^0.26.10
|
||||||
version: 0.26.10(typescript@5.6.3)
|
version: 0.26.10(typescript@5.6.3)
|
||||||
|
|||||||
@@ -91,9 +91,21 @@ async function build(config) {
|
|||||||
|
|
||||||
async function upload(config) {
|
async function upload(config) {
|
||||||
const appFile = fs.readFileSync(config.input, "utf8");
|
const appFile = fs.readFileSync(config.input, "utf8");
|
||||||
const flippers = (await SerialPort.list()).filter(x => x.serialNumber?.startsWith("flip_"));
|
const serialPorts = await SerialPort.list();
|
||||||
|
|
||||||
if (!flippers) {
|
let flippers = serialPorts
|
||||||
|
.filter(x => x.serialNumber?.startsWith("flip_"))
|
||||||
|
.map(x => ({ path: x.path, name: x.serialNumber.replace("flip_", "") }));
|
||||||
|
|
||||||
|
if (!flippers.length) {
|
||||||
|
// some Windows installations don't report the serial number correctly;
|
||||||
|
// filter by STM VCP VID:PID instead
|
||||||
|
flippers = serialPorts
|
||||||
|
.filter(x => x?.vendorId === "0483" && x?.productId === "5740")
|
||||||
|
.map(x => ({ path: x.path, name: x.path }));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!flippers.length) {
|
||||||
console.error("No Flippers found");
|
console.error("No Flippers found");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
assets/dolphin/external/L1_Happy_holidays_128x64/frame_0.png
vendored
Executable file
|
After Width: | Height: | Size: 858 B |
BIN
assets/dolphin/external/L1_Happy_holidays_128x64/frame_1.png
vendored
Executable file
|
After Width: | Height: | Size: 855 B |
BIN
assets/dolphin/external/L1_Happy_holidays_128x64/frame_10.png
vendored
Executable file
|
After Width: | Height: | Size: 872 B |
BIN
assets/dolphin/external/L1_Happy_holidays_128x64/frame_11.png
vendored
Executable file
|
After Width: | Height: | Size: 861 B |
BIN
assets/dolphin/external/L1_Happy_holidays_128x64/frame_12.png
vendored
Executable file
|
After Width: | Height: | Size: 853 B |
BIN
assets/dolphin/external/L1_Happy_holidays_128x64/frame_2.png
vendored
Executable file
|
After Width: | Height: | Size: 851 B |
BIN
assets/dolphin/external/L1_Happy_holidays_128x64/frame_3.png
vendored
Executable file
|
After Width: | Height: | Size: 852 B |
BIN
assets/dolphin/external/L1_Happy_holidays_128x64/frame_4.png
vendored
Executable file
|
After Width: | Height: | Size: 856 B |
BIN
assets/dolphin/external/L1_Happy_holidays_128x64/frame_5.png
vendored
Executable file
|
After Width: | Height: | Size: 850 B |
BIN
assets/dolphin/external/L1_Happy_holidays_128x64/frame_6.png
vendored
Executable file
|
After Width: | Height: | Size: 851 B |
BIN
assets/dolphin/external/L1_Happy_holidays_128x64/frame_7.png
vendored
Executable file
|
After Width: | Height: | Size: 860 B |
BIN
assets/dolphin/external/L1_Happy_holidays_128x64/frame_8.png
vendored
Executable file
|
After Width: | Height: | Size: 857 B |
BIN
assets/dolphin/external/L1_Happy_holidays_128x64/frame_9.png
vendored
Executable file
|
After Width: | Height: | Size: 863 B |
23
assets/dolphin/external/L1_Happy_holidays_128x64/meta.txt
vendored
Executable file
@@ -0,0 +1,23 @@
|
|||||||
|
Filetype: Flipper Animation
|
||||||
|
Version: 1
|
||||||
|
|
||||||
|
Width: 128
|
||||||
|
Height: 64
|
||||||
|
Passive frames: 10
|
||||||
|
Active frames: 18
|
||||||
|
Frames order: 0 1 2 1 0 1 2 1 0 1 2 3 4 5 6 5 4 7 2 8 9 10 11 10 9 10 11 12
|
||||||
|
Active cycles: 1
|
||||||
|
Frame rate: 2
|
||||||
|
Duration: 3600
|
||||||
|
Active cooldown: 7
|
||||||
|
|
||||||
|
Bubble slots: 1
|
||||||
|
|
||||||
|
Slot: 0
|
||||||
|
X: 11
|
||||||
|
Y: 19
|
||||||
|
Text: HAPPY\nHOLIDAYS!
|
||||||
|
AlignH: Right
|
||||||
|
AlignV: Center
|
||||||
|
StartFrame: 22
|
||||||
|
EndFrame: 27
|
||||||
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_0.png
vendored
Executable file
|
After Width: | Height: | Size: 820 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_1.png
vendored
Executable file
|
After Width: | Height: | Size: 881 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_10.png
vendored
Executable file
|
After Width: | Height: | Size: 788 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_11.png
vendored
Executable file
|
After Width: | Height: | Size: 816 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_12.png
vendored
Executable file
|
After Width: | Height: | Size: 864 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_13.png
vendored
Executable file
|
After Width: | Height: | Size: 798 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_14.png
vendored
Executable file
|
After Width: | Height: | Size: 813 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_15.png
vendored
Executable file
|
After Width: | Height: | Size: 879 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_16.png
vendored
Executable file
|
After Width: | Height: | Size: 855 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_17.png
vendored
Executable file
|
After Width: | Height: | Size: 772 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_18.png
vendored
Executable file
|
After Width: | Height: | Size: 817 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_19.png
vendored
Executable file
|
After Width: | Height: | Size: 867 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_2.png
vendored
Executable file
|
After Width: | Height: | Size: 866 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_20.png
vendored
Executable file
|
After Width: | Height: | Size: 809 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_21.png
vendored
Executable file
|
After Width: | Height: | Size: 795 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_22.png
vendored
Executable file
|
After Width: | Height: | Size: 870 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_23.png
vendored
Executable file
|
After Width: | Height: | Size: 852 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_24.png
vendored
Executable file
|
After Width: | Height: | Size: 805 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_25.png
vendored
Executable file
|
After Width: | Height: | Size: 858 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_26.png
vendored
Executable file
|
After Width: | Height: | Size: 830 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_27.png
vendored
Executable file
|
After Width: | Height: | Size: 828 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_28.png
vendored
Executable file
|
After Width: | Height: | Size: 585 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_29.png
vendored
Executable file
|
After Width: | Height: | Size: 431 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_3.png
vendored
Executable file
|
After Width: | Height: | Size: 812 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_30.png
vendored
Executable file
|
After Width: | Height: | Size: 281 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_31.png
vendored
Executable file
|
After Width: | Height: | Size: 270 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_32.png
vendored
Executable file
|
After Width: | Height: | Size: 236 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_33.png
vendored
Executable file
|
After Width: | Height: | Size: 485 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_34.png
vendored
Executable file
|
After Width: | Height: | Size: 771 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_35.png
vendored
Executable file
|
After Width: | Height: | Size: 887 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_36.png
vendored
Executable file
|
After Width: | Height: | Size: 809 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_4.png
vendored
Executable file
|
After Width: | Height: | Size: 890 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_5.png
vendored
Executable file
|
After Width: | Height: | Size: 819 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_6.png
vendored
Executable file
|
After Width: | Height: | Size: 799 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_7.png
vendored
Executable file
|
After Width: | Height: | Size: 817 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_8.png
vendored
Executable file
|
After Width: | Height: | Size: 875 B |
BIN
assets/dolphin/external/L1_Sleigh_ride_128x64/frame_9.png
vendored
Executable file
|
After Width: | Height: | Size: 823 B |
23
assets/dolphin/external/L1_Sleigh_ride_128x64/meta.txt
vendored
Executable file
@@ -0,0 +1,23 @@
|
|||||||
|
Filetype: Flipper Animation
|
||||||
|
Version: 1
|
||||||
|
|
||||||
|
Width: 128
|
||||||
|
Height: 64
|
||||||
|
Passive frames: 18
|
||||||
|
Active frames: 19
|
||||||
|
Frames order: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
|
||||||
|
Active cycles: 1
|
||||||
|
Frame rate: 2
|
||||||
|
Duration: 3600
|
||||||
|
Active cooldown: 7
|
||||||
|
|
||||||
|
Bubble slots: 1
|
||||||
|
|
||||||
|
Slot: 0
|
||||||
|
X: 21
|
||||||
|
Y: 25
|
||||||
|
Text: AAAAaAAAAHHh!!
|
||||||
|
AlignH: Right
|
||||||
|
AlignV: Bottom
|
||||||
|
StartFrame: 30
|
||||||
|
EndFrame: 32
|
||||||
20
assets/dolphin/external/manifest.txt
vendored
@@ -195,21 +195,35 @@ Min butthurt: 0
|
|||||||
Max butthurt: 8
|
Max butthurt: 8
|
||||||
Min level: 1
|
Min level: 1
|
||||||
Max level: 3
|
Max level: 3
|
||||||
Weight: 4
|
Weight: 3
|
||||||
|
|
||||||
Name: L3_Intruder_alert_128x64
|
Name: L3_Intruder_alert_128x64
|
||||||
Min butthurt: 0
|
Min butthurt: 0
|
||||||
Max butthurt: 12
|
Max butthurt: 12
|
||||||
Min level: 3
|
Min level: 3
|
||||||
Max level: 3
|
Max level: 3
|
||||||
Weight: 4
|
Weight: 3
|
||||||
|
|
||||||
Name: L1_Procrastinating_128x64
|
Name: L1_Procrastinating_128x64
|
||||||
Min butthurt: 0
|
Min butthurt: 0
|
||||||
Max butthurt: 8
|
Max butthurt: 8
|
||||||
Min level: 1
|
Min level: 1
|
||||||
Max level: 3
|
Max level: 3
|
||||||
Weight: 6
|
Weight: 3
|
||||||
|
|
||||||
|
Name: L1_Happy_holidays_128x64
|
||||||
|
Min butthurt: 0
|
||||||
|
Max butthurt: 14
|
||||||
|
Min level: 1
|
||||||
|
Max level: 3
|
||||||
|
Weight: 4
|
||||||
|
|
||||||
|
Name: L1_Sleigh_ride_128x64
|
||||||
|
Min butthurt: 0
|
||||||
|
Max butthurt: 14
|
||||||
|
Min level: 1
|
||||||
|
Max level: 3
|
||||||
|
Weight: 4
|
||||||
|
|
||||||
Name: L3_Fireplace_128x64
|
Name: L3_Fireplace_128x64
|
||||||
Min butthurt: 0
|
Min butthurt: 0
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ env = ENV.Clone(
|
|||||||
TARGETS_ROOT=Dir("#/targets"),
|
TARGETS_ROOT=Dir("#/targets"),
|
||||||
LINT_SOURCES=[
|
LINT_SOURCES=[
|
||||||
Dir("applications"),
|
Dir("applications"),
|
||||||
|
# Not C code
|
||||||
|
Dir("!applications/system/js_app/packages"),
|
||||||
],
|
],
|
||||||
LIBPATH=[
|
LIBPATH=[
|
||||||
"${LIB_DIST_DIR}",
|
"${LIB_DIST_DIR}",
|
||||||
|
|||||||
@@ -157,6 +157,7 @@ static BleEventAckStatus ble_svc_hid_event_handler(void* event, void* context) {
|
|||||||
hci_event_pckt* event_pckt = (hci_event_pckt*)(((hci_uart_pckt*)event)->data);
|
hci_event_pckt* event_pckt = (hci_event_pckt*)(((hci_uart_pckt*)event)->data);
|
||||||
evt_blecore_aci* blecore_evt = (evt_blecore_aci*)event_pckt->data;
|
evt_blecore_aci* blecore_evt = (evt_blecore_aci*)event_pckt->data;
|
||||||
// aci_gatt_attribute_modified_event_rp0* attribute_modified;
|
// aci_gatt_attribute_modified_event_rp0* attribute_modified;
|
||||||
|
|
||||||
if(event_pckt->evt == HCI_VENDOR_SPECIFIC_DEBUG_EVT_CODE) {
|
if(event_pckt->evt == HCI_VENDOR_SPECIFIC_DEBUG_EVT_CODE) {
|
||||||
if(blecore_evt->ecode == ACI_GATT_ATTRIBUTE_MODIFIED_VSEVT_CODE) {
|
if(blecore_evt->ecode == ACI_GATT_ATTRIBUTE_MODIFIED_VSEVT_CODE) {
|
||||||
// Process modification events
|
// Process modification events
|
||||||
@@ -274,6 +275,7 @@ bool ble_svc_hid_update_input_report(
|
|||||||
.data_ptr = data,
|
.data_ptr = data,
|
||||||
.data_len = len,
|
.data_len = len,
|
||||||
};
|
};
|
||||||
|
|
||||||
return ble_gatt_characteristic_update(
|
return ble_gatt_characteristic_update(
|
||||||
hid_svc->svc_handle, &hid_svc->input_report_chars[input_report_num], &report_data);
|
hid_svc->svc_handle, &hid_svc->input_report_chars[input_report_num], &report_data);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -403,6 +403,11 @@ bool flipper_format_write_comment_cstr(FlipperFormat* flipper_format, const char
|
|||||||
return flipper_format_stream_write_comment_cstr(flipper_format->stream, data);
|
return flipper_format_stream_write_comment_cstr(flipper_format->stream, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool flipper_format_write_empty_line(FlipperFormat* flipper_format) {
|
||||||
|
furi_check(flipper_format);
|
||||||
|
return flipper_format_stream_write_eol(flipper_format->stream);
|
||||||
|
}
|
||||||
|
|
||||||
bool flipper_format_delete_key(FlipperFormat* flipper_format, const char* key) {
|
bool flipper_format_delete_key(FlipperFormat* flipper_format, const char* key) {
|
||||||
furi_check(flipper_format);
|
furi_check(flipper_format);
|
||||||
FlipperStreamWriteData write_data = {
|
FlipperStreamWriteData write_data = {
|
||||||
|
|||||||
@@ -518,6 +518,14 @@ bool flipper_format_write_comment(FlipperFormat* flipper_format, FuriString* dat
|
|||||||
*/
|
*/
|
||||||
bool flipper_format_write_comment_cstr(FlipperFormat* flipper_format, const char* data);
|
bool flipper_format_write_comment_cstr(FlipperFormat* flipper_format, const char* data);
|
||||||
|
|
||||||
|
/** Write empty line (Improves readability for human based parsing)
|
||||||
|
*
|
||||||
|
* @param flipper_format Pointer to a FlipperFormat instance
|
||||||
|
*
|
||||||
|
* @return True on success
|
||||||
|
*/
|
||||||
|
bool flipper_format_write_empty_line(FlipperFormat* flipper_format);
|
||||||
|
|
||||||
/** Removes the first matching key and its value. Sets the RW pointer to a
|
/** Removes the first matching key and its value. Sets the RW pointer to a
|
||||||
* position of deleted data.
|
* position of deleted data.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ static void mf_plus_poller_set_callback(
|
|||||||
|
|
||||||
static NfcCommand mf_plus_poller_run(NfcGenericEvent event, void* context) {
|
static NfcCommand mf_plus_poller_run(NfcGenericEvent event, void* context) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
furi_assert(event.protocol = NfcProtocolIso14443_4a);
|
furi_assert(event.protocol == NfcProtocolIso14443_4a);
|
||||||
furi_assert(event.event_data);
|
furi_assert(event.event_data);
|
||||||
|
|
||||||
MfPlusPoller* instance = context;
|
MfPlusPoller* instance = context;
|
||||||
@@ -178,7 +178,7 @@ void mf_plus_poller_free(MfPlusPoller* instance) {
|
|||||||
|
|
||||||
static bool mf_plus_poller_detect(NfcGenericEvent event, void* context) {
|
static bool mf_plus_poller_detect(NfcGenericEvent event, void* context) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
furi_assert(event.protocol = NfcProtocolIso14443_4a);
|
furi_assert(event.protocol == NfcProtocolIso14443_4a);
|
||||||
furi_assert(event.event_data);
|
furi_assert(event.event_data);
|
||||||
|
|
||||||
MfPlusPoller* instance = context;
|
MfPlusPoller* instance = context;
|
||||||
|
|||||||
@@ -314,8 +314,8 @@ SubGhzProtocolStatus
|
|||||||
flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1);
|
flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1);
|
||||||
|
|
||||||
if(!subghz_protocol_encoder_bin_raw_get_upload(instance)) {
|
if(!subghz_protocol_encoder_bin_raw_get_upload(instance)) {
|
||||||
break;
|
|
||||||
res = SubGhzProtocolStatusErrorEncoderGetUpload;
|
res = SubGhzProtocolStatusErrorEncoderGetUpload;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
instance->encoder.is_running = true;
|
instance->encoder.is_running = true;
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,11 @@ def get_commit_json(event):
|
|||||||
commit_url = event["pull_request"]["base"]["repo"]["commits_url"].replace(
|
commit_url = event["pull_request"]["base"]["repo"]["commits_url"].replace(
|
||||||
"{/sha}", f"/{event['pull_request']['head']['sha']}"
|
"{/sha}", f"/{event['pull_request']['head']['sha']}"
|
||||||
)
|
)
|
||||||
with urllib.request.urlopen(commit_url, context=context) as commit_file:
|
request = urllib.request.Request(commit_url)
|
||||||
|
if "GH_TOKEN" in os.environ:
|
||||||
|
request.add_header("Authorization", "Bearer %s" % (os.environ["GH_TOKEN"]))
|
||||||
|
|
||||||
|
with urllib.request.urlopen(request, context=context) as commit_file:
|
||||||
commit_json = json.loads(commit_file.read().decode("utf-8"))
|
commit_json = json.loads(commit_file.read().decode("utf-8"))
|
||||||
return commit_json
|
return commit_json
|
||||||
|
|
||||||
|
|||||||
@@ -35,21 +35,25 @@ class Main(App):
|
|||||||
self.parser_format.set_defaults(func=self.format)
|
self.parser_format.set_defaults(func=self.format)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _filter_lint_directories(dirnames: list[str]):
|
def _filter_lint_directories(
|
||||||
|
dirpath: str, dirnames: list[str], excludes: tuple[str]
|
||||||
|
):
|
||||||
# Skipping 3rd-party code - usually resides in subfolder "lib"
|
# Skipping 3rd-party code - usually resides in subfolder "lib"
|
||||||
if "lib" in dirnames:
|
if "lib" in dirnames:
|
||||||
dirnames.remove("lib")
|
dirnames.remove("lib")
|
||||||
# Skipping hidden folders
|
# Skipping hidden and excluded folders
|
||||||
for dirname in dirnames.copy():
|
for dirname in dirnames.copy():
|
||||||
if dirname.startswith("."):
|
if dirname.startswith("."):
|
||||||
dirnames.remove(dirname)
|
dirnames.remove(dirname)
|
||||||
|
if os.path.join(dirpath, dirname).startswith(excludes):
|
||||||
|
dirnames.remove(dirname)
|
||||||
|
|
||||||
def _check_folders(self, folders: list):
|
def _check_folders(self, folders: list, excludes: tuple[str]):
|
||||||
show_message = False
|
show_message = False
|
||||||
pattern = re.compile(SOURCE_CODE_DIR_PATTERN)
|
pattern = re.compile(SOURCE_CODE_DIR_PATTERN)
|
||||||
for folder in folders:
|
for folder in folders:
|
||||||
for dirpath, dirnames, filenames in os.walk(folder):
|
for dirpath, dirnames, filenames in os.walk(folder):
|
||||||
self._filter_lint_directories(dirnames)
|
self._filter_lint_directories(dirpath, dirnames, excludes)
|
||||||
|
|
||||||
for dirname in dirnames:
|
for dirname in dirnames:
|
||||||
if not pattern.match(dirname):
|
if not pattern.match(dirname):
|
||||||
@@ -61,11 +65,11 @@ class Main(App):
|
|||||||
"Folders are not renamed automatically, please fix it by yourself"
|
"Folders are not renamed automatically, please fix it by yourself"
|
||||||
)
|
)
|
||||||
|
|
||||||
def _find_sources(self, folders: list):
|
def _find_sources(self, folders: list, excludes: tuple[str]):
|
||||||
output = []
|
output = []
|
||||||
for folder in folders:
|
for folder in folders:
|
||||||
for dirpath, dirnames, filenames in os.walk(folder):
|
for dirpath, dirnames, filenames in os.walk(folder):
|
||||||
self._filter_lint_directories(dirnames)
|
self._filter_lint_directories(dirpath, dirnames, excludes)
|
||||||
|
|
||||||
for filename in filenames:
|
for filename in filenames:
|
||||||
ext = os.path.splitext(filename.lower())[1]
|
ext = os.path.splitext(filename.lower())[1]
|
||||||
@@ -168,14 +172,20 @@ class Main(App):
|
|||||||
|
|
||||||
def _perform(self, dry_run: bool):
|
def _perform(self, dry_run: bool):
|
||||||
result = 0
|
result = 0
|
||||||
sources = self._find_sources(self.args.input)
|
excludes = []
|
||||||
|
for folder in self.args.input.copy():
|
||||||
|
if folder.startswith("!"):
|
||||||
|
excludes.append(folder.removeprefix("!"))
|
||||||
|
self.args.input.remove(folder)
|
||||||
|
excludes = tuple(excludes)
|
||||||
|
sources = self._find_sources(self.args.input, excludes)
|
||||||
if not self._format_sources(sources, dry_run=dry_run):
|
if not self._format_sources(sources, dry_run=dry_run):
|
||||||
result |= 0b001
|
result |= 0b001
|
||||||
if not self._apply_file_naming_convention(sources, dry_run=dry_run):
|
if not self._apply_file_naming_convention(sources, dry_run=dry_run):
|
||||||
result |= 0b010
|
result |= 0b010
|
||||||
if not self._apply_file_permissions(sources, dry_run=dry_run):
|
if not self._apply_file_permissions(sources, dry_run=dry_run):
|
||||||
result |= 0b100
|
result |= 0b100
|
||||||
self._check_folders(self.args.input)
|
self._check_folders(self.args.input, excludes)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def check(self):
|
def check(self):
|
||||||
|
|||||||
@@ -46,7 +46,8 @@ if (Test-Path -LiteralPath "$toolchain_dist_temp_path") {
|
|||||||
Write-Host -NoNewline "Extracting Windows toolchain.."
|
Write-Host -NoNewline "Extracting Windows toolchain.."
|
||||||
# This is faster than Expand-Archive
|
# This is faster than Expand-Archive
|
||||||
Add-Type -Assembly "System.IO.Compression.Filesystem"
|
Add-Type -Assembly "System.IO.Compression.Filesystem"
|
||||||
[System.IO.Compression.ZipFile]::ExtractToDirectory("$toolchain_zip_temp_path", "$download_dir")
|
Add-Type -Assembly "System.Text.Encoding"
|
||||||
|
[System.IO.Compression.ZipFile]::ExtractToDirectory("$toolchain_zip_temp_path", "$download_dir", [System.Text.Encoding]::UTF8)
|
||||||
# Expand-Archive -LiteralPath "$toolchain_zip_temp_path" -DestinationPath "$download_dir"
|
# Expand-Archive -LiteralPath "$toolchain_zip_temp_path" -DestinationPath "$download_dir"
|
||||||
|
|
||||||
Write-Host -NoNewline "moving.."
|
Write-Host -NoNewline "moving.."
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
entry,status,name,type,params
|
entry,status,name,type,params
|
||||||
Version,+,79.0,,
|
Version,+,79.1,,
|
||||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||||
Header,+,applications/services/bt/bt_service/bt_keys_storage.h,,
|
Header,+,applications/services/bt/bt_service/bt_keys_storage.h,,
|
||||||
Header,+,applications/services/cli/cli.h,,
|
Header,+,applications/services/cli/cli.h,,
|
||||||
@@ -1054,6 +1054,7 @@ Function,+,flipper_format_update_uint32,_Bool,"FlipperFormat*, const char*, cons
|
|||||||
Function,+,flipper_format_write_bool,_Bool,"FlipperFormat*, const char*, const _Bool*, const uint16_t"
|
Function,+,flipper_format_write_bool,_Bool,"FlipperFormat*, const char*, const _Bool*, const uint16_t"
|
||||||
Function,+,flipper_format_write_comment,_Bool,"FlipperFormat*, FuriString*"
|
Function,+,flipper_format_write_comment,_Bool,"FlipperFormat*, FuriString*"
|
||||||
Function,+,flipper_format_write_comment_cstr,_Bool,"FlipperFormat*, const char*"
|
Function,+,flipper_format_write_comment_cstr,_Bool,"FlipperFormat*, const char*"
|
||||||
|
Function,+,flipper_format_write_empty_line,_Bool,FlipperFormat*
|
||||||
Function,+,flipper_format_write_float,_Bool,"FlipperFormat*, const char*, const float*, const uint16_t"
|
Function,+,flipper_format_write_float,_Bool,"FlipperFormat*, const char*, const float*, const uint16_t"
|
||||||
Function,+,flipper_format_write_header,_Bool,"FlipperFormat*, FuriString*, const uint32_t"
|
Function,+,flipper_format_write_header,_Bool,"FlipperFormat*, FuriString*, const uint32_t"
|
||||||
Function,+,flipper_format_write_header_cstr,_Bool,"FlipperFormat*, const char*, const uint32_t"
|
Function,+,flipper_format_write_header_cstr,_Bool,"FlipperFormat*, const char*, const uint32_t"
|
||||||
|
|||||||
|
@@ -1,5 +1,5 @@
|
|||||||
entry,status,name,type,params
|
entry,status,name,type,params
|
||||||
Version,+,79.0,,
|
Version,+,79.1,,
|
||||||
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
|
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
|
||||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||||
Header,+,applications/services/bt/bt_service/bt_keys_storage.h,,
|
Header,+,applications/services/bt/bt_service/bt_keys_storage.h,,
|
||||||
@@ -1194,6 +1194,7 @@ Function,+,flipper_format_update_uint32,_Bool,"FlipperFormat*, const char*, cons
|
|||||||
Function,+,flipper_format_write_bool,_Bool,"FlipperFormat*, const char*, const _Bool*, const uint16_t"
|
Function,+,flipper_format_write_bool,_Bool,"FlipperFormat*, const char*, const _Bool*, const uint16_t"
|
||||||
Function,+,flipper_format_write_comment,_Bool,"FlipperFormat*, FuriString*"
|
Function,+,flipper_format_write_comment,_Bool,"FlipperFormat*, FuriString*"
|
||||||
Function,+,flipper_format_write_comment_cstr,_Bool,"FlipperFormat*, const char*"
|
Function,+,flipper_format_write_comment_cstr,_Bool,"FlipperFormat*, const char*"
|
||||||
|
Function,+,flipper_format_write_empty_line,_Bool,FlipperFormat*
|
||||||
Function,+,flipper_format_write_float,_Bool,"FlipperFormat*, const char*, const float*, const uint16_t"
|
Function,+,flipper_format_write_float,_Bool,"FlipperFormat*, const char*, const float*, const uint16_t"
|
||||||
Function,+,flipper_format_write_header,_Bool,"FlipperFormat*, FuriString*, const uint32_t"
|
Function,+,flipper_format_write_header,_Bool,"FlipperFormat*, FuriString*, const uint32_t"
|
||||||
Function,+,flipper_format_write_header_cstr,_Bool,"FlipperFormat*, const char*, const uint32_t"
|
Function,+,flipper_format_write_header_cstr,_Bool,"FlipperFormat*, const char*, const uint32_t"
|
||||||
|
|||||||
|
@@ -7,6 +7,12 @@
|
|||||||
|
|
||||||
#define GATT_MIN_READ_KEY_SIZE (10)
|
#define GATT_MIN_READ_KEY_SIZE (10)
|
||||||
|
|
||||||
|
#ifdef BLE_GATT_STRICT
|
||||||
|
#define ble_gatt_strict_crash(message) furi_crash(message)
|
||||||
|
#else
|
||||||
|
#define ble_gatt_strict_crash(message)
|
||||||
|
#endif
|
||||||
|
|
||||||
void ble_gatt_characteristic_init(
|
void ble_gatt_characteristic_init(
|
||||||
uint16_t svc_handle,
|
uint16_t svc_handle,
|
||||||
const BleGattCharacteristicParams* char_descriptor,
|
const BleGattCharacteristicParams* char_descriptor,
|
||||||
@@ -42,6 +48,7 @@ void ble_gatt_characteristic_init(
|
|||||||
&char_instance->handle);
|
&char_instance->handle);
|
||||||
if(status) {
|
if(status) {
|
||||||
FURI_LOG_E(TAG, "Failed to add %s char: %d", char_descriptor->name, status);
|
FURI_LOG_E(TAG, "Failed to add %s char: %d", char_descriptor->name, status);
|
||||||
|
ble_gatt_strict_crash("Failed to add characteristic");
|
||||||
}
|
}
|
||||||
|
|
||||||
char_instance->descriptor_handle = 0;
|
char_instance->descriptor_handle = 0;
|
||||||
@@ -68,6 +75,7 @@ void ble_gatt_characteristic_init(
|
|||||||
&char_instance->descriptor_handle);
|
&char_instance->descriptor_handle);
|
||||||
if(status) {
|
if(status) {
|
||||||
FURI_LOG_E(TAG, "Failed to add %s char descriptor: %d", char_descriptor->name, status);
|
FURI_LOG_E(TAG, "Failed to add %s char descriptor: %d", char_descriptor->name, status);
|
||||||
|
ble_gatt_strict_crash("Failed to add characteristic descriptor");
|
||||||
}
|
}
|
||||||
if(release_data) {
|
if(release_data) {
|
||||||
free((void*)char_data);
|
free((void*)char_data);
|
||||||
@@ -82,6 +90,7 @@ void ble_gatt_characteristic_delete(
|
|||||||
if(status) {
|
if(status) {
|
||||||
FURI_LOG_E(
|
FURI_LOG_E(
|
||||||
TAG, "Failed to delete %s char: %d", char_instance->characteristic->name, status);
|
TAG, "Failed to delete %s char: %d", char_instance->characteristic->name, status);
|
||||||
|
ble_gatt_strict_crash("Failed to delete characteristic");
|
||||||
}
|
}
|
||||||
free((void*)char_instance->characteristic);
|
free((void*)char_instance->characteristic);
|
||||||
}
|
}
|
||||||
@@ -111,14 +120,27 @@ bool ble_gatt_characteristic_update(
|
|||||||
release_data = char_descriptor->data.callback.fn(context, &char_data, &char_data_size);
|
release_data = char_descriptor->data.callback.fn(context, &char_data, &char_data_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
tBleStatus result = aci_gatt_update_char_value(
|
tBleStatus result;
|
||||||
|
size_t retries_left = 1000;
|
||||||
|
do {
|
||||||
|
retries_left--;
|
||||||
|
result = aci_gatt_update_char_value(
|
||||||
svc_handle, char_instance->handle, 0, char_data_size, char_data);
|
svc_handle, char_instance->handle, 0, char_data_size, char_data);
|
||||||
if(result) {
|
if(result == BLE_STATUS_INSUFFICIENT_RESOURCES) {
|
||||||
FURI_LOG_E(TAG, "Failed updating %s characteristic: %d", char_descriptor->name, result);
|
FURI_LOG_W(TAG, "Insufficient resources for %s characteristic", char_descriptor->name);
|
||||||
|
furi_delay_ms(1);
|
||||||
}
|
}
|
||||||
|
} while(result == BLE_STATUS_INSUFFICIENT_RESOURCES && retries_left);
|
||||||
|
|
||||||
if(release_data) {
|
if(release_data) {
|
||||||
free((void*)char_data);
|
free((void*)char_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(result != BLE_STATUS_SUCCESS) {
|
||||||
|
FURI_LOG_E(TAG, "Failed updating %s characteristic: %d", char_descriptor->name, result);
|
||||||
|
ble_gatt_strict_crash("Failed to update characteristic");
|
||||||
|
}
|
||||||
|
|
||||||
return result != BLE_STATUS_SUCCESS;
|
return result != BLE_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,6 +154,7 @@ bool ble_gatt_service_add(
|
|||||||
Service_UUID_Type, Service_UUID, Service_Type, Max_Attribute_Records, Service_Handle);
|
Service_UUID_Type, Service_UUID, Service_Type, Max_Attribute_Records, Service_Handle);
|
||||||
if(result) {
|
if(result) {
|
||||||
FURI_LOG_E(TAG, "Failed to add service: %x", result);
|
FURI_LOG_E(TAG, "Failed to add service: %x", result);
|
||||||
|
ble_gatt_strict_crash("Failed to add service");
|
||||||
}
|
}
|
||||||
|
|
||||||
return result == BLE_STATUS_SUCCESS;
|
return result == BLE_STATUS_SUCCESS;
|
||||||
@@ -141,6 +164,7 @@ bool ble_gatt_service_delete(uint16_t svc_handle) {
|
|||||||
tBleStatus result = aci_gatt_del_service(svc_handle);
|
tBleStatus result = aci_gatt_del_service(svc_handle);
|
||||||
if(result) {
|
if(result) {
|
||||||
FURI_LOG_E(TAG, "Failed to delete service: %x", result);
|
FURI_LOG_E(TAG, "Failed to delete service: %x", result);
|
||||||
|
ble_gatt_strict_crash("Failed to delete service");
|
||||||
}
|
}
|
||||||
|
|
||||||
return result == BLE_STATUS_SUCCESS;
|
return result == BLE_STATUS_SUCCESS;
|
||||||
|
|||||||